Создание игры 2048 на Python с использованием Tkinter

PythonPythonBeginner
Практиковаться сейчас

💡 Этот учебник переведен с английского с помощью ИИ. Чтобы просмотреть оригинал, вы можете перейти на английский оригинал

Введение

В этом проекте вы узнаете, как создать простую игру 2048 на Python с использованием библиотеки Tkinter для графического пользовательского интерфейса. 2048 - это популярная игра-головоломка с перемещаемыми плитками, в которой вы объединяете плитки, чтобы получить плитку со значением 2048. Хотя в этом проекте не будет создан самый современный и красивый пользовательский интерфейс, он предоставит прочный фундамент, на основе которого вы сможете улучшить внешний вид.

👀 Предпросмотр

2048 game

🎯 Задачи

В этом проекте вы научитесь:

  • Импортировать необходимые библиотеки для игры
  • Создавать класс Game2048 для обработки логики игры и пользовательского интерфейса
  • Рисовать игровую сетку с использованием Tkinter
  • Создавать начальные плитки на сетке
  • Обновлять пользовательский интерфейс в соответствии с текущим состоянием игровой сетки
  • Определять цвета плиток в зависимости от их значений
  • Обрабатывать нажатия клавиш для перемещения плиток
  • Определять методы для перемещения плиток в разных направлениях
  • Проверять, закончилась ли игра

🏆 Достижения

После завершения этого проекта вы сможете:

  • Использовать библиотеку Tkinter для создания графического пользовательского интерфейса
  • Обрабатывать нажатия клавиш и запускать соответствующие действия
  • Обновлять пользовательский интерфейс в зависимости от состояния игры
  • Реализовывать логику игры для перемещения и объединения плиток
  • Проверять, закончилась ли игра

Создание файлов проекта

Сначала создайте новый файл с именем 2048_game.py и откройте его в вашем любимом текстовом редакторе кода.

cd ~/project
touch 2048_game.py
✨ Проверить решение и практиковаться

Импорт необходимых библиотек

Для работы вашей игры вам нужно импортировать основные библиотеки. В файле 2048_game.py включите библиотеку random Python и Tkinter для создания графического пользовательского интерфейса.

import random
import tkinter as tk

Эти библиотеки будут использоваться для создания функциональности игры и пользовательского интерфейса.

✨ Проверить решение и практиковаться

Создание класса Game2048

Определите класс Game2048 в файле 2048_game.py. Этот класс будет обрабатывать логику игры и пользовательский интерфейс.

class Game2048:
    def __init__(self, root):
        self.root = root
        self.root.title("2048 Game")
        self.root.geometry("400x400")

        ## Initialize the game grid and score
        self.grid = [[0 for _ in range(4)] for _ in range(4)]
        self.score = 0

        ## Create an empty list to store tile labels
        self.tiles = []

Здесь вы создаете конструктор класса, который инициализирует главное окно игры, задает его заголовок и размер, инициализирует игровую сетку и создает список для хранения игровых плиток.

✨ Проверить решение и практиковаться

Отрисовка игровой сетки

В классе Game2048 добавьте метод для отрисовки игровой сетки с использованием Tkinter. Этот метод создает начальную сетку пользовательского интерфейса.

    def draw_grid(self):
        for i in range(4):
            row = []
            for j in range(4):
                cell = tk.Label(self.root, text="", font=("Helvetica", 24), width=5, height=2, borderwidth=4, relief="ridge")
                cell.grid(row=i, column=j, padx=5, pady=5)
                row.append(cell)
            self.tiles.append(row)

Этот метод создает 4x4 сетку меток (labels), которые будут отображать игровые плитки.

✨ Проверить решение и практиковаться

Создание начальных плиток

Теперь вам нужно реализовать метод, который создает начальные плитки при запуске игры. Этот метод поместит одну или две плитки со значением 2 или 4 на игровую сетку.

    def spawn_tile(self):
        empty_cells = [(i, j) for i in range(4) for j in range(4) if self.grid[i][j] == 0]
        if empty_cells:
            i, j = random.choice(empty_cells)
            self.grid[i][j] = 2 if random.random() < 0.9 else 4
            self.update_tiles()

Этот метод находит пустые ячейки на сетке и случайным образом помещает новую плитку в одну из них.

✨ Проверить решение и практиковаться

Обновление пользовательского интерфейса

Создайте метод для обновления пользовательского интерфейса, чтобы отразить текущее состояние игровой сетки.

    def update_tiles(self):
        for i in range(4):
            for j in range(4):
                tile_value = self.grid[i][j]
                self.tiles[i][j]["text"] = str(tile_value) if tile_value > 0 else ""
                self.tiles[i][j]["background"] = self.get_tile_color(tile_value)

Этот метод проходит по всей сетке, обновляя метки (labels) в графическом пользовательском интерфейсе так, чтобы они соответствовали состоянию сетки.

✨ Проверить решение и практиковаться

Определение цветов плиток

