Як створити гру в хрестики-нулики на Python?

Створення простої гри “Хрестики-нулики” на Python

Розглянемо, як можна розробити просту гру “Хрестики-нулики” за допомогою Python. Це чудова вправа для розуміння логіки гри та структури коду.

Ігри – це популярний спосіб розваги. Існує безліч ігор в інтернеті, на мобільних пристроях та комп’ютерах. Але сьогодні ми не створюватимемо складну гру. Наша мета – розробити просту консольну гру “Хрестики-нулики” за допомогою Python.

Якщо ви не знайомі з правилами “Хрестиків-нуликів”, можете ознайомитись з ними тут. Якщо ж ви вже знаєте правила, то можемо переходити далі.

Структура статті

Ця стаття складається з трьох основних розділів. У першому розділі ми розглянемо правила гри “Хрестики-нулики”. Потім ми розберемо алгоритм, який допоможе нам розробити логіку гри. І, нарешті, ми розглянемо структуру коду та його пояснення.

Якщо ви вже знаєте правила гри, можете пропустити перший розділ.

Отже, почнемо з першого розділу.

Правила гри “Хрестики-нулики”

У грі беруть участь двоє гравців. Кожен гравець має свій символ. Зазвичай використовуються символи “X” та “O”. Гра відбувається на дошці, яка складається з 9 клітинок.

Ось приклад дошки для гри:

Геймплей наступний:

  • Перший гравець ставить свій символ у будь-яку вільну клітинку.
  • Другий гравець робить те саме.
  • Мета гри – розмістити три своїх символи в ряд, стовпець або по діагоналі.
  • Гра триває до тих пір, поки один із гравців не виграє або дошка не буде заповнена і гра закінчиться внічию.

Давайте поглянемо на приклад перемоги:

Є 8 можливих комбінацій для перемоги. Якщо ж дошка заповнена, а жоден гравець не виграв, то гра закінчується внічию. Сподіваємось, ви тепер розумієте правила.

Якщо ви хочете пограти, можете спробувати тут. А ми переходимо до наступного розділу.

Алгоритм

Розглянемо алгоритм, який допоможе нам написати код. Цей алгоритм можна використовувати для написання коду будь-якою мовою програмування. Ось як це працює:

  • Створіть дошку, використовуючи двовимірний масив, і ініціалізуйте кожну клітинку як порожню.
    • Можна використовувати будь-який символ для представлення порожньої клітинки. Ми використаємо дефіс “-“.
  • Напишіть функцію, яка перевіряє, чи заповнена дошка.
    • Перевірте кожну клітинку дошки. Якщо хоча б одна клітинка порожня, поверніть false, інакше true.
  • Напишіть функцію, яка перевіряє, чи виграв гравець.
    • Перевірте всі можливі комбінації для перемоги: рядки, стовпці та діагоналі.
  • Створіть функцію для виведення дошки, оскільки нам потрібно буде показувати її гравцям під час гри.
  • Напишіть функцію для запуску гри.
    • Виберіть гравця, який ходить першим, випадковим чином.
    • Запустіть нескінченний цикл, який завершиться, коли гра закінчиться (виграш або нічия).
      • Покажіть дошку гравцеві.
      • Попросіть гравця ввести номер рядка та стовпця.
      • Оновіть дошку, поставивши символ гравця у вибрану клітинку.
      • Перевірте, чи виграв гравець. Якщо так, виведіть повідомлення про перемогу та завершіть цикл.
      • Перевірте, чи заповнена дошка. Якщо так, виведіть повідомлення про нічию та завершіть цикл.
    • Покажіть фінальну дошку.

Сподіваємось, ви розумієте, як працює алгоритм. Якщо ні, не хвилюйтеся, код допоможе вам все зрозуміти.

Код

Ось код на Python, який реалізує описаний вище алгоритм:

import random

