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.
Related
I simply followed the structure of basic Minimax functions with:
def player(board):
if Terminal(board) != False:
return None
else:
if turn(board) == "X":
value,move = max_value(board)
return move + 1
else:
value,move = min_value(board)
return move + 1
def max_value(board):
global arg
if Terminal(board) != False:
ut = Utility(board)
return ut,None
else:
v = -1000
move = None
for action in Actions(board):
aux,act = min_value(Result(board,action))
if aux > v:
v = aux
move = action
if v == 1:
return v,move
return v,move
def min_value(board):
if Terminal(board) != False:
ut = Utility(board)
return ut,None
else:
v = 1000
move = None
print(Actions(board))
for action in Actions(board):
aux,act = max_value(Result(board,action))
if aux < v:
v = aux
move = action
if v == -1:
return v,move
return v,move
player is called initially and returns the best possible move. The other functions are:
def Actions(board = list):
possible_moves = []
n = -1
for move in board:
n += 1
if move == None:
possible_moves.append(n)
return possible_moves
def Result(board,action):
dc_board = board.copy()
dc_board[action] = turn(board)
return dc_board
def Terminal(board):
if board[0] == board[1] == board[2] and board[0] != None:
return board[0]
elif board[3] == board[4] == board[5] and board[3] != None:
return board[3]
elif board[6] == board[7] == board[8] and board[6]!= None:
return board[6]
elif board[0] == board[3] == board[6] and board[0] != None:
return board[0]
elif board[1] == board[4] == board[7] and board[1] != None:
return board[1]
elif board[2] == board[5] == board[8] and board[2] != None:
return board[2]
elif board[0] == board[5] ==board[8] and board[0]!= None:
return board[0]
elif board[2] == board[4] == board[6] and board[2] != None:
return board[2]
else:
return False
def Utility(board):
result = Terminal(board)
if result == False:
return 0
elif result == "X":
return 1
elif result == "O":
return -1
else:
print("Result:")
print(result)
print("Board:")
print(board)
raise "Utility conditions were not met."
I checked the output of all of them independently yet they all seem to be logical. The player function simply returns moves in the order of the TicTacToe board, if a coordinate is full, it skips it, eg: ' if board[move] != None: board[move + 1] = "O" '
I see this a lot, the problem is in your Utility function. Your return value needs to be dependent on player turn. Right now you are returning 1 if 'X' wins, even if it is 'O' turn.
Also I think you need to return higher values to be able to later include depth in the score (to always find the shortest path to victory). Therefore change 1 and -1 to 10 and -10.
Pseudo code:
elif (result == "X" and turn == "X") or (result == "O" and turn == "O"):
return 10
elif (result == "X" and turn == "O") or (result == "O" and turn == "X"):
return -10
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.
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")
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()
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;