Создайте метод для присвоения фоновых цветов плиткам в зависимости от их значений.

    def get_tile_color(self, value):
        colors = {
            0: "#CDC1B4",
            2: "#EEE4DA",
            4: "#EDE0C8",
            8: "#F2B179",
            16: "#F59563",
            32: "#F67C5F",
            64: "#F65E3B",
            128: "#EDCF72",
            256: "#EDCC61",
            512: "#EDC850",
            1024: "#EDC53F",
            2048: "#EDC22E"
        }
        return colors.get(value, "#FF0000")

Этот метод возвращает код цвета на основе значения плитки.

✨ Проверить решение и практиковаться

Обработка нажатий клавиш

Реализуйте метод для обработки нажатий клавиш. На этом этапе вы будете отслеживать нажатия стрелочных клавиш и реагировать соответствующим образом.

    def key_pressed(self, event):
        if self.is_game_over():
            return

        if event.keysym == "Up":
            self.move("up")
        elif event.keysym == "Down":
            self.move("down")
        elif event.keysym == "Left":
            self.move("left")
        elif event.keysym == "Right":
            self.move("right")

        self.spawn_tile()
        self.update_tiles()

Этот метод отслеживает нажатия стрелочных клавиш и запускает соответствующую функцию перемещения.

✨ Проверить решение и практиковаться

Перемещение плиток

Реализуйте методы для перемещения плиток в нужном направлении: вверх, вниз, влево или вправо.

    def move(self, direction):
        if direction == "up":
            self.grid = list(map(list, zip(*self.grid)))
            self.move_left()
            self.grid = list(map(list, zip(*self.grid)))
        elif direction == "down":
            self.grid = list(map(list, zip(*self.grid)))
            self.move_right()
            self.grid = list(map(list, zip(*self.grid)))
        elif direction == "left":
            self.move_left()
        elif direction == "right":
            self.move_right()

Этот метод подготавливает сетку для перемещения, вызывает соответствующую функцию перемещения, а затем восстанавливает исходное состояние сетки.

✨ Проверить решение и практиковаться

Перемещение плиток влево

Определите метод для перемещения плиток влево в рамках строки.

    def move_left(self):
        for i in range(4):
            row = self.grid[i]
            row = [value for value in row if value!= 0]
            while len(row) < 4:
                row.append(0)

            for j in range(3):
                if row[j] == row[j + 1] and row[j]!= 0:
                    row[j] *= 2
                    row[j + 1] = 0
                    self.score += row[j]

            row = [value for value in row if value!= 0]
            while len(row) < 4:
                row.append(0)
            self.grid[i] = row

Этот метод обрабатывает перемещение плиток влево, объединяет соседние плитки, если это возможно, и заполняет пустые ячейки.

✨ Проверить решение и практиковаться

Перемещение плиток вправо

Определите метод для перемещения плиток вправо в рамках строки.

    def move_right(self):
        for i in range(4):
            row = self.grid[i]
            row = [value for value in row if value!= 0]
            while len(row) < 4:
                row.insert(0, 0)

            for j in range(3, 0, -1):
                if row[j] == row[j - 1] and row[j]!= 0:
                    row[j] *= 2
                    row[j - 1] = 0
                    self.score += row[j]

            row = [value for value in row if value!= 0]
            while len(row) < 4:
                row.insert(0, 0)
            self.grid[i] = row

Этот метод отвечает за перемещение плиток вправо, их объединение при необходимости и заполнение пустых мест.

✨ Проверить решение и практиковаться

Проверка окончания игры

Создайте метод для проверки, закончилась ли игра. Игра заканчивается, когда больше нет возможных ходов.

    def is_game_over(self):
        for i in range(4):
            for j in range(4):
                if self.grid[i][j] == 0:
                    return False

        for i in range(4):
            for j in range(3):
                if self.grid[i][j] == self.grid[i][j + 1]:
                    return False

        for j in range(4):
            for i in range(3):
                if self.grid[i][j] == self.grid[i + 1][j]:
                    return False

        return True

Этот метод проверяет, есть ли еще возможные ходы, анализируя, содержит ли сетка пустые ячейки или соседние ячейки с одинаковым значением. Если больше нет возможных ходов, игра заканчивается.

✨ Проверить решение и практиковаться

Запуск проекта

Наконец, перейдите на рабочий стол и запустите проект с помощью следующей команды:

python 2048_game.py
2048 game
✨ Проверить решение и практиковаться

Резюме

В этом проекте вы научились создавать простую игру 2048 на Python с использованием библиотеки Tkinter. Вы начали с настройки проекта, создания основного Python-файла и определения класса Game2048. Затем вы реализовали обработку нажатий клавиш, перемещение плиток и проверку условий окончания игры. Интерфейс игры может не быть самым современным и красивым, но у вас теперь есть фундамент, который вы можете улучшить и настроить для создания более совершенной игры 2048. Чтобы запустить проект, вы можете следовать шагам ниже.