How do I eliminate the "'str' object is not callable"? - python

I get the following error on the code below, and have no idea what is going on. I'm very much a beginner and need some help. I am trying to make a very basic game of tic-tac-toe in the console, and am having trouble.
Traceback (most recent call last):
File "D:/Eric/Projects/Tic Tac Toe/Tic Tac Toe.py", line 68, in <module>
printboard()
File "D:/Eric/Projects/Tic Tac Toe/Tic Tac Toe.py", line 15, in printboard
print("",c[0],"|",c[1],"|",c[2],"\n-----------\n",c[3],"|",c[4],"|",c[5],"\n-----------\n",c[6],"|",c[7],"|",c[8])
TypeError: 'str' object is not callable
Code:
import random, time
#Variables
c = [str(i) for i in range(1,10)] #Cells
cpuletter = "string input"
coinoptions = ["heads", "tails"]
coinflip = random.choice(coinoptions)
play = ""
playercell = 0
#Functions
def printboard(): #Prints the gameboard with the cell variables in the spaces
print("",c[0],"|",c[1],"|",c[2],"\n-----------\n",c[3],"|",c[4],"|",c[5],"\n-----------\n",c[6],"|",c[7],"|",c[8])
return
#Introduction
print("Welcome to Tic Tac Toe. Below is the playing table.") #Welcome + Explanation
printboard()
print("The playing spaces are numbered 1 through 9.\nYou will use these numbers to refer to the places you would like to play your piece.\n")
#X or O?
playerletter = input("Would you like to be X's or O's?\n")
playerletter = playerletter.capitalize()
playerletter = playerletter[0]
while playerletter not in ["X", "O"]: #Confirm choice == "X" or "O." If not, ask again.
playerletter = input("""Sorry, that's not a valid option. Please choose "X" or "O."\n""")
playerletter = playerletter.capitalize()
playerletter = playerletter[0]
if playerletter == "X":
cpuletter = "O"
elif playerletter == "O":
cpuletter = "X"
#Who goes first?
playercoin = input("Randomizing who goes first:\nDo you choose heads or tails?\n") #Asking for "heads" or "tails"
playercoin = playercoin.lower()
while playercoin not in ["heads", "tails"]: #Confirm choice == "Heads" or "Tails." If not, ask again.
playercoin = input("""Sorry, that's not a valid option. Please choose "heads" or "tails."\n""")
playercoin = playercoin.lower()
print("...")
time.sleep(1) #Waits 1 seconds
if coinflip != playercoin: #Tells player who goes first
print("It landed " + coinflip + "! I will go first.")
play = 0
elif coinflip == playercoin:
print("It landed " + coinflip + "! You will go first.")
play = 1
#Game
input("""Ready to play? Press "Enter" to begin!\n""")
if play == 0:
random_index = random.randrange(9) #Randomly selects a cell to change to cpuletter
c[random_index] = cpuletter
print = ("Here is my move.")
printboard()
elif play == 1: #Allows player to choose cell to change to playerletter
printboard()
playercell = int(input("It's your turn. Type a cell number to choose where you play.\n"))
playercell = playercell - 1
c[playercell] = playerletter
printboard()
Edit: Forgot to say that this only happens when the computer goes first, and not the player. I fixed the print = ("Here is my move.") but am still having problems.

print = "Here is my move."
That line reassigns the builtin print function to a string. Don't do that.

Why make such a complex printing function? Format would come very handy right about now:
def printboard(): #Prints the gameboard with the cell variables in the spaces
table = \
'''
{} | {} | {}
----------
{} | {} | {}
----------
{} | {} |
'''
print(table.format(c[1],c[2],c[3],c[4],c[5],c[6],c[7],c[8]))
return
And finally to fix your error, change line 65:
move = ("Here is my move")

