Создаём игру «Крестики-нолики» на Python: пошаговый урок с кодом
«Крестики-нолики» — классический проект для начинающих. Он закрепляет основы: циклы, условия, списки, функции, ввод/вывод. Ниже — полный код с комментариями и разбором.
Правила игры
- Поле N×N (обычно 3×3).
- Два игрока по очереди ставят X и O.
- Победа: заполнена целая строка, столбец или диагональ одним символом.
- Ничья: все клетки заполнены, победителя нет.
Требования
- Python 3.x
- Любой редактор (VS Code, PyCharm, IDLE) или терминал.
- Базовые знания: циклы
for/while,if/else, списки, функции.
Алгоритм
- Создать доску (список списков).
- Запросить размер N (≥3).
- Случайно выбрать первого игрока.
- Цикл игры: показать доску → спросить ход → проверить занятость → поставить знак → проверить победу/ничью → сменить игрока.
- После окончания — предложить реванш.
Полный код (N-мерное поле)
def get_input(prompt, cast=None, condition=None, error_msg=None):
"""Универсальный ввод с валидацией."""
while True:
try:
val = cast(input(prompt)) if cast else input(prompt)
if condition is None or condition(val):
return val
except Exception:
pass
print(error_msg or "Некорректный ввод.")
def print_board(board):
print()
for row in board:
print(" ".join(row))
print()
def check_win(board):
n = len(board)
# Строки
for r in range(n):
if all(board[r][c] == board[r][0] != "_" for c in range(n)):
return True
# Столбцы
for c in range(n):
if all(board[r][c] == board[0][c] != "_" for r in range(n)):
return True
# Главная диагональ
if all(board[i][i] == board[0][0] != "_" for i in range(n)):
return True
# Побочная диагональ
if all(board[i][n-1-i] == board[0][n-1] != "_" for i in range(n)):
return True
return False
def play():
print("------------\nN-ДИМЕНСИОННЫЕ КРЕСТИКИ-НОЛИКИ\n------------")
N = get_input("Размер поля (N ≥ 3): ", cast=int, condition=lambda x: x >= 3,
error_msg="Введите целое число ≥ 3.")
board = [["_"] * N for _ in range(N)]
used = 0
turn = 0 # 0 -> X, 1 -> O
while True:
print_board(board)
prompt = f"Игрок {turn+1} ({"X" if turn==0 else "O"}) — введите строку и столбец (0-{N-1}) через пробел: "
pick = get_input(prompt,
cast=lambda s: tuple(map(int, s.split())),
condition=lambda p: 0 <= p[0] < N and 0 <= p[1] < N and board[p[0]][p[1]] == "_",
error_msg=f"Неверные координаты или клетка занята. Введите два числа 0-{N-1}.")
r, c = pick
board[r][c] = "X" if turn == 0 else "O"
used += 1
if check_win(board):
print_board(board)
print(f"Игрок {turn+1} победил!")
break
elif used == N * N:
print_board(board)
print("Ничья!")
break
turn = 1 - turn
again = get_input("Сыграть ещё раз? (y/n): ", cast=str.lower,
condition=lambda a: a in ("y", "n"),
error_msg="Введите y или n.")
if again == "y":
play()
else:
print("Игра окончена. Спасибо за игру!")
if __name__ == "__main__":
play()
Разбор ключевых частей
1. Функция get_input — безопасный ввод
Принимает промпт, функцию приведения типа (cast), условие проверки (condition) и текст ошибки. В цикле while True просит ввод, пока не станет валидным. Это избавляет от дублирования try/except.
2. Отрисовка доски print_board
Проходит по строкам и печатает символы через пробел. print(" ".join(row)) делает вывод аккуратным.
3. Проверка победы check_win
Проверяет 4 направления: строки, столбцы, две диагонали. Использует all() для краткости: все элементы равны первому и не пусты (!= "_").
4. Главный цикл play()
- Инициализация: доска, счётчик ходов, чья очередь.
- Цикл
while Trueдо победы или ничьи. - После хода: проверка победы → ничьи → смена игрока (
turn = 1 - turn). - Рекурсивный вызов
play()для реванша (можно заменить на внешний цикл).
Пример запуска (3×3)
------------ N-ДИМЕНСИОННЫЕ КРЕСТИКИ-НОЛИКИ ------------ Размер поля (N ≥ 3): 3 _ _ _ _ _ _ _ _ _ Игрок 1 (X) — введите строку и столбец (0-2) через пробел: 1 1 _ _ _ _ X _ _ _ _ Игрок 2 (O) — введите строку и столбец (0-2) через пробел: 0 1 _ O _ _ X _ _ _ _ ... (далее до победы или ничьей)
Идеи для улучшения
- Добавить ИИ (Minimax) для игры против компьютера.
- Графический интерфейс на
tkinterилиpygame. - Сохранение истории партий в файл.
- Цветной вывод в терминале (
colorama).
Заключение
Этот проект отлично тренирует алгоритмическое мышление. Начните с понимания каждого блока, затем экспериментируйте: меняйте размер поля, добавляйте правила, подключайте бота. Удачи!
Python
- Python: получение текущего времени и работы с часовыми поясами
- Python и MySQL: практическое руководство по подключению к БД, созданию и CRUD операциям
- Функции в Python: Создание переиспользуемых модулей кода
- Многопоточное программирование в Python: эффективные техники параллелизма
- Принятие решений в Python: Условная логика и операторы if
- Получение текущей даты и времени в Python: практическое руководство
- Операции с матрицами в Python с NumPy: транспонирование, сложение, умножение и срезы — практическое руководство
- Python vs PHP: ключевые отличия, сильные стороны и выбор правильного языка
- Мастерство преобразования типов в Python: Полное руководство
- Мастерство многопоточности в Python: GIL объяснён с практическими примерами