I implemented this very simple game for my book Python 3 Exercises for Beginners.
Source Code available here:
https://gitlab.com/carles.mateo/python-classes/-/blob/main/2021-09-10/game_tic-tac-toe.py
class TicTacToe:
def __init__(self):
self.a_a_s_map = []
self.generate_map()
def generate_map(self):
self.a_a_s_map = []
for i_y in range(3):
a_s_pos_x = [" ", " ", " "]
self.a_a_s_map.append(a_s_pos_x)
def get_map(self):
s_map = ""
s_map = s_map + " 1 2 3\n"
s_map = s_map + " -------------\n"
for i_y in range(3):
s_map = s_map + str(i_y + 1) + " |"
for s_char in self.a_a_s_map[i_y]:
s_map = s_map + " " + s_char + " |"
s_map = s_map + "\n"
s_map = s_map + " -------------\n"
return s_map
def validate_move(self, s_char, i_x, i_y):
"""
Validates the movement and updates the map
:param s_char:
:param i_x:
:param i_y:
:return: bool
"""
i_x = i_x - 1
i_y = i_y - 1
if self.a_a_s_map[i_y][i_x] == " ":
self.a_a_s_map[i_y][i_x] = s_char
return True
return False
def check_win(self):
for s_char in ["O", "X"]:
# check horizontal
for i_y in range(3):
i_horizontal_match = 0
for i_x in range(3):
if self.a_a_s_map[i_y][i_x] == s_char:
i_horizontal_match = i_horizontal_match + 1
if i_horizontal_match == 3:
return True
# Check vertical
for i_x in range(3):
i_vertical_match = 0
for i_y in range(3):
if self.a_a_s_map[i_y][i_x] == s_char:
i_vertical_match = i_vertical_match + 1
if i_vertical_match == 3:
return True
# Check diagonal
if self.a_a_s_map[1][1] == s_char:
if self.a_a_s_map[0][0] == s_char and self.a_a_s_map[2][2] == s_char:
return True
if self.a_a_s_map[0][2] == s_char and self.a_a_s_map[2][0] == s_char:
return True
return False
def check_stale(self):
for i_y in range(3):
for i_x in range(3):
if self.a_a_s_map[i_y][i_x] == " ":
# Is not full
return False
# We checked all and all were full
return True
def get_from_keyboard(s_question, i_min, i_max):
i_number = 0
while True:
s_answer = input(s_question)
try:
i_number = int(s_answer)
except:
print("Please, type a number")
continue
if i_number < i_min or i_number > i_max:
print("Invalid value. Values should be between", i_min, "and", i_max)
continue
# Validations are Ok
break
return i_number
if __name__ == "__main__":
o_tictactoe = TicTacToe()
while True:
s_map = o_tictactoe.get_map()
print(s_map)
while True:
i_x = get_from_keyboard("Your move O for x: ", i_min=1, i_max=3)
i_y = get_from_keyboard("Your move O for y: ", i_min=1, i_max=3)
b_valid_move = o_tictactoe.validate_move("O", i_x, i_y)
if b_valid_move is False:
print("Invalid move")
continue
break
s_map = o_tictactoe.get_map()
print(s_map)
b_check_win = o_tictactoe.check_win()
if b_check_win is True:
print("Player O wins!")
exit(0)
b_stale = o_tictactoe.check_stale()
if b_stale is True:
print("Nobody wins in war")
exit(0)
while True:
i_x = get_from_keyboard("Your move X for x: ", i_min=1, i_max=3)
i_y = get_from_keyboard("Your move X for y: ", i_min=1, i_max=3)
b_valid_move = o_tictactoe.validate_move("X", i_x, i_y)
if b_valid_move is False:
print("Invalid move")
continue
break
s_map = o_tictactoe.get_map()
print(s_map)
b_check_win = o_tictactoe.check_win()
if b_check_win is True:
print("Player X wins!")
exit(0)