I ran your code, but I did not get any errors. This particular TypeError is usually caused by programmers mistakenly switching out square brackets with parentheses (therefore "calling" it as if the string was a function, which it's not.). Please check and run your code again.
EDIT: Solution: Change the variable name of print = "Here is my move." on line 65 to something else, like movePrint = "Here is my move".

Related

Python doesn't take my input but there is no error (code continues running)

I continue learning the basics of Python by extending my TicTacToe game. It now lets the player choose difficulty. It seems that it works (finally), but sometimes I experience a strange issue.
Note that I use Google Colab (in case that is relevant).
This is a turn-based game, meaning I play my turn, then computer plays, then me etc until someone wins or we get to a tie (the order depends on what you input in the beginning, sometimes computer plays first). But sometimes, when I'm asked for my input and I give it, the input line disappears but nothing happens. My input is not shown on the board, the input line disappears, and the computer doesn't play because it's waiting for me to finish my turn. The code continues running (and Google Colab marks the code is currently at human_move(), meaning it's waiting for my input). It doesn't give an error message on its own, but see below for what's shown when I interrupt it manually.
I don't really know how to recreate the issue, other than playing many times in Colab (ony my own computer, the issue repeats almost always). So far it's happened on medium and hard difficulty. Here's how the last board looked when it got stuck (I played Os, computer played Xs). For my next move I pressed 4, then the input line disappeared without playing my move:
+-------+-------+-------+
| | | |
| O | 2 | 3 |
| | | |
+-------+-------+-------+
| | | |
| 4 | X | X |
| | | |
+-------+-------+-------+
| | | |
| 7 | 8 | O |
| | | |
+-------+-------+-------+
I'm attaching my full code. I know it's long and I'm sorry, but look below for an error message to maybe make it more clear.
# I need these functions to make everything work
from IPython.core.display import clear_output
from random import randrange
# Sets the board at the beginning
official_board = [1, 2, 3, 4, 5, 6, 7, 8, 9]
# Just displays the current board
def display_board(board):
print(
"\n+-------+-------+-------+",
"\n| | | |",
"\n| ",board[0]," | ",board[1]," | ",board[2]," |",
"\n| | | |",
"\n+-------+-------+-------+",
"\n| | | |",
"\n| ",board[3]," | ",board[4]," | ",board[5]," |",
"\n| | | |",
"\n+-------+-------+-------+",
"\n| | | |",
"\n| ",board[6]," | ",board[7]," | ",board[8]," |",
"\n| | | |",
"\n+-------+-------+-------+"
)
# Asks player to define who plays first (human or computer). Impacts the order of turns.
def who_plays_first():
global first_player
while True:
first_player = int(input("Choose who plays first: 1 for human, 2 for computer"))
if first_player == 1 or first_player == 2:
break
print("invalid input, read the instruction")
if first_player == 1:
first_player = "human"
else:
first_player = "computer"
return(first_player)
# Asks player to set difficulty. Impacts how computer decides on its move.
def choose_difficulty():
global difficulty
while True:
difficulty = int(input("Choose difficulty: 1 = easy, 2 = medium, 3 = hard"))
if difficulty == 1 or difficulty == 2 or difficulty == 3:
break
print("invalid input, read the instruction")
if difficulty == 1:
difficulty = "easy"
elif difficulty == 2:
difficulty = "medium"
else:
difficulty = "hard"
return(difficulty)
# Makes a list of free fields. Used in other functions.
def make_list_of_free_fields(board):
list_of_free_fields = []
for field in range(1,10):
if field in board:
list_of_free_fields.append(field)
return(list_of_free_fields)
# Checks whether the player (defined by the sign) won.
def victory_for(sign, board):
if (board[0] == sign and board[1] == sign and board[2] == sign or
board[3] == sign and board[4] == sign and board[5] == sign or
board[6] == sign and board[7] == sign and board[8] == sign or
board[0] == sign and board[3] == sign and board[6] == sign or
board[1] == sign and board[4] == sign and board[7] == sign or
board[2] == sign and board[5] == sign and board[8] == sign or
board[0] == sign and board[4] == sign and board[8] == sign or
board[2] == sign and board[4] == sign and board[6] == sign):
return True
else:
return False
# Asks the human player to make their move.
def human_move():
while True:
human_input = int(input("Choose a field"))
if human_input in make_list_of_free_fields(official_board):
break
print("You must choose one of the free fields on the board by typing 1-9")
official_board[human_input-1] = "O"
# This is how the computer makes its move.
# Depends on the difficulty.
def computer_move():
# This is how the computer plays on easy
if difficulty == "easy":
# Computer plays a random move out of the list of available fields
while True:
computer_input = randrange(10)
if computer_input in make_list_of_free_fields(official_board):
break
official_board[computer_input-1] = "X"
# this is how the computer plays on medium
# (or hard if less than 2 turns available for computer)
elif difficulty == "medium" or len(make_list_of_free_fields(official_board)) < 3:
# Check whether there's a (list of) move(s) that would guarantee computer victory
# if yes, play a random move out of that list and end the function
# if not, move to the next part of the function
brings_computer_victory = []
for field in make_list_of_free_fields(official_board):
temp_board = official_board[:]
temp_move = field
temp_board[temp_move-1] = "X"
if victory_for("X", temp_board) == True:
brings_computer_victory.append(temp_move)
if brings_computer_victory != []:
while True:
computer_input = randrange(10)
if computer_input in brings_computer_victory:
break
official_board[computer_input-1] = "X"
return
# Check whether there's a (list of) move(s) that would guarantee human victory
# Prevent human from winning by playing a random move out of that list and end function
# if there is no such move, move to the next part of the function
brings_human_victory = []
for field in make_list_of_free_fields(official_board):
temp_board = official_board[:]
temp_move = field
temp_board[temp_move-1] = "O"
if victory_for("O", temp_board) == True:
brings_human_victory.append(temp_move)
if brings_human_victory != []:
while True:
computer_input = randrange(10)
if computer_input in brings_human_victory:
break
official_board[computer_input-1] = "X"
return
# if you got to here, it means there were no moves that would
# guarantee computer or human victory, so
# play a random field as if you were playing on easy.
while True:
computer_input = randrange(10)
if computer_input in make_list_of_free_fields(official_board):
break
official_board[computer_input-1] = "X"
# this is how the computer plays on hard (assuming more than 2 turns available)
# the first part is the same as on medium, i.e.
# if it's possible to win, use to opportunity, if not
# check whether human will be able to win and stop him.
# if none of that is possible, don't play random (like on medium)
# but be smart (see further code and comments for details)
else:
# Check whether there's a (list of) move(s) that would guarantee computer victory
# if yes, play a random move out of that list and end the function
# if not, move to the next part of the function
brings_computer_victory = []
for field in make_list_of_free_fields(official_board):
temp_board = official_board[:]
temp_move = field
temp_board[temp_move-1] = "X"
if victory_for("X", temp_board) == True:
brings_computer_victory.append(temp_move)
if brings_computer_victory != []:
while True:
computer_input = randrange(10)
if computer_input in brings_computer_victory:
break
official_board[computer_input-1] = "X"
return
# Check whether there's a (list of) move(s) that would guarantee human victory
# Prevent human from winning by playing a random move out of that list and end function
# if there is no such move, move to the next part of the function
brings_human_victory = []
for field in make_list_of_free_fields(official_board):
temp_board = official_board[:]
temp_move = field
temp_board[temp_move-1] = "O"
if victory_for("O", temp_board) == True:
brings_human_victory.append(temp_move)
if brings_human_victory != []:
while True:
computer_input = randrange(10)
if computer_input in brings_human_victory:
break
official_board[computer_input-1] = "X"
return
# if you got to here, it means there were no moves that would
# guarantee computer or human victory, so we move to next step.
# We'll look two moves in advance to see if playing something now
# creates opportunities for later.
# We start by checking opportunities for the computer.
# We will have two new lists:
# a) one saying which moves give two winning options in the next turn.
# b) one saying which moves give one winning option in the next turn.
# if the list of moves giving 2 options is not empty, we randomly pick a move from there.
# else, if the list of moves with 1 option is not empty, we randomly draw from there.
# if we did one of the two previous options, we end the function.
# First, let's create the lists to determine which moves would give
# computer one or two winning options in the turn after.
gives_two_options = []
gives_one_option = []
for first_move in make_list_of_free_fields(official_board):
board_after_first_move = official_board[:]
board_after_first_move[first_move-1] = "X"
opportunities = 0
for second_move in make_list_of_free_fields(board_after_first_move):
board_after_second_move = board_after_first_move[:]
board_after_second_move[second_move-1] ="X"
if victory_for("X", board_after_second_move) == True:
opportunities += 1
if opportunities > 1:
gives_two_options.append(first_move)
if opportunities == 1:
gives_one_option.append(first_move)
# if there's a list of moves which would give computer two winning options,
# play a random move from that list and end function.
# If not, check whether there's list of moves which would give one
# winning option (and play randomly from there) and end function.
# If no such lists exist, go on with the code.
if gives_two_options != []:
while True:
computer_input = randrange(10)
if computer_input in gives_two_options:
break
official_board[computer_input-1] = "X"
return
if gives_one_option != []:
while True:
computer_input = randrange(10)
if computer_input in gives_one_option:
break
official_board[computer_input-1] = "X"
return
# if we're here, it means there were no good opportunities for computer.
# so let's check if there are any for the human, and then prevent them.
# Let's create the lists to determine which moves would give
# human one or two winning options in the turn after.
gives_two_options = []
gives_one_option = []
for first_move in make_list_of_free_fields(official_board):
board_after_first_move = official_board[:]
board_after_first_move[first_move-1] = "O"
opportunities = 0
for second_move in make_list_of_free_fields(board_after_first_move):
board_after_second_move = board_after_first_move[:]
board_after_second_move[second_move-1] ="O"
if victory_for("O", board_after_second_move) == True:
opportunities += 1
if opportunities > 1:
gives_two_options.append(first_move)
if opportunities == 1:
gives_one_option.append(first_move)
# if there's a list of moves which would give human two winning options,
# play a random move from that list and end function.
# If not, check whether there's list of moves which would give one
# winning option (and play randomly from there) and end function.
# If no such lists exist, go on with the code.
if gives_two_options != []:
while True:
computer_input = randrange(10)
if computer_input in gives_two_options:
break
official_board[computer_input-1] = "X"
return
if gives_one_option != []:
while True:
computer_input = randrange(10)
if computer_input in gives_one_option:
break
official_board[computer_input-1] = "X"
return
# if you got to here, it means there were no moves that would
# create meaningful opportunities for computer or the human, so
# play a random field as if you were playing on easy.
while True:
computer_input = randrange(10)
if computer_input in make_list_of_free_fields(official_board):
break
official_board[computer_input-1] = "X"
# This is the final piece of code that connects all the functions.
who_plays_first()
choose_difficulty()
clear_output()
if first_player == "human":
display_board(official_board)
while True:
human_move()
clear_output()
display_board(official_board)
if victory_for("O", official_board) == True:
print("You won!")
break
if len(make_list_of_free_fields(official_board)) == 0:
print("it's a tie")
break
computer_move()
clear_output()
display_board(official_board)
if victory_for("X", official_board) == True:
print("You lost!")
break
else:
while True:
computer_move()
clear_output()
display_board(official_board)
if victory_for("X", official_board) == True:
print("You lost!")
break
if len(make_list_of_free_fields(official_board)) == 0:
print("it's a tie")
break
human_move()
clear_output()
display_board(official_board)
if victory_for("O", official_board) == True:
print("You won!")
break
After further inspection and many tries to recreate the problem in Colab, I failed to reach anything. But then I decided to run the code on my own computer (Anaconda, Visual Studio Code, Jupiter, not sure if relevant). There, the problem occurs much more frequently (almost on every move I make). Python doesn't raise an error on its own, but the code seems to be stuck in a loop. When I stop it manually, I get this error:
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
c:\Users\Divo\Downloads\TicTacToe_2.ipynb Cell 10 in <cell line: 6>()
37 print("it's a tie")
38 break
---> 39 human_move()
40 clear_output()
41 display_board(official_board)
c:\Users\Divo\Downloads\TicTacToe_2.ipynb Cell 10 in human_move()
2 def human_move():
3 while True:
----> 4 human_input = int(input("Choose a field"))
5 if human_input in make_list_of_free_fields(official_board):
6 break
ValueError: invalid literal for int() with base 10: ''
The error tells you what is wrong, you are trying to parse something that can't be interpreted as an integer, in this case an empty string ''. It is generally very dangerous to parse human input as an integer, without first checking that it can actually be converted to an integer. First you could check if it is numeric, and then if it is in the desired range (and then that it is in a free spot, like you do):
if human_input.isnumeric():
if human_input in range(1, 10):

