I recently created a tic tac toe game with the min-max function. However, I keep getting an error for stack overflow and recursion depth. How would you optimize this such as that it does not happen. I created the Tic Tac Toe game initially. Then I included the min-max algorithm. If there anyway to make the code faster or optimize the function. This would really help thanks
board = ["."] * 9
wining_comb = [[0,1,2],[3,4,5],[6,7,8],[0,3,6],[1,4,7],[2,5,8],[3,4,6],[0,4,8]]
game = True
key = {
"x": 1,
"O":-1,
}
def new_board():
print (board[0] + "|" + board[1] + "|" + board[2])
print (board[3] + "|" + board[4] + "|" + board[5])
print (board[6] + "|" + board[7] + "|" + board[8])
new_board()
def wining(comb):
global game
for l in range(len(wining_comb)):
a = wining_comb[l][0]
f = wining_comb[l][1]
v = wining_comb[l][2]
if comb[a] == comb[f] == comb[v] == "O" or "x" == comb[a] == comb[f] == comb[v]:
game = False
return a
break
else:
game = True
break
def minmax(board,depth, ismax):
if wining(board) != None:
score = key[wining(board)]
return score
else:
if ismax == True:
bestscore = float('-inf')
for k in range(len(board)):
if board[k] == ".":
board[k] == "x"
score = minmax(board,depth+1,False)
board[k] == '.'
bestscore = max(bestscore, score)
return bestscore
else:
bestscore = float('inf')
for k in range(len(board)):
if board[k] == ".":
board[k] == "O"
score = minmax(board,depth+1,True)
board[k] == '.'
bestscore = min(bestscore,score)
return bestscore
def player1() :
bestscore = float('inf')
bestmove = 0
for k in range(len(board)):
if board[k] == ".":
board[k] == "x"
score = minmax(board,0, False)
board[k] == "."
if score > bestscore:
bestscore = score
bestmove = k
board[bestmove] = "x"
new_board()
def player2():
number = int(input("Please enter your poistion?") )
board[number - 1 ] = "O"
new_board()
wining(board)
while game==True:
player1()
player2()
Related
--------- Global Variables -----------
# Will hold our game board data
board = ["-", "-", "-",
"-", "-", "-",
"-", "-", "-"]
# Lets us know if the game is over yet
game_still_going = True
# Tells us who the winner is
winner = None
# Tells us who the current player is (X goes first)
current_player = "X"
# ------------- Functions ---------------
# Play a game of tic tac toe
def play_game():
# Show the initial game board
display_board()
# Loop until the game stops (winner or tie)
while game_still_going:
# Handle a turn
handle_turn(current_player)
# Check if the game is over
check_if_game_over()
# Flip to the other player
flip_player()
# Since the game is over, print the winner or tie
if winner == "X" or winner == "O":
print(winner + " won.")
elif winner == None:
print("Tie.")
# Display the game board to the screen
def display_board():
print("\n")
print(board[0] + " | " + board[1] + " | " + board[2] + " 1 | 2 | 3")
print(board[3] + " | " + board[4] + " | " + board[5] + " 4 | 5 | 6")
print(board[6] + " | " + board[7] + " | " + board[8] + " 7 | 8 | 9")
print("\n")
# Handle a turn for an arbitrary player
def handle_turn(player):
# Get position from player
print(player + "'s turn.")
position = input("Choose a position from 1-9: ")
# Whatever the user inputs, make sure it is a valid input, and the spot is open
valid = False
while not valid:
# Make sure the input is valid
while position not in ["1", "2", "3", "4", "5", "6", "7", "8", "9"]:
position = input("Choose a position from 1-9: ")
# Get correct index in our board list
position = int(position) - 1
# Then also make sure the spot is available on the board
if board[position] == "-":
valid = True
else:
print("You can't go there. Go again.")
# Put the game piece on the board
board[position] = player
# Show the game board
display_board()
# Check if the game is over
def check_if_game_over():
check_for_winner()
check_for_tie()
# Check to see if somebody has won
def check_for_winner():
# Set global variables
global winner
# Check if there was a winner anywhere
row_winner = check_rows()
column_winner = check_columns()
diagonal_winner = check_diagonals()
# Get the winner
if row_winner:
winner = row_winner
elif column_winner:
winner = column_winner
elif diagonal_winner:
winner = diagonal_winner
else:
winner = None
# Check the rows for a win
def check_rows():
# Set global variables
global game_still_going
# Check if any of the rows have all the same value (and is not empty)
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 any row does have a match, flag that there is a win
if row_1 or row_2 or row_3:
game_still_going = False
# Return the winner
if row_1:
return board[0]
elif row_2:
return board[3]
elif row_3:
return board[6]
# Or return None if there was no winner
else:
return None
# Check the columns for a win
def check_columns():
# Set global variables
global game_still_going
# Check if any of the columns have all the same value (and is not empty)
column_1 = board[0] == board[3] == board[6] != "-"
column_2 = board[1] == board[4] == board[7] != "-"
column_3 = board[2] == board[5] == board[8] != "-"
# If any row does have a match, flag that there is a win
if column_1 or column_2 or column_3:
game_still_going = False
# Return the winner
if column_1:
return board[0]
elif column_2:
return board[1]
elif column_3:
return board[2]
# Or return None if there was no winner
else:
return None
# Check the diagonals for a win
def check_diagonals():
# Set global variables
global game_still_going
# Check if any of the columns have all the same value (and is not empty)
diagonal_1 = board[0] == board[4] == board[8] != "-"
diagonal_2 = board[2] == board[4] == board[6] != "-"
# If any row does have a match, flag that there is a win
if diagonal_1 or diagonal_2:
game_still_going = False
# Return the winner
if diagonal_1:
return board[0]
elif diagonal_2:
return board[2]
# Or return None if there was no winner
else:
return None
# Check if there is a tie
def check_for_tie():
# Set global variables
global game_still_going
# If board is full
if "-" not in board:
game_still_going = False
return True
# Else there is no tie
else:
return False
# Flip the current player from X to O, or O to X
def flip_player():
# Global variables we need
global current_player
# If the current player was X, make it O
if current_player == "X":
current_player = "O"
# Or if the current player was O, make it X
elif current_player == "O":
current_player = "X"
# ------------ Start Execution -------------
# Play a game of tic tac toe
play_game()
So I am trying to write a unit test for this code, so for example I am trying to check the def check_columns() function.
So far I came up with:
import unittest
import Tic_tac_toe
class TestGame(unittest.TestCase):
def test_check_for_column(self):
columns_1 = None
self.assertEqual(Tic_tac_toe.check_columns(), columns_1)
This checks out because initially, there is no input so I get None but I am trying to input "x" in the column and see if it returns the winner. How would I do that?
I am building a Tic Tac Toe AI. Here are the rules for the AI:
If there is a winning move, play it.
If the opponent has a winning move, block it.
Otherwise, play randomly.
Here's the code:
# main.py
# Prorities:
# - If there is a winning move, play it
# - If the opponent has a winning move, block it.
# - If nothing to block, make a random move.
import random
import time
import copy
boxes = []
for i in range(3):
row = []
for j in range(3):
row.append(" ")
boxes.append(row)
def printBoard():
to_print = ""
to_print += " " + boxes[0][0] + " | " + boxes[0][1] + " | " + boxes[0][2] + " \n"
to_print += "---+---+---\n"
to_print += " " + boxes[1][0] + " | " + boxes[1][1] + " | " + boxes[1][2] + " \n"
to_print += "---+---+---\n"
to_print += " " + boxes[2][0] + " | " + boxes[2][1] + " | " + boxes[2][2] + " \n"
return to_print
turn = random.randint(1, 2)
if turn == 1:
coin = "you (X)"
else:
coin = "the AI (O)"
print("The coin flip shows", coin, "will go first!")
input("Press Enter to begin! ")
def checkWin(boxes):
win = False
who = " "
for i in range(3):
if boxes[i][0] == boxes[i][1] and boxes[i][1] == boxes[i][2]:
who = boxes[i][0]
if who != " ":
win = True
for i in range(3):
if boxes[0][i] == boxes[1][i] and boxes[2][i] == boxes[1][i]:
who = boxes[0][i]
if who != " ":
win = True
if boxes[0][0] == boxes[1][1] and boxes[1][1] == boxes[2][2]:
who = boxes[0][0]
if who != " ":
win = True
if boxes[0][2] == boxes[1][1] and boxes[1][1] == boxes[2][0]:
who = boxes[0][2]
if who != " ":
win = True
return win, who
def checkTie(boxes):
for row in boxes:
for box in boxes:
if box != "X" and box != "O":
return False
return True
def checkMove(boxes, player):
for i in range(3):
for j in range(3):
if boxes[i][j] != "X" and boxes[i][j] != "O":
boxCopy = copy.deepcopy(boxes)
boxCopy[i][j] = player
win, who = checkWin(boxCopy)
if win:
return True, i, j
return False, 0, 0
while True:
print("Check 1")
win, who = checkWin(boxes)
if win and who == "X":
print("Player X has won.")
print(" ")
print(printBoard())
break
elif win and who == "O":
print("Player O has won.")
print(" ")
print(printBoard())
break
elif checkTie(boxes) == True:
print("It has been concluded as a tie.")
break
print("Check 2")
if turn == 1:
print("")
print(printBoard())
row = (int(input("Pick a row to play: ")) -1)
col = (int(input("Pick a column to play: ")) -1)
if ((row < 4 and row > -1) and (col < 4 and col > -1)) and (boxes[row][col] == " "):
boxes[row][col] = "X"
turn = 2
else:
print("Sorry, that is not allowed.")
print(" ")
# Prorities:
# - If there is a winning move, play it
# - If the opponent has a winning move, block it.
# - If nothing to block, make a random move.
else:
print("")
print(printBoard())
print("[*] AI is choosing...")
time.sleep(1)
row = random.randint(0, 2)
col = random.randint(0, 2)
winMove, winRow, winCol = checkMove(boxes, "O")
lossMove, lossRow, lossCol = checkMove(boxes, "X")
if winMove and (boxes[winRow][winCol] != "X" and boxes[winRow][winCol] != "O"):
boxes[winRow][winCol] = "O"
turn = 1
print("Statement 1: Win play")
elif lossMove and (boxes[lossRow][lossCol] != "X" and boxes[lossRow][lossCol] != "O"):
boxes[lossRow][lossCol] = "O"
turn = 1
print("Statement 2: Block play")
elif boxes[row][col] != "X" and boxes[row][col] != "O":
boxes[row][col] = "O"
turn = 1
print("Statement 3: Random play")
else:
print("Statement 4: None")
print("Check 3")
The problem occurs when there is a tie. Either the function checkTie(), or the if statement isn't working. You might see a couple print('Check #') every once in a while. When you run the code and it's a tie, it shows all the checks going by. Which means it is passing through the check. When there is a tie, it just keeps doing the loop and repeating its turn but not making a move.
What is the mistake and how can I do this correctly?
I think your function should be
def checkTie(boxes):
for row in boxes:
for box in row:
if box != "X" and box != "O":
return False
return True
You mistyped ( I think) boxes for row in the second for statement.
def checkTie(boxes):
if any(" " in box for box in boxes):
return False
return True
Change your checkTie function to this
The rest is all good.
I am currently learning python and trying to build a tic tac toe game. I wrote a program to prevent the user repeating the same input but when I repeat the same number two times, the program starts looping continuously without stopping. Could someone give me advice on how to rectify this issue? see below the code:
from tabulate import tabulate
# define the board
board = ["_", "_", "_",
"_", "_", "_",
"_", "_", "_"]
# Current player
current_player = "X"
winner = None
game_still_on = True
def play_game():
while game_still_on:
position()
board_display()
handle_player()
winner_check()
winner_check2()
def handle_player():
global current_player
if current_player == "X":
current_player = "O"
elif current_player == "O":
current_player = "X"
def board_display():
board_row1 = [board[0], board[1], board[2]]
board_row2 = [board[3], board[4], board[5]]
board_row3 = [board[6], board[7], board[8]]
com_board = [board_row1,
board_row2,
board_row3]
print(tabulate(com_board, tablefmt="grid"))
# position input
def position():
global board
print(current_player+"'s turn")
positions = input("enter 1-9")
valid = False
while not valid:
while int(positions) >= 10 or 0 >= int(positions):
positions = input("Choose a position from 1 -9")
positions = int(positions)
if board[positions-1] == "_":
valid = True
else:
print("Choose another")
board[positions - 1] = current_player
def winner_check():
if board[0] == board[1] == board[2] != "_":
return board[0]
elif board[3] == board[4] == board[5] != "_":
return board[3]
elif board[6] == board[7] == board[8] != "_":
return board[6]
elif board[0] == board[3] == board[6] != "_":
return board[0]
elif board[1] == board[4] == board[7] != "_":
return board[1]
elif board[2] == board[5] == board[8] != "_":
return board[2]
elif board[0] == board[4] == board[8] != "_":
return board[0]
elif board[2] == board[4] == board[6] != "_":
return board[1]
else:
return None
def winner_check2():
row_winner = winner_check()
if row_winner:
global game_still_on
global winner
winner = row_winner
print((winner+ " won"))
game_still_on = False
play_game()
Let's look at this function:
# position input
def position():
global board
print(current_player+"'s turn")
positions = input("enter 1-9")
valid = False
while not valid:
while int(positions) >= 10 or 0 >= int(positions):
positions = input("Choose a position from 1 -9")
positions = int(positions)
if board[positions-1] == "_":
valid = True
else:
print("Choose another")
board[positions - 1] = current_player
This has nested validation loops. The inner one checks the range of the input integer (if it is an integer -- otherwise it throws an exception) and requests input until it's in range. That's fine.
Then in the outer validation loop, it checks if the requested space is unoccupied. If so, fine. If not, it prompts the user to choose another. But the input call is before the outer loop, so it just tries again to validate the same input that already failed.
Try moving the input into the outer loop:
# position input
def position():
global board
print(current_player+"'s turn")
valid = False
while not valid:
positions = input("enter 1-9")
while int(positions) >= 10 or 0 >= int(positions):
positions = input("Choose a position from 1 -9")
positions = int(positions)
if board[positions-1] == "_":
valid = True
else:
print("Choose another")
board[positions - 1] = current_player
I'd probably also change the inner loop to be just an if with a continue and make the handling of non-integer input more robust.
so this code is making a tic tac toe game and lets the users keep playing until there is a winner. However, my code is creating the array, and automatically deciding that player two is the winner. I ran it through the debugger, and it will create the array for the board, and will automatically pick player 2 the winner. I know for a fact its after the array is made, but I cannot find out why. Any help is appreciated, thanks so much.
"""tictactoe game for 2 players"""
choices = []
for x in range(1, 9):
choices.append(x)
breakpoint()
playerOneTurn = True
winner = False
def printBoard():
print('\n -----')
print('|' + choices[0] + '|' + choices[1] + '|' + choices[2] + '|')
print(' -----')
print('|' + choices[3] + '|' + choices[4] + '|' + choices[5] + '|')
print(' -----')
print('|' + choices[6] + '|' + choices[7] + '|' + choices[8] + '|')
print(' -----\n')
while winner:
printBoard()
if playerOneTurn:
print("Player 1:")
else:
print("Player 2:")
try:
choice = int(input(">> "))
except:
print("please enter a valid field")
continue
if choices[choice - 1] == 'X' or choices[choice] == 'O':
print("illegal move, please try again")
continue
if playerOneTurn:
choices[choice - 1] = "X"
else:
choices[choice - 1] = "O"
playerOneTurn = not playerOneTurn
for x in range(0, 3):
y = x * 3
if choices[y] == choices[(y + 1)] and choices[y] == choices[(y + 2)]:
winner = True
printBoard()
if choices[x] == choices[(x + 3)] and choices[x] == choices[(x + 6)]:
winner = True
printBoard()
if((choices[0] == choices[4] and choices[0] == choices[8]) or
(choices[2] == choices[4] and choices[4] == choices[6])):
winner = True
printBoard()
print("Player " + str(int(playerOneTurn + 1)) + " wins!\n")
I am a first semester student and I am trying to restart my game. Problem is I dont really know how even though the game works fine. I assumed the solution would be to call the function play() again but for the life of me im stuck!
Tried creating a while loop to try and loop the game while still playing
while playing == True:
play()
continue_play = input("Continue playing? (y/n)")
if continue_play.lower() == "n":
playing = False
else:
new_game = play()
show_board()
new_game()
This is the while loop....new game returns 'nonetype' not callable....
below is my actual code for entire game:
playing = True
#Global variables to be used
game_active = True
champion = None
active_player = " X "
#Displays board
def show_board():
print(" 1 2 3")
print("1 " + board[0] + " | " + board[1] + " | " + board[2])
print(" ----+-----+----")
print("2 " + board[3] + " | " + board[4] + " | " + board[5])
print(" ----+-----+----")
print("3 " + board[6] + " | " + board[7] + " | " + board[8])
#play game of TIC TAC TOE
def play():
global board
board = [" ", " ", " ",
" ", " ", " ",
" ", " ", " "]
#display the game board to users
show_board()
#while game is still active
while game_active:
#Whos turn is it?
turns(active_player)
#check if game has met finishing requirements
check_game_done()
#Change player turn
change_player()
#game has ended
if champion == " X " or champion == " O ":
print(champion + " Is the winner!")
elif champion == None:
print(" Draw ")
#function for handling player turns
def turns(player):
print(player + "'s Turn.")
player_position = input("Please choose a number for your move between 1-9: ")
ok = False
while not ok:
while player_position not in ["1", "2", "3", "4", "5", "6", "7", "8", "9"]:
player_position = input(" Please choose a number for your move between 1-9: ")
player_position = int(player_position) - 1
if board[player_position] == " ":
ok = True
else:
print("Sorry this spot is taken.")
board[player_position] = player
show_board()
#function to check over game to see if game completed
def check_game_done():
check_win()
check_draw()
def check_win():
#using global variable from above code
global champion
#rows
winning_row = check_rows()
#columns
winning_column = check_columns()
#diagonals
winning_diagonal = check_diagonals()
if winning_row:
#winner found
champion = winning_row
elif winning_column:
#winner found
champion = winning_column
elif winning_diagonal:
#winner found
champion = winning_diagonal
else:
#no winner found
champion = None
def check_rows():
#call global variable to check if game still active
global game_active
#check rows for winning condition
row1 = board[0] == board[1] == board[2] != " "
row2 = board[3] == board[4] == board[5] != " "
row3 = board[6] == board[7] == board[8] != " "
#winning conditions met?
if row1 or row2 or row3:
game_active = False
#who won?
if row1:
return board[0]
elif row2:
return board[3]
elif row3:
return board[6]
else:
return None
def check_columns():
#call global variable to check if game still active
global game_active
#check columns for winning condition
column1 = board[0] == board[3] == board[6] != " "
column2 = board[1] == board[4] == board[7] != " "
column3 = board[2] == board[5] == board[8] != " "
#Win conditions met
if column1 or column2 or column3:
game_active = False
#who won
if column1:
return board[0]
elif column2:
return board[1]
elif column3:
return board[3]
else:
return None
def check_diagonals():
#call global variable to check if game still active
global game_active
#check diagonals for winning condition
diagonal_1 = board[0] == board[4] == board[8] != " "
diagonal_2 = board[2] == board[4] == board[6] != " "
#win conditon met
if diagonal_1 or diagonal_2:
game_active = False
#who won
if diagonal_1:
return board[0]
elif diagonal_2:
return board[2]
else:
return None
# Checking to see if conditions for a draw have been met
def check_draw():
global game_active
if " " not in board:
game_active = False
return True
else:
return False
# Using function to decide whos turn it is
def change_player():
global active_player
if active_player == " X ":
active_player = " O "
elif active_player == " O ":
active_player = " X "
return None
# Restarting game again
while playing == True:
play()
continue_play = input("Continue playing? (y/n)")
if continue_play.lower() == "n":
playing = False
else:
new_game = play()
show_board()
new_game()
play()
Change the while loop to:
...
while playing == True:
play()
continue_play = input("Continue playing? (y/n)")
if continue_play.lower() == "n":
playing = False
else:
game_active = True
champion = None
play()
show_board()
...
Now it will work.