Let’s Talk about the finished product. An unbeatable tic tac toe game!
I finished!
It’s definitely not perfect, however it is an incredibly more improved game than the first time I created it. First of all it is much cleaner. My first time, I must say the functions were decently named. However, the white space was not consistent and also my equations were not spaced properly x+= 2 compared to x += 2
. I had fewer and larger functions, most of my functions did multiple things which made it tough to test, run, and debug.
Now my functions are smaller, properly named, and have a consistent clean look to them. Initially when I wanted to share my code, I would literally copy and paste, now I can send a link to Github, showing my progress.
Nice changes after rigorously learning about Clean Code and TDD for a month.
Here is some of my previous code when it came to running the AI, compared to my new code.
#first time
while True:
if letterXO == "o":
move()
if game_over():
sys.exit()
elif letterXO == "x":
moveO()
if game_over():
sys.exit()
def move():
time.sleep(1)
print("\n"*2)
computer()
global counter
counter +=1
grid()
if game_over():
sys.exit()
get_int()
counter +=1
print()
grid()
print("\n"*2+"Okay, it's my turn")
time.sleep(1)
exceptions()
end_move()
if game_over():
sys.exit()
def moveO():
global counter
get_int()
counter +=1
print()
grid()
if game_over():
sys.exit()
time.sleep(1)
exceptions()
end_move()
if game_over():
sys.exit()
time.sleep(1)
computerO()
counter +=1
print("\n"*2+"Okay, it's my turn")
print("\n"*2)
if game_over():
sys.exit()
grid()
print("\n"*2)
#new code
def play_computer(game_board, number_of_moves, X_turn):
while True:
print(gb.display_Game(game_board))
if X_turn:
ai_move = mm.minimax(game_board, number_of_moves, X_turn)[1]
game_board = ui.update_board(ai_move, game_board, X_turn)
Else:
game_board = ui.parse_input(game_board, X_turn)
if cgo.is_game_over(game_board):
congrats_message(game_board)
break
X_turn = not X_turn
Way cleaner in general, and let me also compare my previous computer logic with the Minimax algorithm.
#hundreds of lines like
def computer():
list[0] = "x"
#branch 1
if list[1] == "o" and counter >=2 and list[6] != "o" and list[8] != "o" and list[4] != "o":
list[4] = "x"
#branch2
elif list[2] == "o" and counter>=2:
list[6] = "x"
if list[3] == "o" and counter >=4:
list[8] ="x"
#branch 4
elif list[4] == "o" and counter >=2:
list[8] = "x"
#branch4.2
if list[2] == "o" and counter >=4:
list[6] ="x"
#branch4.6
elif list[6] == "o" and counter >=4:
list[2] ="x"
#branch4.1
elif list[1] == "o" and counter >=4:
list[7] = "x"
if list[6] == "o" and counter >=5 :
list[2] = "x"
if list[5] =="o" and counter >=5:
list[3] ="x"
#Compare that too
def minimax(gamestate, depth ,isX):
depth += 1
if cg.is_game_over(gamestate):
value = Value(gamestate)
return value / depth, None
if isX :
best_value = -100000000
for action in cg.actions(gamestate):
new_gamestate = copy.deepcopy(gamestate)
new_gamestate = ui.update_board(action, new_gamestate, isX)
value = minimax(new_gamestate, depth, not isX)[0]
if value > best_value:
best_value = value
best_action = action
return best_value, best_action
else:
best_value = 100000000
for action in cg.actions(gamestate):
new_gamestate = copy.deepcopy(gamestate)
new_gamestate = ui.update_board(action, new_gamestate, isX)
value = minimax(new_gamestate, depth, not isX)[0]
if value < best_value:
best_value = value
best_action = action
return best_value, best_action
I know I have a long way to go, but for now I am enjoying the victory of this second iteration.
Best,
Merl