Why am i getting a error for putting a if statement in my function

racks = "1"
racksPerSecond = 0
gameScreenChoice1 = "Traffic Drugs (1) "
gameScreenChoice2 = "Get Slaves (2) "
print("You are NBA Young Boy (Never Broke Again)")
startScreen = input("To start your journey out the trenches press 1: ")
if startScreen == "1":
print("What do you want to do?")
waysToGetRacks = input(gameScreenChoice1 + gameScreenChoice2)
def TrafficDrugs(slaveQuestion1):
(
slaveQuestion1 == input(" Push P if you want a rack")
if TrafficDrugs(slaveQuestion1):
racks += "1"
)
def getSlaves():
()
if waysToGetRacks == "1":
TrafficDrugs()
if waysToGetRacks == "2":
getSlaves()
Dont ask about the varaibles, but im very confused why im getting a error
You don't need brackets inside your func:
def TrafficDrugs(slaveQuestion1):
slaveQuestion1 == input(" Push P if you want a rack")
if TrafficDrugs(slaveQuestion1):
racks += "1"
you can't call a recursive function you have just defined you need to enter a valid parameter in order to pass the if statement.

Get a single character in Python as input without having to press Enter (Similar to getch in C++)

First of all, I am totally new in Python, having just started to learn it. I know a lot of stuff about C++ however and I am just trying to implement some of those in Python.
I have done quite a search on it but I couldn't find any solution that fits my requirement. Please see the following code,
import os
class _Getch:
"""Gets a single character from standard input. Does not echo to the
screen."""
def __init__(self):
try:
self.impl = _GetchWindows()
except:
print("Error!")
def __call__(self): return self.impl()
class _GetchWindows:
def __init__(self):
import msvcrt
def __call__(self):
import msvcrt
return msvcrt.getch()
def mainfun():
check = fh = True
while check:
fh = True
arr = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
print ("Welcome to Tic Tac Toe Game!!!\n\n")
print("Enter 1 to Start Game")
print("Enter 2 to Exit Game")
a = _Getch()
if a == "1":
while fh:
os.system("cls")
drawboard()
playermove()
fh = checkresult()
elif a == "2":
break
As you can see, What I am trying to do here is asking the user to press a number from 1 and 2 and then store that number in "a" and then use it for my requirements.
Now, I first tried using this,
input('').split(" ")[0]
But this didn't work. It required me to always Press Enter after having typed 1 or 2. So, that didn't work.
Then I found this class of Getch and I implemented it. Long story short, it entered me into a never ending loop and my result is something like this now,
Welcome to Tic Tac Toe Game!!!
Enter 1 to Start Game
Enter 2 to Exit Game
Press Enter to Continue....
Welcome to Tic Tac Toe Game!!!
Enter 1 to Start Game
Enter 2 to Exit Game
Press Enter to Continue....
Welcome to Tic Tac Toe Game!!!
Enter 1 to Start Game
Enter 2 to Exit Game
Press Enter to Continue....
And it is a never ending loop... Even if I press any key like "1" or "2", it still doesn't stop and keep on performing this and don't enter any function.
What I want is a function similar to this,
It should work on PYCHARM Console (I am practicing and I don't want to practice on Terminal. I am used to using the console of the IDE I am working on)
It pauses and waits for the user to enter any input (like input does)
It accepts and stores the very first key entered by the user into the variable. Like in this case, if user presses "1" then it should store that character in "a" and simply move on. You don't have to Press "ENTER" to move on.
If the user presses any other button like "a" or "b" or anything like this, it will simply not do anything and keep on asking for the input until the required number "1" or "2" is entered (and I think that can very easily be handled in this while loop)
In other words, I just want an alternative to getch() command of C++ in Python. I have tried a lot to find it, but I couldn't. Please refer to me a question which provides a solution to this exact question or provide a solution here. Thank you.
Edit: Please note this isn't the complete code. I have only provided the code which is relevant. If anyone needs to see the whole code, I am happy to share that as well.
Complete code is as follows,
import os
import keyboard
def getch():
alphabet = list(map(chr, range(97, 123)))
while True:
for letter in alphabet: # detect when a letter is pressed
if keyboard.is_pressed(letter):
return letter
for num in range(10): # detect numbers 0-9
if keyboard.is_pressed(str(num)):
return str(num)
arr = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
playerturn = 1
def drawboard():
global playerturn
print("Player 1 (X) - Player 2 (O)\n")
print("Turn: Player " + str(playerturn))
print("\n")
for i in range(3):
print (" ", end='')
for j in range(3):
print(arr[i][j], end='')
if j == 2:
continue
print(" | ", end='')
if i == 2:
continue
print("")
print("____|____|____")
print(" | | ")
def playermove():
global playerturn
row = col = 0
correctmove = False
print("\n\nMake your Move!\n")
while not correctmove:
row = int(input("Enter Row: "))
col = int(input("Enter Col: "))
if (3 > row > -1) and (-1 < col < 3):
for i in range(3):
for j in range(3):
if arr[row][col] == 0:
correctmove = True
if playerturn == 1:
arr[row][col] = 1
else:
arr[row][col] = 2
playerturn += 1
if playerturn > 2:
playerturn = 1
if not correctmove:
print ("Wrong Inputs, please enter again, ")
def checkwin():
for player in range(1, 3):
for i in range(3):
if arr[i][0] == player and arr[i][1] == player and arr[i][2] == player: return player
if arr[0][i] == player and arr[1][i] == player and arr[2][i] == player: return player
if arr[0][0] == player and arr[1][1] == player and arr[2][2] == player: return player
if arr[0][2] == player and arr[1][1] == player and arr[2][0] == player: return player
return -1
def checkdraw():
for i in range(3):
for j in range(3):
if arr[i][j] == 0:
return False
return True
def checkresult():
check = checkwin()
if check == 1:
os.system('cls')
drawboard()
print("\n\nPlayer 1 has won the game!!\n")
elif check == 2:
os.system('cls')
drawboard()
print("\n\nPlayer 2 has won the game!!\n")
elif check == 3:
os.system('cls')
drawboard()
print("\n\nThe game has been drawn!!\n")
else:
return True
return False
def mainfun():
check = fh = True
while check:
os.system("cls")
fh = True
arr = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
print ("Welcome to Tic Tac Toe Game!!!\n\n")
print("Enter 1 to Start Game")
print("Enter 2 to Exit Game")
a = getch()
if a == "1":
while fh:
os.system("cls")
drawboard()
playermove()
fh = checkresult()
elif a == "2":
break
print ("Press any key to continue...")
getch()
mainfun()
EDIT2: Problem is resolved by using Keyboard module... The next issue here is how do I remove the data stored in input buffer after the getch() function is called? Because the data in buffer is getting displayed on the next input (when I am taking in the row and column) and I don't want that to happen. I fonud a solution for Linux but not for Windows (or for Pycharm)
It looks like this feature isn't in the standard python library but you can recreate it.
First, install the module 'keyboard'
$ pip3 install keyboard
Then you can use keyboard.is_pressed() to see if any one character is pressed.
import keyboard # using module keyboard
import string # use this to get the alphabet
print("Input a character")
def getch():
alphabet = list(string.ascii_lowercase)
while True:
for letter in alphabet: # detect when a letter is pressed
if keyboard.is_pressed(letter):
return letter
for num in range(10): # detect numbers 0-9
if keyboard.is_pressed(str(num)):
return str(num)
answer = getch()
print("you choose " + answer)
Edit: For unix you need to run with the script with sudo. This code should work fine on windows.
For EDIT-2:
Use below code to flush the screen:
sys.stdout.flush()

Boolean condition is reading True, but the while loop still isn't breaking

For some reason the while loop is not breaking when the condition is met. The while loop should be checking for a players input to fill up a tic tac toe board until the variable "win" reads True.
Once the board reflects one of the winning conditions of tic tac toe, it assigns the variable "win" to True, and in turn should break out of the loop.
For some reason the loop isn't breaking, but the variable "win" is still reading True.
Can someone explain why the loop isn't breaking? I have tried rewriting the condition for the while loop to read "while win == False", but that doesn't seem to resolve the issue either.
I have included some of the functions I am using, and explained some of the simpler ones with a comment next to it.
I am using repl.it to do all of this online and not on a program on my local machine, so I think this may be part of the issue as well.
import os
board = ["#"," "," "," "," "," "," "," "," "," "]
def determine_win(marker):
# Winning Patterns:
# (1,2,3), (4,5,6), (7,8,9), (1,4,7), (2,5,8), (3,6,9), (3,5,7), (1,5,9)
if board[1]== board[2]==board[3]==marker:
return True
elif board[4]== board[5]==board[6]==marker:
return True
elif board[7]== board[8]==board[9]==marker:
return True
elif board[1]== board[4]==board[7]==marker:
return True
elif board[2]== board[5]==board[8]==marker:
return True
elif board[3]== board[6]==board[9]==marker:
return True
elif board[3]== board[5]==board[7]==marker:
return True
elif board[1]== board[5]==board[9]==marker:
return True
else:
return False
player1 = xo() # A Function that takes user input either "X" or O"
if player1 == "X":
player2 = "O"
else:
player2 = "X"
win = False
while not win:
display_board(board) # display_baord(board) takes the list "board" and uses it as input to display the tic tac toe board to the screen.
print("\nPlayer 1")
board[player_turn()] = player1
win = determine_win(player1)
print(win) # used to verify if win is changing
input() # used to pause the screen for troubleshooting
display_board(board)
print("\nPlayer 2")
board[player_turn()] = player2
win = determine_win(player2)
print(win) # used to verify if win is changing
input() # used to pause the screen for troubleshooting
print("Win Declared")
As the comment said, the reason is because while only check the condition of win when you finish the whole iteration of the loop. I would prefer the following way to make the code neater:
# win = False <-- you don't need this now
while True:
display_board(board) # display_baord(board) takes the list "board" and uses it as input to display the tic tac toe board to the screen.
print("\nPlayer 1")
board[player_turn()] = player1
if determine_win(player1):
print("Player 1 won")
break # break out of the loop
display_board(board)
print("\nPlayer 2")
board[player_turn()] = player2
if determine_win(player2):
print("Player 2 won")
break # break out of the loop
if not determine_win(player1):
display_board(board)
print("\nPlayer 2")
board[player_turn()] = player2
win = determine_win(player2)
# player 2 wins
else:
# player 1 wins
win = True
use something like this. It is same as #jasonharper and #Idlehands answered

Beginner to Python - why the heck is my while loop not working?

I am trying to write a program for an assignment where you input a specific command and you can play Rock-Paper-Scissors-Lizard-Spock against the computer.
It was done and working until I realized that the assignment instructions wanted me to make it so that you keep playing the game until one person gets five wins.
So I thought, no big deals, let's throw in a while loop and some variables to track the wins. But when I run the program, it only runs once still. I don't know what I am doing wrong - as this should work. This is my first time working with Python (version 3.3) and this IDE, so I really need some help. Usually I'd just debug but I can't figure out how to work the one in this IDE.
Here is my code. The trouble while-loop is at the way bottom. I am nearly positive everything inside the class works. I would like to note that I already tried while(computerWins < 5 and userWins < 5), so I don't think the condition is the problem.
import random
computerWins = 0
userWins = 0
print ('SELECTION KEY:\nRock = r\nPaper = p\nScissors = sc\nLizard = l\nSpock = sp')
class rockPaperScissorsLizardSpock:
#Two methods for converting from strings to numbers
#convert name to number using if/elif/else
#also converts abbreviated versions of the name
def convertName(name):
if(name == 'rock' or name == 'r'):
return 0
elif(name == 'Spock' or name == 'sp'):
return 1
elif(name == 'paper' or name == 'p'):
return 2
elif(name == 'lizard' or name == 'l'):
return 3
elif(name == 'scissors' or name == 'sc'):
return 4
else:
print ('Error: Invalid name')
#convert number to a name using if/elif/else
def convertNum(number):
if(number == 0):
return 'rock'
elif(number == 1):
return 'Spock'
elif(number == 2):
return 'paper'
elif(number == 3):
return 'lizard'
elif(number == 4):
return 'scissors'
else:
print ('Error: Invalid number')
#User selects an option, and their selection is saved in the 'choice' variable
#Using a while loop so that the user cannot input something other than one of the legal options
prompt = True
while(prompt):
i = input('\nEnter your selection: ')
if(i=='r' or i=='p' or i=='sc' or i=='l' or i=='sp'):
prompt = False
else:
print('Invalid input.')
prompt = True
#Convert the user's selection first to a number and then to its full string
userNum = convertName(i)
userChoice = convertNum(userNum)
#Generate random guess for the computer's choice using random.randrange()
compNum = random.randrange(0, 4)
#Convert the computer's choice to a string
compChoice = convertNum(compNum)
print ('You chose', userChoice)
print ('The computer has chosen', compChoice)
#Determine the difference between the players' number selections
difference = (compNum - userNum) % 5
#Use 'difference' to determine who the winner of the round is
if(difference == 1 or difference == 2):
print ('The computer wins this round.')
computerWins = computerWins+1
elif (difference == 4 or difference == 3):
print ('You win this round!')
userWins = userWins+1
elif(difference == 0):
print ('This round ended up being a tie.')
#Plays the game until someone has won five times
while(computerWins != 5 and userWins != 5):
rockPaperScissorsLizardSpock()
if(computerWins == 5 and userWins != 5):
print ('The computer wins.')
elif(computerWins != 5 and userWins == 5):
print ('You win!')
The essential problem is that rockpaperscissorslizardspock is a class, where you expect it to be a function. The code inside it runs exactly once, when the whole class definition is parsed, rather than each time you call the class as you seem to expect.
You could put the relevant code into an __init__ method - this is a fairly direct analogue of a Java constructor, and hence is is run each time you call the class. But in this case, you probably don't need it to be in a class at all - calling the class creates a new instance (like doing new MyClass() in Java), which you don't use. You would also in this case (or if you made it into a function) need to make some more modifications to make sure the game state persists properly.
The easiest actual solution is to:
delete the line class rockpaperscissorslizardspock: (and unindent everything below it)
Take all the code that was under the class but not in a function - everything from the player makes a selection to determining the winner of the round - and paste it in place of the call to rockpaperscissorslizardspock() in the bottom loop.
The first thing is that you are using a class where you should probably be using a function.
Your code initially runs because python is loading the class.
However, the line rockPaperScissorsLizardSpock() is creating new anonymous instances of your class which calls a constructor that you haven't defined so it does nothing.
One of the interesting things about python is that it allows nested functions so if you change the class to a def you're almost there.
After that, you'll run into trouble with global variables in a local context. That problem is already explained in another StackOverflow question: Using global variables in a function other than the one that created them.
Here is my suggestion for the skeleton to a more simple solution. Use some ideas from here if you like.
import random
legal_shapes = ['r', 'p', 'sc', 'sp', 'l']
scoreboard = [0, 0]
print('SELECTION KEY:\nRock = r\nPaper = p\nScissors = sc\nLizard = l\n'
'Spock = sp')
while(max(scoreboard) < 5):
print("\nScore is {}-{}".format(*scoreboard))
# pick shapes
p1_shape = input('Enter your selection: ')
if p1_shape not in legal_shapes:
print('Not legal selection!')
continue
p2_shape = random.choice(legal_shapes)
print('\np1 plays {} and p2 plays {}'.format(
p1_shape.upper(), p2_shape.upper()))
# determine int values and result indicator
p1_shape_int = legal_shapes.index(p1_shape)
p2_shape_int = legal_shapes.index(p2_shape)
res = (p1_shape_int - p2_shape_int) % 5
if res != 0:
res = abs((res % 2) - 2)
# Print winner
if res == 0:
print(' -> Draw!!')
else:
print(' -> p{} wins'.format(res))
scoreboard[res-1] += 1
print("\nThe game is over!!")
print("p{} won with score {}-{}".format(res, *scoreboard))
It outputs something like
(env)➜ tmp python3 rsp.py
SELECTION KEY:
Rock = r
Paper = p
Scissors = sc
Lizard = l
Spock = sp
Score is 0-0
Enter your selection: T
Not legal selection!
Score is 0-0
Enter your selection: l
p1 plays L and p2 plays SP
-> p2 wins
Score is 0-1
Enter your selection: l
p1 plays L and p2 plays SC
-> p2 wins
...
The game is over!!
p2 won with score 2-5

Categories

Resources