class TicTacToe:

    def __init__(self):
        self.board = []

    def create_board(self):
        for i in range(3):
            row = []
            for j in range(3):
                row.append('-')
            self.board.append(row)

    def get_random_first_player(self):
        return random.randint(0, 1)

    def fix_spot(self, row, col, player):
        self.board[row][col] = player

    def is_player_win(self, player):
        win = None
        n = len(self.board)

        # Перевірка рядків
        for i in range(n):
            win = True
            for j in range(n):
                if self.board[i][j] != player:
                    win = False
                    break
            if win:
                return win

        # Перевірка стовпців
        for i in range(n):
            win = True
            for j in range(n):
                if self.board[j][i] != player:
                    win = False
                    break
            if win:
                return win

        # Перевірка діагоналей
        win = True
        for i in range(n):
            if self.board[i][i] != player:
                win = False
                break
        if win:
            return win

        win = True
        for i in range(n):
            if self.board[i][n - 1 - i] != player:
                win = False
                break
        if win:
            return win
        return False
    
    def is_board_filled(self):
        for row in self.board:
            for item in row:
                if item == '-':
                   return False
        return True


    def swap_player_turn(self, player):
        return 'X' if player == 'O' else 'O'

    def show_board(self):
        for row in self.board:
            for item in row:
                print(item, end=" ")
            print()

    def start(self):
        self.create_board()

        player="X" if self.get_random_first_player() == 1 else 'O'
        while True:
            print(f"Хід гравця {player}")
            self.show_board()

            # Отримання вводу від користувача
            row, col = list(
                map(int, input("Введіть номер рядка та стовпця для встановлення знаку: ").split()))
            print()

            # Встановлення знаку
            self.fix_spot(row - 1, col - 1, player)

            # Перевірка, чи виграв поточний гравець
            if self.is_player_win(player):
                print(f"Гравець {player} виграв!")
                break

             # Перевірка, чи є нічия
            if self.is_board_filled():
               print("Нічия!")
               break

            # Зміна гравця
            player = self.swap_player_turn(player)

        # Відображення кінцевої дошки
        print()
        self.show_board()


# Запуск гри
tic_tac_toe = TicTacToe()
tic_tac_toe.start()
  

Ось приклад виводу коду:

$ python tic_tac_toe.py 
Хід гравця X
- - -
- - -
- - -
Введіть номер рядка та стовпця для встановлення знаку: 1 1

Хід гравця O
X - -
- - -
- - -
Введіть номер рядка та стовпця для встановлення знаку: 2 1

Хід гравця X
X - -
O - -
- - -
Введіть номер рядка та стовпця для встановлення знаку: 1 2

Хід гравця O
X X -
O - -
- - -
Введіть номер рядка та стовпця для встановлення знаку: 1 3

Хід гравця X
X X O
O - -
- - -
Введіть номер рядка та стовпця для встановлення знаку: 2 2

Хід гравця O
X X O
O X -
- - -
Введіть номер рядка та стовпця для встановлення знаку: 3 3

Хід гравця X
X X O        
O X -        
- - O
Введіть номер рядка та стовпця для встановлення знаку: 3 2

Гравець X виграв!

X X O
O X -
- X O

Основні моменти, які допоможуть вам зрозуміти структуру коду:

  • Ми використовуємо клас для того, щоб зберігати всі методи в одному місці. Це робить код більш організованим і дозволяє легко його використовувати повторно.
  • Ми розділили код на функції, кожна з яких виконує окреме завдання. Це полегшує розуміння та підтримку коду.
  • Такий підхід допомагає нам легко оновлювати програму.

Не соромтеся змінювати структуру коду та вдосконалювати його.

Висновок

Вітаємо! Ви створили гру “Хрестики-нулики” з нуля. Можливо, це не найскладніша гра, але вона допомагає нам зрозуміти, як працює логіка гри і як структурувати код. Дотримуйтесь цих порад, щоб створювати інші цікаві ігри.

Бажаємо успіхів у програмуванні! 👩‍💻

Далі ви можете ознайомитись зі статтею про створення гри “Вгадай число” та модульне тестування за допомогою модуля Python unittest.

Сподобалась стаття? Поділіться нею зі своїми друзями!