-
Notifications
You must be signed in to change notification settings - Fork 4
/
tic_tac_toe.py
222 lines (176 loc) · 9 KB
/
tic_tac_toe.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
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
# Функция для удобного вывода содержимого
import os
import sys
class TicTacToe:
"""
Игра в крестики нолики.
Класс реализует игру в крестики нолики для 2 игроков,
каждый из игроков имеет возможность выбирать себе имя и фигуру.
"""
# Стандартные символы для заполнения ячеек
CROSS = 'x'
CIRCLE = 'o'
# Стандартный символ для заполнения пустотных ячеек
EMPTY = " "
def __init__(self):
# Словарь с тремя списками, это матрица для заполнения крест/нолик
self.all_list = {
"A": [TicTacToe.EMPTY]*3,
"B": [TicTacToe.EMPTY]*3,
"C": [TicTacToe.EMPTY]*3
}
# Данные об игроках, выбранная фигура и значение для заполнения списков
self.gamer_one = { "figure":TicTacToe.CROSS, "name":"First"}
self.gamer_two = { "figure":TicTacToe.CIRCLE,"name":"Second"}
# Текущий игрок
self.current_player = self.gamer_one
# Количество сделанных шагов игроками
self.counter_move = 0
# Победитель
self.winner = None
# Первоначальная анкетат для игроков, вы бор фигуры и имен для игроков
self.question_choose()
def question_choose(self):
"""
Выбор имен для игроков. ли игрок выбрали имя то его больше об этом
не спрашивать. Первый игрок выбирает фигуру которую будет играть.
"""
choose_name = False
while True:
try:
if not choose_name:
self.gamer_one['name'] = input("Name for first player ? ")
self.gamer_two['name'] = input("Name for second player ? ")
choose_name = True
answer = input("Choose figure for gamer '{name}' ('x' or 'o') ? :"
.format(name=self.gamer_one['name']))
if answer == TicTacToe.CROSS:
self.gamer_one['figure'] = TicTacToe.CROSS
self.gamer_two['figure'] = TicTacToe.CIRCLE
break
elif answer == TicTacToe.CIRCLE:
self.gamer_one['figure'] = TicTacToe.CIRCLE
self.gamer_two['figure'] = TicTacToe.CROSS
break
else:
print("Please, choose 'x' or 'o' for first gamer.")
except EOFError:
print("\nExit from game with (Ctrl + D)")
sys.exit()
except KeyboardInterrupt:
print("\nExit from game with (Ctrl + C)")
sys.exit()
print("'{name}' gamer pick a '{figure}'".format(
name=self.gamer_one['name'], figure=self.gamer_one['figure']))
print("'{name}' gamer pick a '{figure}'".format(
name=self.gamer_two['name'], figure=self.gamer_two['figure']))
def start(self):
"""
Цикл заполнения ячеек таблицы до победы одного из игроков.
Запуск цикла, показать таблицу пользователю, сдлеать проверку на победителя
если победителя пока что нету, то дать пользователю заполнить ячейку,
повторять процесс до тех пор пока не будет найден победитель.
Проверка на победителя производится только после 5 шагов, только тогда
кто то может победить.
"""
print("*** Start game. ***")
while True:
self.show_table_char()
if self.counter_move >= 5:
if self.check_finish():
self.show_winner()
break
self.choose_move()
self.change_player()
print("*** End game. ***")
def show_winner(self):
"""Выводим победителя, если он есть и ничью если его нету."""
if self.winner is None:
print("Победителя нету, ничья.")
else:
print("Победитель игрок по имени '{winner}' ".format(winner=self.current_player['name']))
print("Игра закончена на {num} ходу".format(num=self.counter_move))
def check_finish(self):
"""
Проверяем заполнена ли выйгрышная комбинация.
Есть 8 победных комбинаций, все их можно разделить на 3 категории:
горизонтальные, вертикальные, диагональные.
"""
if self.check_horizontal_list() or self.check_vertical_list() \
or self.check_diagonal_list() or self.check_diagonal_revers_list():
self.change_player()
self.winner = self.current_player
return True
elif self.counter_move == 9:
self.winner = None
return True
return False
def check_diagonal_revers_list(self):
"""Проверка по обратной диагонали"""
if self.all_list["A"][2] == self.all_list["B"][1] == self.all_list["C"][0] != TicTacToe.EMPTY:
return True
return False
def check_diagonal_list(self):
"""Проверка по диагонали"""
if self.all_list["A"][0] == self.all_list["B"][1] == self.all_list["C"][2] != TicTacToe.EMPTY:
return True
return False
def check_vertical_list(self):
"""Проверка по вертикали"""
for i in range(0, 3):
if self.all_list["A"][i] == self.all_list["B"][i] == self.all_list["C"][i] != TicTacToe.EMPTY:
return True
return False
def check_horizontal_list(self):
"""Проверка на горизонтальные"""
for elem in self.all_list.values():
if elem[0] == elem[1] == elem[2] != TicTacToe.EMPTY:
return True
return False
def choose_move(self):
"""
Выбор ячеек игроками.
Принимаем введеннйю ячейку, если введено верно то заполняем нужный
элемент списка, меняем текущего игрока и даем ему заполнить свою ячейку.
"""
while True:
try:
choose = input("Player '{name}' choose ?".format(name=self.current_player["name"]))
if (len(choose) == 2) and (choose[0] in self.all_list.keys()) \
and ((int(choose[1])-1) in range(0,3)):
if self.all_list[choose[0]][int(choose[1]) - 1] == TicTacToe.EMPTY:
if self.current_player['figure'] == TicTacToe.CROSS:
self.all_list[choose[0]][int(choose[1]) - 1] = TicTacToe.CROSS
elif self.current_player['figure'] == TicTacToe.CIRCLE:
self.all_list[choose[0]][int(choose[1]) - 1] = TicTacToe.CIRCLE
self.counter_move += 1
break
else:
print("Ячейка {choose} уже заполнена, выберите другую.".format(choose=choose))
else:
print("Введите позицию в виде буква и число, к примеру так: B2 или A1 ")
except EOFError:
print("\nExit from game with (Ctrl + D)")
sys.exit()
except KeyboardInterrupt:
print("\nExit from game with (Ctrl + C)")
sys.exit()
def change_player(self):
"""Переключение текущего игрока"""
if self.current_player == self.gamer_one:
self.current_player = self.gamer_two
else:
self.current_player = self.gamer_one
def show_table_char(self):
"""
Красивый вывод состояния таблицы крестики нолики.
Вариант со строками.
"""
print(" 1 2 3 ")
print("A ", " | ".join(self.all_list["A"]))
print("B ", " | ".join(self.all_list["B"]))
print("C ", " | ".join(self.all_list["C"]))
# Запуск игры
if __name__ == '__main__':
game = TicTacToe()
game.start()