This question already has an answer here:
Pygame Tic Tak Toe Logic? How Would I Do It
(1 answer)
Closed 1 year ago.
I've tried to make a tic tac toe game in Python. From what I make I feel that my code is working however it is really bad. Is there anyway to improve from this code?
class Board():
def __init__(self):
self.board = ["[]","[]","[]","[]","[]","[]","[]","[]","[]"]
def createboard(self):
board = ["[]","[]","[]","[]","[]","[]","[]","[]","[]"]
print(self.board[0],self.board[1],self.board[2])
print(self.board[3],self.board[4],self.board[5])
print(self.board[6],self.board[7],self.board[8])
def checkwin(self):
if self.board[0]=="[O]" and self.board[1]=="[O]" and self.board[2]=="[O]":
print("O Wins!")
#break
elif self.board[3]=="[O]"and self.board[4]=="[O]"and self.board[5]=="[O]":
print("O Wins!")
# break
elif self.board[6]=="[O]"and self.board[7]=="[O]"and self.board[8]=="[O]":
print("O Wins!")
# break
elif self.board[0]=="[O]"and self.board[3]=="[O]"and self.board[6]=="[O]":
print("O Wins!")
# break
elif self.board[1]=="[O]"and self.board[4]=="[O]"and self.board[7]=="[O]":
print("O Wins!")
# break
elif self.board[2]=="[O]"and self.board[5]=="[O]"and self.board[8]=="[O]":
print("O Wins!")
# break
elif self.board[0]=="[O]"and self.board[4]=="[O]"and self.board[8]=="[O]":
print("O Wins!")
# break
elif self.board[2]=="[O]"and self.board[4]=="[O]"and self.board[6]=="[O]":
print("O Wins!")
# break
elif self.board[0]=="[X]"and self.board[1]=="[X]"and self.board[2]=="[X]":
print("X Wins!")
# break
elif self.board[3]=="[X]"and self.board[4]=="[X]"and self.board[5]=="[X]":
print("X Wins!")
# break
elif self.board[6]=="[X]"and self.board[7]=="[X]"and self.board[8]=="[X]":
print("X Wins!")
# break
elif self.board[0]=="[X]"and self.board[3]=="[X]"and self.board[6]=="[X]":
print("X Wins!")
# break
elif self.board[1]=="[X]"and self.board[4]=="[X]"and self.board[7]=="[X]":
print("X Wins!")
# break
elif self.board[2]=="[X]"and self.board[5]=="[X]"and self.board[8]=="[X]":
print("X Wins!")
# break
elif self.board[0]=="[X]"and self.board[4]=="[X]"and self.board[8]=="[X]":
print("X Wins!")
# break
elif self.board[2]=="[X]"and self.board[4]=="[X]"and self.board[6]=="[X]":
print("O Wins!")
# break
def omove(self):
o = int(input("Its 'O's'move please insert 1-9"))
if o == 1:
self.board[0] = "[O]"
self.createboard()
elif o == 2:
self.board[1] = "[O]"
self.createboard()
elif o == 3:
self.board[2] = "[O]"
self.createboard()
elif o == 4:
self.board[3] = "[O]"
self.createboard()
elif o == 5:
self.board[4] = "[O]"
self.createboard()
elif o == 6:
self.board[5] = "[O]"
self.createboard()
elif o == 7:
self.board[6] = "[O]"
self.createboard()
elif o == 8:
self.board[7] = "[O]"
self.createboard()
elif o == 9:
self.board[8] = "[O]"
self.createboard()
else:
print('that column is out of range')
o = int(input("please insert 1-9"))
def xmove(self):
x = int(input("Its 'x's'move please insert 1-9"))
if x == 1:
self.board[0] = "[X]"
self.createboard()
elif x == 2:
self.board[1] = "[X]"
self.createboard()
elif x == 3:
self.board[2] = "[X]"
self.createboard()
elif x == 4:
self.board[3] = "[X]"
self.createboard()
elif x == 5:
self.board[4] = "[X]"
self.createboard()
elif x == 6:
self.board[5] = "[X]"
self.createboard()
elif x == 7:
self.board[6] = "[X]"
self.createboard()
elif x == 8:
self.board[7] = "[X]"
self.createboard()
elif x == 9:
self.board[8] = "[X]"
self.createboard()
else:
print('that column is out of range')
o = int(input("please insert 1-9"))
a = Board()
a.createboard()
a.omove()
a.checkwin()
a.xmove()
a.checkwin()
a.omove()
a.checkwin()
a.xmove()
a.checkwin()
a.omove()
a.checkwin()
a.xmove()
a.checkwin()
a.omove()
a.checkwin()
a.xmove()
a.checkwin()
a.omove()
a.checkwin()
I would love any kind of feedback to improve my skills in programming. What I thought about this is I think I used too much if condition maybe it can be swapped by another simple method and how can I even break when the game is finished ex: if X wins the game, the game is then closed
A big change would be to refactor the move functions to pass in the token you need and avoid the elifs with maths.
def move(self, token):
o = int(input(f"Its '{token}'s'move please insert 1-9"))
while not (0 < o <= 9):
print('that column is out of range')
o = int(input("please insert 1-9"))
self.board[o-1] = f"[{token}]"
self.createboard()
used via...
move("O")
move("X")
self.board = 9*['[]']
def createboard(self):
for i,j in enumerate(board, 1):
print(j)
if i%3 == 0: print('\n')
Have a look at python tutorial: https://docs.python.org/3/tutorial/
Related
So I'm trying to make a game in python where you register players at the start and then can play games of odd or even. I wanted a system where the game would loop over for each player and once ever player within the list has been gone through it opens the menu again.
There is a list named players and the following code just results in an endless loop around the first player. I've tried a few different loops such as a for loop and variants of the while loop but none of them are able to do what I want them to.
This is the code that I have:
class OddOrEven(Game):
def oddoreven():
index = 0
print("Hey", players[index], "Odd (o) or Even (e)?")
choice = input('> \u001b[1m')
print('\u001b[0m', end='')
randomdice = d.roll()
while index < len(players):
while choice != "o" or choice != "e":
if choice == "o" and randomdice == 1 or randomdice == 3 or randomdice == 5:
print("Congratulations,", players[index], "You win!")
print()
elif choice == "o" and randomdice == 2 or randomdice == 4 or randomdice == 6:
print("Sorry,", players[index], "You lose!")
print()
elif choice == "e" and randomdice == 2 or randomdice == 4 or randomdice == 6:
print("Congratulations,", players[index], "You win!")
print()
elif choice == "e" and randomdice == 1 or randomdice == 3 or randomdice == 5:
print("Sorry,", players[index], "You lose!")
print()
else:
print("Invalid choice.")
choice = input('> \u001b[1m')
print('\u001b[0m', end='')
index += 1
So I ended up fixing it with some tweaking of the code, turns out I had forgotten to add a loop around where the next player would be asked the question so this is what I now have that is working.
index = 0
for index in range(len(players)):
print("Hey", players[index], "Odd (o) or Even (e)?")
choice = input('> \u001b[1m')
print('\u001b[0m', end='')
power = p.getPower()
randomdice = d.roll()
# If statement that checks what the power is and adds the value to the random dice so that the new dice can be printed
if power == 1:
randomdice + 1
elif power == 2:
randomdice + 2
elif power == 3:
randomdice + 3
elif power == 4:
randomdice + 4
elif power == 5:
randomdice + 5
if randomdice == 1:
print (dice[0])
elif randomdice == 2:
print (dice[1])
elif randomdice == 3:
print (dice[2])
elif randomdice == 4:
print (dice[3])
elif randomdice == 5:
print (dice[4])
elif randomdice == 6:
print (dice[5])
while index < len(players):
if choice == "o" and randomdice == 1 or randomdice == 3 or randomdice == 5:
print("Congratulations,", players[index], "You win!")
print()
break
elif choice == "o" and randomdice == 2 or randomdice == 4 or randomdice == 6:
print("Sorry,", players[index], "You lose!")
print()
break
elif choice == "e" and randomdice == 2 or randomdice == 4 or randomdice == 6:
print("Congratulations,", players[index], "You win!")
print()
break
elif choice == "e" and randomdice == 1 or randomdice == 3 or randomdice == 5:
print("Sorry,", players[index], "You lose!")
print()
break
else:
print("Invalid choice.")
print("Odd (o) or Even (e)?")
choice = input('> \u001b[1m')
print('\u001b[0m', end='')
index += 1
The program is just a very basic 'o and x' game.
In the program one function (the user input) is calling another function (to check if there is a winner).
Obviously not every turn is a winner, but needs to be checked after each go. Then if the criteria for winning is met then I want it to break the program.
I have managed to make it work using sys.exit() in the winner function however I actually want the 'user input' function to check if the 'winner' function has been fulfilled.
Here is the code, (it works). I will put a # Message in the place that I want the check to actually happen.
Winner function
import sys
def winlose(g):
#down line 1 ### WORKING ###
if g[0][0] == g[1][0] and g[0][0] == g[2][0] and g[0][0] != 0:
if g[0][0] == 'x':
print(f"Player 1 wins")
sys.exit()
elif g[0][0] == 'o':
print(f"Player 2 wins")
sys.exit()
#accross line 1 ### WORKING ###
elif g[0][0] == g[0][1] and g[0][0] == g[0][2] and g[0][0] != 0:
if g[0][0] == 'x':
print(f"Player 1 wins")
sys.exit()
elif g[0][0] == 'o':
print(f"Player 2 wins")
sys.exit()
# diagonal top left ### WORKING ###
elif g[0][0] == g[1][1] and g[0][0] == g[2][2] and g[0][0] != 0:
if g[0][0] == 'x':
print(f"Player 1 wins")
sys.exit()
elif g[0][0] == 'o':
print(f"Player 2 wins")
sys.exit()
#middle down ### WORKING ###
elif g[0][1] == g[1][1] and g[0][1] == g[2][1] and g[0][1] != 0:
if g[0][1] == 'x':
print(f"Player 1 wins")
sys.exit()
elif g[0][1] == 'o':
print(f"Player 2 wins")
sys.exit()
#end down ### WORKING ###
elif g[0][2] == g[1][2] and g[0][2] == g[2][2] and g[0][2] != 0:
if g[0][2] == 'x':
print(f"Player 1 wins")
sys.exit()
elif g[0][2] == 'o':
print(f"Player 2 wins")
sys.exit()
#diagonal right ### WORKING ###
elif g[0][2] == g[1][1] and g[0][2] == g[2][0] and g[0][2] != 0:
if g[0][2] == 'x':
print(f"Player 1 wins")
sys.exit()
elif g[0][2] == 'o':
print(f"Player 2 wins")
sys.exit()
# middle accross ### WORKING ###
elif g[1][0] == g[1][1] and g[1][0] == g[1][2] and g[1][0] != 0:
if g[1][0] == 'x':
print(f"Player 1 wins")
sys.exit()
elif g[1][0] == 'o':
print(f"Player 2 wins")
sys.exit()
#bottom accross
elif g[2][0] == g[2][1] and g[2][0] == g[2][2] and g[2][0] != 0:
if g[2][0] == 'x':
print(f"Player 1 wins")
sys.exit()
elif g[2][0] == 'o':
print(f"Player 2 wins")
sys.exit()
User input page
from winner import winlose as w
g = [[0, 0, 0],
[0, 0, 0],
[0, 0, 0]]
no = 0
print("\n")
for item in g:
print(item)
print("\n")
def player(no):
while True:
counter = ''
turn = ''
if no % 2 == 0:
turn = 'Player 1'
counter = 'x'
else:
counter = 'o'
turn = 'Player 2'
print(f"{turn} which square do you want to go in?")
row = int(input('row 1, 2 or 3? ')) - 1
column = int(input('column 1, 2 or 3? ')) - 1
if g[row][column] == 0:
g[row][column] = counter
no += 1
print("\n")
for item in g:
print(item)
print("\n")
w(g)
# I would like the check to see if someone has won the game to happen here. If it has to break the while loop
else:
print('that space is taken, please go again')
player(no)
if no == 9:
print("Its a draw")
break
player(no)
You can do so by using the keyword "break" inside of the loop.
while True:
break
the body is executed exactly once thanks to break
First you should set a flag whether game ended or keep going, like:
def winlose(g):
isGameEnded = False
then, you should change all sys.exit with
isGameEnded = True
at the end of function return it to main program,
return isGameEnded
and in the main function you can do this simply:
if(winlose(g)):
break
full form of program;
def winlose(g):
isGameEnded = False
#down line 1 ### WORKING ###
if g[0][0] == g[1][0] and g[0][0] == g[2][0] and g[0][0] != 0:
if g[0][0] == 'x':
print(f"Player 1 wins")
isGameEnded = True
elif g[0][0] == 'o':
print(f"Player 2 wins")
isGameEnded = True
#accross line 1 ### WORKING ###
elif g[0][0] == g[0][1] and g[0][0] == g[0][2] and g[0][0] != 0:
if g[0][0] == 'x':
print(f"Player 1 wins")
isGameEnded = True
elif g[0][0] == 'o':
print(f"Player 2 wins")
isGameEnded = True
# diagonal top left ### WORKING ###
elif g[0][0] == g[1][1] and g[0][0] == g[2][2] and g[0][0] != 0:
if g[0][0] == 'x':
print(f"Player 1 wins")
isGameEnded = True
elif g[0][0] == 'o':
print(f"Player 2 wins")
isGameEnded = True
#middle down ### WORKING ###
elif g[0][1] == g[1][1] and g[0][1] == g[2][1] and g[0][1] != 0:
if g[0][1] == 'x':
print(f"Player 1 wins")
isGameEnded = True
elif g[0][1] == 'o':
print(f"Player 2 wins")
isGameEnded = True
#end down ### WORKING ###
elif g[0][2] == g[1][2] and g[0][2] == g[2][2] and g[0][2] != 0:
if g[0][2] == 'x':
print(f"Player 1 wins")
isGameEnded = True
elif g[0][2] == 'o':
print(f"Player 2 wins")
isGameEnded = True
#diagonal right ### WORKING ###
elif g[0][2] == g[1][1] and g[0][2] == g[2][0] and g[0][2] != 0:
if g[0][2] == 'x':
print(f"Player 1 wins")
isGameEnded = True
elif g[0][2] == 'o':
print(f"Player 2 wins")
isGameEnded = True
# middle accross ### WORKING ###
elif g[1][0] == g[1][1] and g[1][0] == g[1][2] and g[1][0] != 0:
if g[1][0] == 'x':
print(f"Player 1 wins")
isGameEnded = True
elif g[1][0] == 'o':
print(f"Player 2 wins")
isGameEnded = True
#bottom accross
elif g[2][0] == g[2][1] and g[2][0] == g[2][2] and g[2][0] != 0:
if g[2][0] == 'x':
print(f"Player 1 wins")
isGameEnded = True
elif g[2][0] == 'o':
print(f"Player 2 wins")
isGameEnded = True
return isGameEnded
and the user side;
def player(no):
while True:
counter = ''
turn = ''
if no % 2 == 0:
turn = 'Player 1'
counter = 'x'
else:
counter = 'o'
turn = 'Player 2'
print(f"{turn} which square do you want to go in?")
row = int(input('row 1, 2 or 3? ')) - 1
column = int(input('column 1, 2 or 3? ')) - 1
if g[row][column] == 0:
g[row][column] = counter
no += 1
print("\n")
for item in g:
print(item)
print("\n")
if(winlose(g)):
print("game is over")
break
# I would like the check to see if someone has won the game to happen here. If it has to break the while loop
else:
print('that space is taken, please go again')
player(no)
if no == 9:
print("Its a draw")
break
Whenever you use a while loop you can just call a function and whatever it returns will be used as the condition for the loop. You can see how I flip the bool value of x every time I call the function so then it breaks. Please accept this awnser if you though this was helpful
x = False
def foo():
x = not (x)
return x
while foo():
foo()
print("weeee")
I am trying to make a tic tac toe game in the terminal with python but i cant figure out why i get the victory message after choosing the first position can anybody else see why? i have made a for loop to check if i have won in rows or columns and made 2 if statements to check if i have won by diagonal
import random
board = [[' ',' ',' '],
[' ',' ',' '],
[' ',' ',' ']]
def checkwin(board):
for row in board:
if len(set(row)) == 1:
return True
elif board[0][0] == board[1][1] == board[2][2]:
return True
elif board[2][0] == board[1][1] == board[0][2]:
return True
else:
return False
def check_space_taken(board, number):
if not choose_position(board, number) == ' ':
return True
else:
return False
def choose_position(board, number):
if number <= 3:
board[0][number-1] = 'X'
elif number <= 6:
board[1][number-4] = 'X'
elif number <= 9:
board[2][number-7] = 'X'
return board, number
def computer_position(board, computer_number):
computer_number = random.randint(0,9)
if computer_number <= 3:
board[0][computer_number-1] = 'O'
elif computer_number <= 6:
board[1][computer_number-4] = 'O'
elif computer_number <= 9:
board[2][computer_number-7] = 'O'
return board, computer_number
Game_over = False
while not Game_over:
print(board)
player_input = int(input('move to: '))
changed_board = choose_position(board, player_input)
for line in changed_board:
print(line)
if checkwin(board):
print('\n-----------------------Congrats you won-----------------------\n')
Game_over = True
In principle, your logic isn't incorrect, but you need to account for empty spaces. You also forgot to check columns:
def checkwin(board):
for i in range(3):
if board[i][0] != " " and board[i][0] == board[i][1] == board[i][2]:
return True # found a winning row
if board[0][i] != " " and board[0][i] == board[1][i] == board[2][i]:
return True # found a winning column
# winning diagonals?
if board[1][1] != " " and board[0][0] == board[1][1] == board[2][2]:
return True
if board[1][1] != " " and board[2][0] == board[1][1] == board[0][2]:
return True
return False
I'm just wondering how I can make it so elif player_position == 1 will work. I want to check the value of the argument (pos) in function player_position() and execute code depending on its value. I've only been learning Python for about 1 month.
def player_position(pos):
position = pos
if position == goliath.spawn:
print('The Goliath Has Attacked!')
if goliath.accuracy == 1:
print('You Have Been Killed!')
else:
print('You Killed The Goliath!')
else:
print('Nothing Happens...')
def starting_room():
while True:
position_update = input('Enter A Direction: ')
if position_update == 'Forwards':
player_position(1)
elif position_update == 'Backwards':
player_position(3)
elif position_update == 'Left':
player_position(4)
elif position_update == 'Right':
player_position(2)
elif player_position == 1:
if position_update == 'Forwards':
print('Room 2')
elif position_update == 'Backwards':
player_position(0)
elif position_update == 'Left':
print('There Are Monsters In the Dark')
elif position_update == 'Right':
print('There Are Monsters In The Dark')
starting_room()
You're making a call to player_position, a function which does not return anything. Instead, assuming you want to keep track of the player's current position within your starting_room function, you'll want to keep track of the pos there.
Something like this: (note - you'll need to add more code to break out of the while loop - this code should allow you to keep track of the pos though)
def player_position(pos):
position = pos
if position == goliath.spawn:
print('The Goliath Has Attacked!')
if goliath.accuracy == 1:
print('You Have Been Killed!')
else:
print('You Killed The Goliath!')
else:
print('Nothing Happens...')
def starting_room():
pos = 0 #initialize the pos to 0
while True:
position_update = input('Enter A Direction: ')
if pos == 1: #check to see if current pos is 1
if position_update == 'Forwards':
print('Room 2')
#you may want to add "break" here to stop this while loop
elif position_update == 'Backwards':
pos = 0
elif position_update == 'Left':
print('There Are Monsters In the Dark')
elif position_update == 'Right':
print('There Are Monsters In The Dark')
elif position_update == 'Forwards':
pos = 1
elif position_update == 'Backwards':
pos = 3
elif position_update == 'Left':
pos = 4
elif position_update == 'Right':
pos = 2
player_position(pos) #call the player_position function with the current pos
starting_room()
I need to calculate difference between 'player_number' and 'comp_number' but it says:
TypeError: unsupported operand type(s) for Sub: 'NoneType' and 'int'
I understand this error. My code generates player_number is None type that is why I can not subtract it.
How can I handle this problem? Any ideas?
Here is my code:
def name_to_number(name):
if name == "rock":
name = 0
elif name == "paper":
name = 1
elif name == "Spock":
name = 2
elif name == "lizard":
name = 3
elif name == "scissors":
name = 4
else:
print 'Name is not listed:',name
def number_to_name(number):
if number == 0:
print "rock"
elif number == 1:
print "Spock"
elif number == 2:
print "paper"
elif number == 3:
print "lizard"
elif number == 4:
print "scissors"
else:
print 'Your number is not valid:',number
def rpsls(player_choice):
if player_choice == "rock":
print 'Player choses', player_choice
player_number = name_to_number(player_choice)
elif player_choice == "Spock":
print 'Player choses',player_choice
player_number = name_to_number(player_choice)
elif player_choice == "paper":
print 'Player choses',player_choice
player_number = name_to_number(player_choice)
elif player_choice == "lizard":
print 'Player choses',player_choice
player_number = name_to_number(player_choice)
elif player_choice == "scissors":
print 'Player choses',player_choice
player_number = name_to_number(player_choice)
else:
print "Name not in list",player_choice
import random
comp_number = random.randrange(0,4)
if comp_number == 0:
print "Computer choses",number_to_name(0)
elif comp_number == 1:
print "Computer choses",number_to_name(1)
elif comp_number == 2:
print "Computer choses",number_to_name(2)
elif comp_number == 3:
print "Computer choses",number_to_name(3)
elif comp_number == 4:
print "Computer choses",number_to_name(4)
diffrence = player_number - comp_number
if diffrence % 5 == 1 or 2:
print 'Player wins!'
elif (diffrence % 5) == 3 or 4:
print 'Computer wins!'
else:
print 'Game tie'
rpsls("rock")
You have this assigment
player_number = name_to_number(player_choice)
But none of your if/elif/else cases in name_to_number use the return keyword. To return a value from this function, you would do
def name_to_number(name):
if name == "rock":
return 0
elif name == "paper":
return 1
elif name == "Spock":
return 2
elif name == "lizard":
return 3
elif name == "scissors":
return 4
else:
print 'Name is not listed:',name
The same goes for your number_to_name function
Untested Fix. 'return' statement was missing. Using the same variable name for a string and an int is not nice programming style.
def name_to_number(name):
number = -1
if name == "rock":
number = 0
elif name == "paper":
number = 1
elif name == "Spock":
number = 2
elif name == "lizard":
number = 3
elif name == "scissors":
number = 4
else:
print 'Name is not listed:',name
return number #This line was missing