-
Notifications
You must be signed in to change notification settings - Fork 0
/
tictactoe_procedural.py
177 lines (161 loc) · 5.72 KB
/
tictactoe_procedural.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
#!/usr/bin/env python3
"""
Project: TicTacToe - class exercise, proceudral version
TicTacToe - an easy procedural implementation to get started
Your task is to write a simple program which pretends to play
tic-tac-toe with a human player. To make it all easier for you, we've
decided to simplify the game. Here are our assumptions:
1.. The computer (i.e., your program) should play the game using 'X's;
the human player (e.g., you) should play the game using 'O's; the
first move belongs to the computer - it always puts its first 'X' in
the middle of the board.
2.. All the squares are numbered row by row starting with 1 (see the
example session below for reference) the human player inputs their
move by entering the number of the square they choose - the number
must be valid, i.e., it must be an integer, it must be > than 0 and
< than 10, and it cannot point to a field which is already occupied:
the program checks if the game is over.
3.. There are four possible verdicts: the game should continue, or the
game ends with a tie, your win, or the computer's win; the computer
responds with its move and the check is repeated.
4.. Don't implement any form of artificial intelligence - a random
field choice made by the computer is good enough for the game.
"""
from random import randrange
from sqlalchemy import null
HUMAN_PLAYER = 'O'
COMPUTER_PLAYER = 'X'
GAME_PLAYERS = [HUMAN_PLAYER, COMPUTER_PLAYER]
# Graphics for displaying the game board.
# ruler: 123*567 123*567 123*567
BOARD_LINER = '+-------+-------+-------+'
BOARD_SPACE = '| | | |'
BOARD_MOVES = '| {} | {} | {} |'
def calculate_next_move(game_board):
"""
Calculate the next move.
"""
print('Computer\'s move:')
positions = get_available_positions(game_board)
positions_count = len(positions)
if positions_count > 0:
# Randomly select an available position.
random_move = randrange(positions_count)
row, col = positions[random_move]
game_board[row][col] = COMPUTER_PLAYER
def display_positions(game_board):
"""
Display the current board.
"""
for row_idx in range(len(game_board)):
print(BOARD_LINER)
print(BOARD_SPACE)
print(BOARD_MOVES.format(
game_board[row_idx][0],
game_board[row_idx][1],
game_board[row_idx][2]
))
print(BOARD_SPACE)
print(BOARD_LINER)
return game_board
def get_available_positions(game_board):
"""
Get a list of the remaining available moves.
"""
positions = []
for row_idx in range(3):
for col_idx in range(3):
if game_board[row_idx][col_idx] not in GAME_PLAYERS:
positions.append((row_idx, col_idx))
return positions
def get_new_game_board():
"""
Prepare new game board.
"""
return [[3 * row_idx + col_idx + 1 for col_idx in range(3)]\
for row_idx in range(3)]
def game_is_over(game_board, player):
"""
If a victory is detected return True.
"""
diagonal_1 = True
diagonal_2 = True
for idx in range(3):
# Check each row for a win.
if game_board[idx][0] == player and\
game_board[idx][1] == player and\
game_board[idx][2] == player:
return True
# Check each column for a win.
if game_board[0][idx] == player and\
game_board[1][idx] == player and\
game_board[2][idx] == player:
return True
# Check each diagonal for a win.
if diagonal_1:
if game_board[idx][idx] != player:
diagonal_1 = False
if diagonal_2:
if game_board[2 - idx][2 - idx] != player:
diagonal_2 = False
return True if diagonal_1 or diagonal_1 else False
def request_next_move(game_board):
"""
Handle taking turns between each of the players.
"""
valid_move = False
while not valid_move:
player_move = input("Enter your move: ")
if not valid_players_move(player_move):
print("Bad move, try again")
continue
player_move = int(player_move) - 1
selected_row = player_move // 3
selected_col = player_move % 3
if game_board[selected_row][selected_col] in GAME_PLAYERS:
print("Already taken, try again")
continue
valid_move = True
game_board[selected_row][selected_col] = HUMAN_PLAYER
def valid_players_move(player_move):
"""
Validate that the player picked a move that is on the board.
"""
return True if player_move.isdigit() and\
1 <= int(player_move) <= 9 else False
# -----------------
# Game begins here.
# -----------------
# Set up the game board.
game_board = get_new_game_board()
# The computer gets the first move and always chooses the center.
game_board[1][1] = COMPUTER_PLAYER
available_positions = display_positions(game_board)
# Human and computer turns. Computer has taken the first move to
# select the middle of the board.
victor = None
human_turn = True
while available_positions:
display_positions(game_board)
# Get next move.
if human_turn:
player = HUMAN_PLAYER
request_next_move(game_board)
else:
player = COMPUTER_PLAYER
calculate_next_move(game_board)
# Assess next move.
if game_is_over(game_board, player):
# We found 3 in a row, game over,
victor = player
display_positions(game_board)
break
human_turn = not human_turn
available_positions = get_available_positions(game_board)
# End game.
if victor == HUMAN_PLAYER:
print("Game over, you won!")
elif victor == COMPUTER_PLAYER:
print("Game over, the compute won")
else:
print("Game over, tie!")