I am trying to make a minimax tic-tac-toe game because I am a novice at Python and I am trying to figure out how a simple AI-mini-max game works. The AI for some reason still goes in order in which the spot turns up on the list for the board.
Ex: if the top right spot was first in the "b" list, it picks it first. It looks like it is calculating the scores, but I do not think it is utilizing them for some reason. I want it to not go in order of what the spaces in the board. I can't figure out a way to replace the code that places the "O".
import random
import math
three = [0, 0, 0]
game = True
turnai = False
result = ""
b = [" ", " ", " ", " ", " ", " ", " ", " ", " "]
x = "X"
o = "O"
#Spots on the board Ex: ur = upper right, mm = middle middle, lm = lower middle
ur = b[2]
um = b[1]
ul = b[0]
ml = b[3]
mm = b[4]
mr = b[5]
ll = b[6]
lm = b[7]
lr = b[8]
cw = " "
AI = ""
player = ""
#Board setup
def board(ul, um, ur, ml, mm, mr, ll, lm, lr):
print("|" + " " + ul + " " + "|" + " " + um + " " + "|" + " " + ur + " " + "|")
print("|" + " " + ml + " " + "|" + " " + mm + " " + "|" + " " + mr + " " + "|")
print("|" + " " + ll + " " + "|" + " " + lm + " " + "|" + " " + lr + " " + "|")
board(ul, um, ur, ml, mm, mr, ll, lm, lr)
print("This is the game of tic-tac-toe")
print("You will be playing against an AI")
print("Type where you want to place your letter Ex: ur = upper right, mm = middle middle, and ll = lower right")
first = "P"
player = "X"
AI = "O"
#Checks if someone has won
def checkwinner():
ur = b[2]
um = b[1]
ul = b[0]
ml = b[3]
mm = b[4]
mr = b[5]
ll = b[6]
lm = b[7]
lr = b[8]
row1 = [ul, ml, ll]
row2 = [um, mm, lm]
row3 = [ur, mr, lr]
column1 = [ul, um, ur]
column2 = [ml, mm, mr]
column3 = [ll, lm, lr]
diagonal1 = [ul, mm, lr]
diagonal2 = [ur, mm, ll]
if row1 == ["X", "X", "X"] or row2 == ["X", "X", "X"] or row3 == ["X", "X", "X"] or column1 == ["X", "X",
"X"] or column2 == [
"X", "X", "X"] or column3 == ["X", "X", "X"] or diagonal1 == ["X", "X", "X"] or diagonal2 == ["X", "X",
"X"]:
if player == x:
print("You win! (X)")
return "X"
if player != x:
print("You lose!")
return "O"
if row1 == ["O", "O", "O"] or row2 == ["O", "O", "O"] or row3 == ["O", "O", "O"] or column1 == ["O", "O",
"O"] or column2 == [
"O", "O", "O"] or column3 == ["O", "O", "O"] or diagonal1 == ["O", "O", "O"] or diagonal2 == ["O", "O",
"O"]:
if player == o:
print("You win! (O)")
return "X"
if player != o:
print("You lose")
return "O"
if b[0] != " " and b[1] != " " and b[2] != " " and b[3] != " " and b[4] != " " and b[5] != " " and b[
6] != " " and b[7] != " " and b[8] != " ":
print("TIE!")
winner = True
return "0"
return "null"
#Minimax Algorithm
def minimax(b, depth, isMaximizing):
result = checkwinner()
if result != "null":
score = scores[result] + score
return score
if (isMaximizing):
bestScore = -math.inf
j = 0
for str in b:
if str == " ":
b[j] = AI
score = minimax(b, depth + 1, False) + score
b[j] = " "
bestScore = max(score, bestScore)
j += 1
return bestScore
else:
bestScore = math.inf
k = 0
for str in b:
if str == " ":
b[k] = player
score = minimax(b, depth + 1, True) + score
b[k] = " "
bestScore = min(score, bestScore)
k += 1
return bestScore
#Game Start loop
if (first == "P"):
while (game == True):
i = 0
scores = {
'O': 1,
'X': -1,
'0': 0
}
#AI turn
bestScore = -math.inf
turnai = False
i = 0
for str in b:
if str == " ":
b[i] = AI
score = minimax(b, 0, True)
b[i] = " "
print(score)
if score > bestScore and turnai == False:
bestScore = score
b[i] = AI
turnai = True
i += 1
turnai = False
print("")
# b = [ul, um, ur, ml, mm, mr, ll, lm, lr]
ur = b[2]
um = b[1]
ul = b[0]
ml = b[3]
mm = b[4]
mr = b[5]
ll = b[6]
lm = b[7]
lr = b[8]
#Prints Board
board(b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7], b[8])
cw = checkwinner()
#Checks if game ended
if cw == "X" or cw == "O" or cw == "0":
game = False
break
#Player turn
print("Where do you want to place your letter?")
turn = input(": ")
if turn == "ur" and ur == " ":
b[2] = player
uru = True
if turn == "um" and um == " ":
b[1] = player
umu = True
if turn == "ul" and ul == " ":
b[0] = player
ulu = True
if turn == "mr" and mr == " ":
b[5] = player
mru = True
if turn == "mm" and mm == " ":
b[4] = player
mmu = True
if turn == "ml" and ml == " ":
b[3] = player
mlu = True
if turn == "lr" and lr == " ":
b[8] = player
lru = True
if turn == "lm" and lm == " ":
b[7] = player
lmu = True
if turn == "ll" and ll == " ":
b[6] = player
llu = True
#Prints Board
board(b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7], b[8])
sw = checkwinner()
#Checks if game needs to be ended
if cw == "X" or cw == "O" or cw == "0":
game = False
break
str
as a variable name as it is a builtin.enumerate
to get the index and the value from a list as you iterate.scores
should be defined in minimax
because that's the only place it is used.AI is taking the first spot available because of this section of code:
bestScore = -math.inf
turnai = False
i = 0
for str in b:
if str == " ":
b[i] = AI
score = minimax(b, 0, True)
b[i] = " "
print(score)
if score > bestScore and turnai == False: # Allways true first loop
bestScore = score
b[i] = AI
turnai = True # ^ Never true in later loops
Which ironically only occurs when turnai == false
turnai
boolean in game loop because you explicitly code both the ai and user turns.boolean == True
just say while game:
break
if your control bool is set to false.sw = checkwinner()
then you examine the value of cw
I could fix this for you but I think I've given you enough to work with here and I will tell you that your concept is sound(ish) so if you just keep with it a little further you should get some satisfactory results...
The major logical flaw here is that you never actually count how many wins a given choice leaves... Your minimax function just returns 1 every time.