# WARNING WARNING WARNING: IF YOU MOVE ANYTHING OR EDIT ANYTHING IN THE NEXT CELL, EVERTHING WILL SCATTER!!!!
# To play:
# 1. Run the cell below
# "Input Command >" shows up.
# the command you put determines the game to play.
# You can play against "easy" or "medium" computer
# Or you can play with another user
# 2. To play against easy computer: start easy user
# Input Command > start easy user
# 3. To play against medium computer: start medium user
# Input Command > start medium user
# OR
# Input Command > start user medium
# 4. Next, you need to supply your moves, i and j, separated by space
# Enter the coordinates (e.g 1 1): > 2 2
# 5. The board coordinates. It is a 3 x 3 board
# {1 3} {2 3} {3 3}
# {1 2} {2 2} {3 2}
# {1 1} {2 1} {3 1}
# 6. Winning: You need all X or all O to take a row, or a column, or a diagonal
# 7. Game restart after one ends: wins or draw.
# 8. To quit game type exit in Input Command
# Input Command > exit
# 7. Goodluck
import random
class TicTacToe:
def __init__(self):
self.updated = ['_', '_', '_', '_', '_', '_', '_', '_', '_']
self.all_position = [i for i in range(9)]
self.pos_played = []
self.idx = {'1': {'1': 6, '2': 3, '3': 0},
'2': {'1': 7, '2': 4, '3': 1},
'3': {'1': 8, '2': 5, '3': 2}}
self.player1 = 'X'
self.player2 = 'O'
self.player_turn = self.player1
self.wins_matrix = [self.updated[:3],
self.updated[3:6],
self.updated[6:],
self.updated[2:8:2],
self.updated[:9:4],
self.updated[:9:3],
self.updated[1:9:3],
self.updated[2:9:3]]
def reboot(self):
self.updated = ['_', '_', '_', '_', '_', '_', '_', '_', '_']
def prints(self):
print(f'---------\n| {self.updated[0]} {self.updated[1]} {self.updated[2]} |\n| {self.updated[3]} {self.updated[4]} {self.updated[5]} |\n| {self.updated[6]} {self.updated[7]} {self.updated[8]} |\n---------')
def status(self):
self.wins_matrix = [self.updated[:3],
self.updated[3:6],
self.updated[6:],
self.updated[2:8:2],
self.updated[:9:4],
self.updated[:9:3],
self.updated[1:9:3],
self.updated[2:9:3]]
x_wins = any([all([True if i == 'X' else False for i in j]) for j in self.wins_matrix])
o_wins = any([all([True if i == 'O' else False for i in j]) for j in self.wins_matrix])
draw = all([all([True if i != '_' else False for i in j]) for j in self.wins_matrix])
if x_wins:
return 'X wins'
elif o_wins:
return 'O wins'
elif draw:
return 'Draw'
else:
return 'Game not finished'
def user(self):
while True:
moves = input('Enter the coordinates (e.g 1 1): > ').strip().split()
if moves[0].isnumeric() and moves[1].isnumeric():
if (0 < int(moves[0]) <= 3) and (0 < int(moves[1]) <= 3):
pos_idx = self.idx[moves[0]][moves[1]]
if self.updated[pos_idx] is not '_':
print('This cell is occupied! Choose another one')
continue
else:
self.updated[pos_idx] = self.player_turn
self.pos_played.append(pos_idx)
if self.player_turn == self.player1:
self.player_turn = self.player2
else:
self.player_turn = self.player1
return None
else:
print('Coordinates should be from 1 to 3!')
continue
else:
print('You should enter numbers!')
continue
def easy(self):
print('Making move level "easy"')
pos_idx = random.choice(list(set(self.all_position) - set(self.pos_played)))
self.updated[pos_idx] = self.player_turn
self.pos_played.append(pos_idx)
if self.player_turn == self.player1:
self.player_turn = self.player2
else:
self.player_turn = self.player1
def medium(self):
self.wins_matrix = [self.updated[:3],
self.updated[3:6],
self.updated[6:],
self.updated[2:8:2],
self.updated[:9:4],
self.updated[:9:3],
self.updated[1:9:3],
self.updated[2:9:3]]
print('Making move level "medium"')
if first_player == 'medium':
win_move = [sum([True if i == 'X' else False for i in j]) for j in self.wins_matrix]
def_move = [sum([True if i == 'O' else False for i in j]) for j in self.wins_matrix]
elif second_player == 'medium':
win_move = [sum([True if i == 'O' else False for i in j]) for j in self.wins_matrix]
def_move = [sum([True if i == 'X' else False for i in j]) for j in self.wins_matrix]
a, b = sum(win_move), sum(def_move)
if a == 2 and b == 2:
lst_idx = win_move.index(max(win_move))
pos_idx = self.wins_matrix[lst_idx].index('_')
elif a < 2 and b == 2:
lst_idx = def_move.index(max(def_move))
pos_idx = self.wins_matrix[lst_idx].index('_')
elif a == 2 and b < 2:
lst_idx = win_move.index(max(win_move))
pos_idx = self.wins_matrix[lst_idx].index('_')
else:
pos_idx = random.choice(list(set(self.all_position) - set(self.pos_played)))
self.updated[pos_idx] = self.player_turn
self.pos_played.append(pos_idx)
if self.player_turn == self.player1:
self.player_turn = self.player2
else:
self.player_turn = self.player1
def check(self):
if (self.status().split())[-1] in ['wins', 'Draw']:
return True
else:
return False
def reset(self):
print(' '.join(self.status().split()))
self.reboot()
self.player_turn = 'X'
self.pos_played = []
class PlayGame(TicTacToe):
def play(self):
while True:
start_command = input('Input command: > ')
command_split = start_command.split()
if 'exit' in command_split:
return None
else:
if len(command_split) != 3:
print('Bad parameters!')
else:
if command_split[0] == 'start':
global first_player
global second_player
_, first_player, second_player = command_split
if first_player == second_player == 'easy':
self.prints()
while '_' in self.updated:
self.easy()
self.prints()
if self.check():
self.reset()
break
elif first_player == 'easy' and second_player == 'user':
self.prints()
while '_' in self.updated:
if self.player_turn == self.player1:
self.easy()
self.prints()
elif self.player_turn == self.player2:
self.user()
self.prints()
if self.check():
self.reset()
break
elif first_player == 'user' and second_player == 'easy':
self.prints()
while '_' in self.updated:
if self.player_turn == self.player1:
self.user()
self.prints()
elif self.player_turn == self.player2:
self.easy()
self.prints()
if self.check():
self.reset()
break
elif first_player == 'user' and second_player == 'user':
self.prints()
while '_' in self.updated:
if self.player_turn == self.player1:
self.user()
self.prints()
elif self.player_turn == self.player2:
self.user()
self.prints()
if self.check():
self.reset()
break
elif first_player == 'user' and second_player == 'medium':
self.prints()
while '_' in self.updated:
if self.player_turn == self.player1:
self.user()
self.prints()
elif self.player_turn == self.player2:
self.medium()
self.prints()
if self.check():
self.reset()
break
elif first_player == 'medium' and second_player == 'user':
self.prints()
while '_' in self.updated:
if self.player_turn == self.player1:
self.medium()
self.prints()
elif self.player_turn == self.player2:
self.user()
self.prints()
if self.check():
self.reset()
break
elif first_player == 'medium' and second_player == 'medium':
self.prints()
while '_' in self.updated:
if self.player_turn == self.player1:
self.medium()
self.prints()
elif self.player_turn == self.player2:
self.medium()
self.prints()
if self.check():
self.reset()
break
elif first_player == 'medium' and second_player == 'easy':
self.prints()
while '_' in self.updated:
if self.player_turn == self.player1:
self.medium()
self.prints()
elif self.player_turn == self.player2:
self.easy()
self.prints()
if self.check():
self.reset()
break
elif first_player == 'easy' and second_player == 'medium':
self.prints()
while '_' in self.updated:
if self.player_turn == self.player1:
self.easy()
self.prints()
elif self.player_turn == self.player2:
self.medium()
self.prints()
if self.check():
self.reset()
break
PlayGame().play()
Input command: > start user medium --------- | _ _ _ | | _ _ _ | | _ _ _ | --------- Enter the coordinates (e.g 1 1): > 1 1 --------- | _ _ _ | | _ _ _ | | X _ _ | --------- Making move level "medium" --------- | _ _ _ | | _ _ _ | | X O _ | --------- Enter the coordinates (e.g 1 1): > 2 2 --------- | _ _ _ | | _ X _ | | X O _ | --------- Making move level "medium" --------- | _ O _ | | _ X _ | | X O _ | --------- Enter the coordinates (e.g 1 1): > 3 3 --------- | _ O X | | _ X _ | | X O _ | --------- X wins Input command: > start medium medium --------- | _ _ _ | | _ _ _ | | _ _ _ | --------- Making move level "medium" --------- | _ _ _ | | X _ _ | | _ _ _ | --------- Making move level "medium" --------- | _ O _ | | X _ _ | | _ _ _ | --------- Making move level "medium" --------- | _ X _ | | X _ _ | | _ _ _ | --------- Making move level "medium" --------- | O X _ | | X _ _ | | _ _ _ | --------- Making move level "medium" --------- | O X _ | | X _ _ | | _ _ X | --------- Making move level "medium" --------- | O X O | | X _ _ | | _ _ X | --------- Making move level "medium" --------- | O X O | | X _ _ | | X _ X | --------- Making move level "medium" --------- | O X O | | X O _ | | X _ X | --------- Making move level "medium" --------- | O X O | | X O X | | X _ X | --------- Making move level "medium" --------- | O X O | | X O X | | X O X | --------- Draw Input command: > exit