So this is my tic tac toe python game, but the result is that after someone wins, you have to choose another square before it ends, and when it ends, it never shows 'player one won!' or 'player two won!' I'm not sure why that is happening. Can someone please help?
# Tic Tac Toe Game
import time
import sys
who = 'p1'
finished = 'no'
board = [0,1,2,
3,4,5,
6,7,8]
def show():
print (board[0], '|', board [1], '|', board[2])
print ('---------')
print (board[3], '|', board [4], '|', board[5])
print ('---------')
print (board[6], '|', board [7], '|', board[8])
def checkWin():
if board[0] == 'x' and board[3] == 'x' and board[6] == 'x':
finished = 'yes'
return True
elif board[0] == 'y' and board[3] == 'y' and board[6] == 'y':
finished = 'yes'
return True
elif board[1] == 'x' and board[4] == 'x' and board[7] == 'x':
finished = 'yes'
return True
elif board[1] == 'y' and board[4] == 'y' and board[7] == 'y':
finished = 'yes'
return True
elif board[2] == 'y' and board[5] == 'y' and board[8] == 'y':
finished = 'yes'
return True
elif board[2] == 'x' and board[5] == 'x' and board[8] == 'x':
finished = 'yes'
return True
elif board[0] == 'y' and board[1] == 'y' and board[2] == 'y':
finished = 'yes'
return True
elif board[0] == 'x' and board[1] == 'x' and board[2] == 'x':
finished = 'yes'
return True
elif board[3] == 'x' and board[4] == 'x' and board[5] == 'x':
finished = 'yes'
return True
elif board[3] == 'y' and board[4] == 'y' and board[5] == 'y':
finished = 'yes'
return True
elif board[6] == 'y' and board[7] == 'y' and board[8] == 'y':
finished = 'yes'
return True
elif board[6] == 'x' and board[7] == 'x' and board[8] == 'x':
finished = 'yes'
return True
elif board[0] == 'x' and board[4] == 'x' and board[8] == 'x':
finished = 'yes'
return True
elif board[0] == 'y' and board[4] == 'y' and board[8] == 'y':
finished = 'yes'
return True
elif board[2] == 'y' and board[4] == 'y' and board[6] == 'y':
finished = 'yes'
return True
elif board[2] == 'x' and board[4] == 'x' and board[6] == 'x':
finished = 'yes'
return True
else:
return False
print ('Welcome to a two-player Tic.Tac.Toe Game!')
time.sleep(2)
print ("Just pick a spot to put your mark!")
time.sleep(1.5)
print ('Now, start!')
time.sleep(0.2)
print (show())
while checkWin() == False:
while who == 'p1':
try:
p1 = int(input('Player 1, select a spot: '))
if board[p1] != 'x' and board[p1] != 'o':
board[p1] = 'x'
who = 'p2'
break
else:
print ('This spot is taken.')
pass
except (ValueError, IndexError):
print ('That is not available. Please try again.')
print (show())
while who == 'p2':
try:
p2 = int(input('Player 2, select a spot: '))
if board[p2] != 'x' and board[p2] != 'o':
board[p2] = 'o'
who = 'p1'
break
else:
print ('This spot is taken.')
pass
except (ValueError, IndexError):
print ('That is not available. Please try again.')
print (show())
while checkWin == True:
# x
if board[0] == 'x' and board[3] == 'x' and board[6] == 'x':
print ('Player 1 won!')
sys.exit()
elif board[1] == 'x' and board[4] == 'x' and board[7] == 'x':
print ('Player 1 won!')
sys.exit()
elif board[2] == 'x' and board[5] == 'x' and board[8] == 'x':
print ('Player 1 won!')
sys.exit()
elif board[0] == 'x' and board[1] == 'x' and board[2] == 'x':
print ('Player 1 won!')
sys.exit()
elif board[3] == 'x' and board[4] == 'x' and board[5] == 'x':
print ('Player 1 won!')
sys.exit()
elif board[6] == 'x' and board[7] == 'x' and board[8] == 'x':
print ('Player 1 won!')
sys.exit()
elif board[0] == 'x' and board[4] == 'x' and board[8] == 'x':
print ('Player 1 won!')
sys.exit()
elif board[2] == 'x' and board[4] == 'x' and board[6] == 'x':
print ('Player 1 won!')
sys.exit()
# y
else:
print ('Player 2 won!')
sys.exit()
Related
i am struggling to see how my minimax algorithm is not working. It cycles through all the best moves but it dosen't pick the best one and i can't figure out why. For example i can input 1 5 9 and win. sorry in advance if the solution is something simple
Here is the code.
board = {1: ' ', 2: ' ', 3: ' ',
4: ' ', 5: ' ', 6: ' ',
7: ' ', 8: ' ', 9: ' '}
win = False
turn = 1
depth = 1
nodeindex = 0
possibles= []
moves = []
depth = 0
targetdepth = 3
movesdone = []
#def minimax(moves, targetdepth, depth, turn, scores):
def checkForWin(mark):
if board[1] == board[2] and board[1] == board[3] and board[1] == mark:
return True
elif (board[4] == board[5] and board[4] == board[6] and board[4] == mark):
return True
elif (board[7] == board[8] and board[7] == board[9] and board[7] == mark):
return True
elif (board[1] == board[4] and board[1] == board[7] and board[1] == mark):
return True
elif (board[2] == board[5] and board[2] == board[8] and board[2] == mark):
return True
elif (board[3] == board[6] and board[3] == board[9] and board[3] == mark):
return True
elif (board[1] == board[5] and board[1] == board[9] and board[1] == mark):
return True
elif (board[7] == board[5] and board[7] == board[3] and board[7] == mark):
return True
else:
return False
def checkForWin2():
if (board[1] == board[2] and board[1] == board[3] and board[1] != ' '):
return True
elif (board[4] == board[5] and board[4] == board[6] and board[4] != ' '):
return True
elif (board[7] == board[8] and board[7] == board[9] and board[7] != ' '):
return True
elif (board[1] == board[4] and board[1] == board[7] and board[1] != ' '):
return True
elif (board[2] == board[5] and board[2] == board[8] and board[2] != ' '):
return True
elif (board[3] == board[6] and board[3] == board[9] and board[3] != ' '):
return True
elif (board[1] == board[5] and board[1] == board[9] and board[1] != ' '):
return True
elif (board[7] == board[5] and board[7] == board[3] and board[7] != ' '):
return True
else:
return False
def possiblemoves(board):
y=0
possibles.clear()
for i in board:
if board[i] == " ":
possibles.append(i)
return possibles
def botgo(possibles, mark):
bestscore = -800
bestmove = 0
for key in board.keys():
if (board[key] == ' '):
board[key] = mark
score = minimax(board,0,False)
board[key] = ' '
if(score > bestscore):
bestscore = score
bestmove = key
insert(bestmove,mark='O')
return
def printboard():
print(board[1] + '|' + board[2] + '|' + board[3])
print('-----')
print(board[4] + '|' + board[5] + '|' + board[6])
print('-----')
print(board[7] + '|' + board[8] + '|' + board[9])
def start():
turn = 1
count = 0
while count != 9:
humango()
printboard()
possiblemoves(board)
botgo(possibles, mark='O')
printboard()
count = count + 1
#minimax(depth, possibles)
def spacefree(space):
if board[space] == ' ':
return True
else:
return False
def insert(space, mark):
if spacefree(space):
board[space]=mark
if checkForWin(mark):
if mark == 'X':
printboard()
print("human win")
exit()
else:
printboard()
print("BOT WIN")
exit()
else:
print("cannot insert there!!!")
space = int(input("Enter position"))
insert(space, mark)
def checkdraw(board):
if checkForWin2():
return True
def humango():
global turn
space = int(input("Enter position"))
insert(space, mark='X')
turn = turn + 1
printboard()
def minimax(board, depth, ismax):
if checkForWin(mark='O'):
return 1
elif checkForWin(mark='X'):
return -1
elif checkdraw(board):
return 0
if ismax == True:
bestscore = -800
for key in board.keys():
if (board[key] == ' '):
board[key] = 'O'
score = minimax(board, depth + 1, False)
board[key] = ' '
if (score > bestscore):
bestscore = score
printboard()
return bestscore
else:
bestscore = 800
for key in board.keys():
if (board[key] == ' '):
board[key] = 'X'
score = minimax(board, depth + 1, True)
board[key] = ' '
if (score < bestscore):
bestscore = score
return bestscore
start()
sorry for the messy code, thank you in advance
It seems you are complicating things, it will be much easier for you to debug with less code to look at. I would first suggest that you use a list instead of a dict to simplify your code in this game: board = [' ']*9. All my suggestions/simplifications below are based on this representation.
1.. Checking for win on a 1D board is super easy. First you create a variable with all the possible winning lines:
winning_lines = ([0, 1, 2], [3, 4, 5], [6, 7, 8], [0, 3, 6], [1, 4, 7], [2, 5, 8], [0, 4, 8], [2, 4, 6])
Then you can loop through them with a loop:
def is_win(board, player):
for pos in winning_lines:
if board[pos[0]] == board[pos[1]] == board[pos[2]] == player:
return 1
2.. Checking for draw is even simpler since you only need to check if there are empty spaces or not:
def is_draw(board):
return 0 if ' ' in board else 1
3.. You don't need the depth variable in this game since you always go to maximum depth, ending in win, draw or loss. The depth can be used to always chose the shortest path to winning if there are more than 1 path, or the longest path to loss. Then you need to add and subtract depth from your check_win return statements in the minimax loop.
4.. You can get all the possible moves with list comprehension:
possible_moves = [i for i in range(len(board)) if board[i] == ' ']
Debugging
There are a few other clean ups to do, but to figure out why it gives the wrong answer you need to do some debugging. Does your win/draw/loss function work as you think it does, i.e. does it return the correct result for a known input board? Does it loop through all the possible moves? Print things in your minimax loop and see if it behaves as you would expect.
so i am making a tic tac toe program and the check win functions dont work, it seems as it just skips through it even if its true
this is a new way i wrote and it doesnt work
row_1 = board[0] == board[1] == board[2] != "-"
row_2 = board[3] == board[4] == board[5] != "-"
row_3 = board[6] == board[7] == board[8] != "-"
if row_1 or row_2 or row_3:
if row_1 or row_2 or row_3 == char:
status = True
check = True
elif row_1 or row_2 or row_3 == ai_char:
status2 = True
check = False
this is the old way i had it doesnt work
if board[0] == board[3] == board[6] == char:
status = True
check = True
if board[1] == board[4] == board[7] == char:
status = True
check = True
if board[2] == board[5] == board[8] == char:
status = True
check = True
if board[0] == board[3] == board[6] == ai_char:
status2 = True
check = False
if board[1] == board[4] == board[7] == ai_char:
status2 = True
check = False
if board[2] == board[5] == board[8] == ai_char:
status2 = True
check = False
both ways looks like it should work but it doesnt
this is the whole code https://pastebin.com/G7Stkk79
why don't you make it much simpler by using this as an option.
row1 = all(board[i] != '-' for i in [0,3,6])
You can also try to use
row1 = all(board[i] != '-' for i in range(0,7,3))
The above code will work as follows:
if board[0] != '-' and board[3] != '-' and board[6] != '-':
row1 = True
else:
row1 = False
In this case, if any of the values in board[0], board[3], board[6] is equal to '-', then it will result in False else True.
In your code, you are checking for an entire row. It is much easier as you are going from 0 through 8 where row1=(0,1,2), row2=(3,4,5), and row3=(6,7,8)
If you want to check if the values in each row is not '-', then this code will work:
row_1_dash = all(board[i] != '-' for i in range(0,3))
row_2_dash = all(board[i] != '-' for i in range(3,6))
row_3_dash = all(board[i] != '-' for i in range(6,9))
If you want to check if each value in a row is the same, then you can check as follows:
row_1_same = all(board[i] == board[i+1] for i in range(0,2))
row_2_same = all(board[i] == board[i+1] for i in range(3,5))
row_3_same = all(board[i] == board[i+1] for i in range(6,8))
You can also check if the values are the same and also not equal to '-' using this:
row_1_win = all(board[i] == board[i+1] and board[i] != '-' for i in range(0,2))
row_2_win = all(board[i] == board[i+1] and board[i] != '-' for i in range(3,5))
row_3_win = all(board[i] == board[i+1] and board[i] != '-' for i in range(6,8))
With these options, you can probably reduce your code to find if the player won.
Let me know if you want to know the full implementation. This may help you look at options to implement your solution.
I've decided to learn Python about 2 weeks ago, been going through various books and videos, and I've decided to try my hand at programming a tic tac toe game. I was somewhat successful (it doesn't recognize if there's already a mark in a certain spot and allows overwriting of already placed marks) and I was wondering if any more experienced programmers could give me some general feedback about how I could do things better. Thank you so much and I hope you're all staying safe.
board = ['-'] * 9
def print_board():
print (board[0] + '|' + board[1] + '|' + board[2])
print (board[3] + '|' + board[4] + '|' + board[5])
print (board[6] + '|' + board[7] + '|' + board[8])
legalMoves = [1,2,3,4,5,6,7,8,9]
print_board()
turnCount = 0
def move():
move = int(input('Pick a number 1-9:'))
while move not in legalMoves:
print('Illegal move')
move = int(input('Pick a number 1-9:'))
marks = ['X','O']
if turnCount % 2 == 0:
board[move - 1] = marks[1]
else:
board[move - 1] = marks[0]
while True:
if board[0] == board[1] == board[2] == 'X'\
or board[3] == board[4] == board[5] == 'X'\
or board[6] == board[7] == board[8] == 'X'\
or board[0] == board[3] == board[6] == 'X'\
or board[1] == board[4] == board[7] == 'X'\
or board[2] == board[5] == board[8] == 'X'\
or board[0] == board[4] == board[8] == 'X'\
or board[2] == board[4] == board[6] == 'X' \
or board[0] == board[1] == board[2] == 'O' \
or board[3] == board[4] == board[5] == 'O' \
or board[6] == board[7] == board[8] == 'O' \
or board[0] == board[3] == board[6] == 'O' \
or board[1] == board[4] == board[7] == 'O' \
or board[2] == board[5] == board[8] == 'O' \
or board[0] == board[4] == board[8] == 'O':
print('Victory')
break
else:
move()
print_board()
turnCount = turnCount + 1
well you need to check if the user has typed
an int or something else, so that breaks your
program, also prevent the user from overwriting
existed cell input, also prevent the user from
typing a number out of range which you have
already taken care of that, so I have written
this small function to give you the correct
input and deals with wrong ones, you can use it
def isInt(strInt):
for c in strInt:
if c not in "0123456789": return False
return True
def getNextMove():
while True:
moveStr = input("Pick a number 1-9: ")
if not isInt(moveStr):
print("Pls write only a number")
continue
move = int(moveStr)
if move < 1 or move > 9:
print("Pls only 1-9 numbers are allowed")
continue
if board[move - 1] != "-":
print("Pls choose an empty cell")
continue
return move
Well, if that helped, I couldn't stop my self from writing the full code for the game, I couldn't sleep anyway, so here it is, you may get some ideas, happy coding!
board = [" "] * 9
winner = ""
def printBoard():
print("-" * 7)
for i in range(3):
print(f"|{board[i * 3]}|{board[i * 3 + 1]}|{board[i * 3 + 2]}|")
print("-" * 7)
def isInt(strInt):
for c in strInt:
if c not in "0123456789": return False
return True
def getNextMove():
while True:
moveStr = input("Pick a number 1-9: ")
if not isInt(moveStr):
print("Pls write only a number")
continue
move = int(moveStr)
if move < 1 or move > 9:
print("Pls only 1-9 numbers are allowed")
continue
if board[move - 1] != " ":
print("Pls choose an empty cell")
continue
return move
def checkHVD():
for i in range(3):
if board[i * 3] == board[i * 3 + 1] == board[i * 3 + 2] and board[i * 3] != " ":
return board[i * 3]
elif board[i] == board[i + 3] == board[i + 6] and board[i] != " ":
return board[i]
if (board[0] == board[4] == board[8] or board[2] == board[4] == board[6]) and board[4] != " ":
return board[4]
return False
for i in range(9):
board[getNextMove() - 1] = i % 2 == 0 and "X" or "O"
printBoard()
winner = checkHVD();
if winner:
identity = winner == "X" and "first" or "second"
print(f"The {identity} player({winner}) won")
break
if not winner:
print("It's a tie")
I'm trying to learn python and have been writing a (very) simple tic-tac-toe program. However, I've got stuck because it won't seem to execute beyond letting the user enter a number. After that, nothing happens. I can't figure out where I have gone wrong. Sure there are tons of errors, but help much appreciated!
Thanks!
import random
board = range(0,9)
def print_board():
print board[0], "|", board[1], "|", board[2]
print board[3], "|", board[4], "|", board[5]
print board[6], "|", board[7], "|", board[8]
def checkAll():
if board[0] == board[1] == board[2]:
True
if board[3] == board[4] == board[5]:
True
if board[6] == board[7] == board[8]:
True
if board[0] == board[3] == board[6]:
True
if board[1] == board[4] == board[7]:
True
if board[2] == board[5] == board[8]:
True
if board[0] == board[4] == board[8]:
True
if board[6] == board[4] == board[2]:
True
print_board()
while True:
input = int(raw_input("Choose a number to place your X: "))
if input <= 8:
if board[input] != "x" or board[input] != "o":
board[input] = "x" # places x if board[input] is neither x or o
# Check for winner
if checkAll() == True:
"The game is over!"
break;
finding = True
while finding:
random.seed() # gives a random generator
opponent = random.randrange(0,8) # generates a random integer between 1 and 8
if board[opponent] != "x" or board[opponent] != "o":
board[opponent] = "o"
# Check for winner
if checkAll() == True:
"The game is over!"
break;
else:
print "This spot is taken."
print_board()
else: "Please choose a number between O and 8."
Well there're many things which need improvement in your code (you have to rewrite your CheckAll function at least so it could check board of any size), but two things will help you to debug - first, you have to actually return something from your CheckAll function:
...
if board[0] == board[1] == board[2]:
return True
if board[3] == board[4] == board[5]:
return True
...
second, you may actually want to print output:
if checkAll() == True:
print "The game is over!"
break;
This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
def getCSpot():
global board
global cspot
spotchosen = False
while spotchosen == False:
spotchosen = False
cspot = random.randint(0, 8)
if board[cspot] == 'X' or board[cspot] == 'O':
cspot = random.randint(0, 8)
else:
spotchosen = True
board[cspot] = 'O'
I dont really understand why this isn't working. It does not put the O in the string at all. I have another part of the code that determines if there is a winner when there are 3 O's or X's in a row and that doesn't work either, here is that code. Any help is much appreciated.
def didwin(player):
global gameOver
if (board[0] == player and board[1] == player and board[2] == player or
board[3] == player and board[4] == player and board[5] == player or
board[6] == player and board[7] == player and board[8] == player or
board[0] == player and board[3] == player and board[6] == player or
board[1] == player and board[4] == player and board[7] == player or
board[2] == player and board[5] == player and board[8] == player or
board[0] == player and board[4] == player and board[8] == player or
board[2] == player and board[4] == player and board[6] == player):
gameOver = True
if player == 'X':
print 'congratulations! You won!!'
endGame()
else:
print 'Better luck next time, you lost!'
endGame()
And for reference purposes, here is the endGame function.
def endGame():
global board
displayBoard()
answer = ' '
while answer == ' ':
print 'Would you like to play another game?'
answer = raw_input('Y/N')
if answer == 'Y' or answer == 'y' or answer == 'Yes' or answer == 'yes':
board = [0, 1, 2, 3, 4, 5, 6, 7, 8]
game1()
game()
elif answer == 'N' or answer == 'n' or answer == 'No' or answer == 'no':
exit()
Edit: the following is my whole code with no edits from beginning to end.
board = [0, 1, 2,
3, 4, 5,
6, 7, 8]
import random
def displayBoard():
global board
print board[0], '|', board[1], '|', board[2]
print '----------'
print board[3], '|', board[4], '|', board[5]
print '----------'
print board[6], '|', board[7], '|', board[8]
def getspot():
global board
spotchosen = False
while spotchosen == False:
spotchosen = False
playerSpot = int(raw_input('Where would you like to go? '))
if board[playerSpot] != 'X':
board[playerSpot] = 'X'
if board[playerSpot] != 'O':
board[playerSpot] = 'X'
if playerSpot == 'X':
playerSpot = raw_input('You have already chosen that spot. Please choose another. ')
if playerSpot == 'O':
playerSpot = raw_input('The computer chose that spot already. Please choose another. ')
else:
spotchosen = True
def getCSpot():
global board
global cspot
spotchosen = False
while spotchosen == False:
spotchosen = False
cspot = random.randint(0, 8)
if board[cspot] == 'X' or board[cspot] == 'O':
cspot = random.randint(0, 8)
else:
spotchosen = True
board[cspot] = 'O'
def endGame():
global board
displayBoard()
answer = ' '
while answer == ' ':
print 'Would you like to play another game?'
answer = raw_input('Y/N')
if answer == 'Y' or answer == 'y' or answer == 'Yes' or answer == 'yes':
board = [0, 1, 2, 3, 4, 5, 6, 7, 8]
game1()
game()
elif answer == 'N' or answer == 'n' or answer == 'No' or answer == 'no':
exit()
def didwin(player):
global gameOver
if (board[0] == player and board[1] == player and board[2] == player or
board[3] == player and board[4] == player and board[5] == player or
board[6] == player and board[7] == player and board[8] == player or
board[0] == player and board[3] == player and board[6] == player or
board[1] == player and board[4] == player and board[7] == player or
board[2] == player and board[5] == player and board[8] == player or
board[0] == player and board[4] == player and board[8] == player or
board[2] == player and board[4] == player and board[6] == player):
gameOver = True
if player == 'X':
print 'congratulations! You won!!'
endGame()
else:
print 'Better luck next time, you lost!'
endGame()
else:
gameOver = False
def mainGame():
gameOver = False
while gameOver == False:
displayBoard()
getspot()
didwin('X')
didwin('O')
mainGame()
I'm pretty sure that the problem, whatever it is, is in code that you didn't show us.
I didn't test your endGame function, to keep things simple. But I pasted in your other code, and added the following:
board = [0, 1, 2, 3, 4, 5, 6, 7, 8]
gameOver = False
def endGame():
print 'endGame called'
for i in range(9):
getCSpot()
print(board)
didwin('O')
if gameOver:
print 'gameOver'
break
The result was:
[0, 'O', 2, 3, 4, 5, 6, 7, 8]
[0, 'O', 2, 3, 'O', 5, 6, 7, 8]
[0, 'O', 2, 3, 'O', 5, 'O', 7, 8]
[0, 'O', 2, 3, 'O', 5, 'O', 'O', 8]
Better luck next time, you lost!
endGame called
gameOver
Of course the sequence is random, so it's not exactly the same every time, but it always replaces one random number at a time with 'O' until there's a 3-in-a-row, then tells me I lost.
So, it works exactly as intended. If your code doesn't work, you're doing something else wrong. Maybe you're setting up board or something else wrong in the initial setup?
Adding in your displayBoard and endGame code, it works until you say 'y' to play another game, at which point it calls some functions named game1 and game which don't exist, raising a NameError.
I also saw in your start function (from the comment that you since deleted, so this is from memory) that you were calling a function called getspot() in the game loop, instead of calling getCSpot(). If getspot is defined somewhere, the problem is presumably that you've got one correct function and one incorrect one. Or maybe it's not defined anywhere, and by "isn't working" and "does not put the O in the string at all" you mean "doesn't get called because the game halts with an exception before I ever get a chance"?
Now that you've posted the whole thing, there are a few obvious problems.
First, you never call getCSpot anywhere. That's why it doesn't do anything. Presumably you want this:
def mainGame():
gameOver = False
while gameOver == False:
displayBoard()
getspot()
didwin('X')
didwin('O')
getCSpot()
didwin('X')
didwin('O')
Also, in getspot, your if statements are all wrong. You're going to allow the move if board[playerSpot] != 'X', and also allow the move if board[playerSpot] != 'O'—in other words, always. And then you're going to count the player as moved unless playerSpot == 'O' is false—which it always is, because it's supposed to be a number.
I think you want this:
if board[playerSpot] == 'X':
playerSpot = raw_input('You have already chosen that spot. Please choose another. ')
elif board[playerSpot] == 'O':
playerSpot = raw_input('The computer chose that spot already. Please choose another. ')
else:
board[playerSpot] = 'X'
spotchosen = True