当前位置:首页>python>用 Python 实现一个可视化的推箱子游戏

用 Python 实现一个可视化的推箱子游戏

  • 2026-10-11 17:43:41
用 Python 实现一个可视化的推箱子游戏

用 Python 实现一个可视化的推箱子游戏,这是一个很经典的编程练习,既能锻炼逻辑思维,也能学习图形界面编程。

使用 Python 内置的 tkinter 库来实现这个游戏,它不需要额外安装,简单易用,非常适合新手入门图形界面开发。

实现思路

  1. 使用 tkinter 创建游戏窗口和画布
  2. 定义游戏元素(墙、空地、箱子、目标点、玩家)的表示和绘制方式
  3. 设计游戏地图数据结构,用二维列表表示
  4. 实现键盘控制玩家移动的逻辑,包括推箱子的碰撞检测
  5. 添加游戏胜利判断和提示

完整代码实现

import tkinter as tk
from tkinter import messagebox

classSokobanGame:
def__init__(self, root):
# 游戏基本设置
        self.root = root
        self.root.title("推箱子游戏")

# 每个格子的大小(像素)
        self.cell_size = 60

# 定义游戏元素的颜色
        self.colors = {
'wall': '
#8B4513',      # 墙 - 棕色
'floor': '#F5DEB3',     # 空地 - 小麦色
'box': '#FFD700',       # 箱子 - 金色
'target': '#FF6347',    # 目标点 - 番茄红
'player': '#4169E1'# 玩家 - 皇家蓝
        }

# 定义游戏地图 (0=空地, 1=墙, 2=箱子, 3=目标点, 4=玩家)
        self.map = [
            [1, 1, 1, 1, 1, 1, 1],
            [1, 0, 0, 0, 0, 0, 1],
            [1, 0, 2, 0, 2, 0, 1],
            [1, 0, 0, 2, 0, 0, 1],
            [1, 0, 3, 0, 3, 0, 1],
            [1, 0, 3, 0, 0, 4, 1],
            [1, 1, 1, 1, 1, 1, 1]
        ]

# 找到玩家初始位置
        self.player_x, self.player_y = self.find_player()

# 创建画布
        self.canvas = tk.Canvas(
            root, 
            width=len(self.map[0])*self.cell_size, 
            height=len(self.map)*self.cell_size
        )
        self.canvas.pack()

# 绑定键盘事件
        self.root.bind('<KeyPress>', self.on_key_press)

# 绘制初始游戏界面
        self.draw_game()

deffind_player(self):
"""找到玩家在地图中的初始位置"""
for y, row in enumerate(self.map):
for x, cell in enumerate(row):
if cell == 4:
return x, y
return0, 0

defdraw_cell(self, x, y, color):
"""绘制单个格子"""
        x1 = x * self.cell_size
        y1 = y * self.cell_size
        x2 = x1 + self.cell_size
        y2 = y1 + self.cell_size
        self.canvas.create_rectangle(x1, y1, x2, y2, fill=color, outline='black', width=2)

defdraw_game(self):
"""绘制整个游戏界面"""
        self.canvas.delete('all')  # 清空画布

# 绘制地图
for y, row in enumerate(self.map):
for x, cell in enumerate(row):
# 先绘制基础格子(墙或空地)
if cell == 1:
                    self.draw_cell(x, y, self.colors['wall'])
else:
                    self.draw_cell(x, y, self.colors['floor'])

# 绘制覆盖在上面的元素
if cell == 2:  # 箱子
                    self.draw_cell(x, y, self.colors['box'])
elif cell == 3:  # 目标点
# 目标点用圆形表示
                    center_x = x * self.cell_size + self.cell_size // 2
                    center_y = y * self.cell_size + self.cell_size // 2
                    radius = self.cell_size // 3
                    self.canvas.create_oval(
                        center_x - radius, center_y - radius,
                        center_x + radius, center_y + radius,
                        fill=self.colors['target']
                    )
elif cell == 4:  # 玩家
# 玩家用正方形表示
                    center_x = x * self.cell_size + self.cell_size // 2
                    center_y = y * self.cell_size + self.cell_size // 2
                    half_size = self.cell_size // 4
                    self.canvas.create_rectangle(
                        center_x - half_size, center_y - half_size,
                        center_x + half_size, center_y + half_size,
                        fill=self.colors['player']
                    )

defmove_player(self, dx, dy):
"""处理玩家移动逻辑"""
# 计算新位置
        new_x = self.player_x + dx
        new_y = self.player_y + dy

# 检查新位置是否是墙
if self.map[new_y][new_x] == 1:
returnFalse

# 检查新位置是否是箱子
if self.map[new_y][new_x] == 2:
# 计算箱子要移动到的位置
            box_new_x = new_x + dx
            box_new_y = new_y + dy

# 检查箱子的新位置是否合法(不是墙也不是箱子)
if self.map[box_new_y][box_new_x] in (0, 3):
# 移动箱子
                self.map[box_new_y][box_new_x] = 2
                self.map[new_y][new_x] = 0# 清空原来箱子的位置
else:
returnFalse

# 移动玩家
        self.map[self.player_y][self.player_x] = 0# 清空原来玩家的位置
        self.map[new_y][new_x] = 4# 设置新位置为玩家
        self.player_x, self.player_y = new_x, new_y

returnTrue

defcheck_win(self):
"""检查是否获胜(所有目标点都有箱子)"""
for y, row in enumerate(self.map):
for x, cell in enumerate(row):
# 如果还有空的目标点,说明还没赢
if cell == 3:
returnFalse
returnTrue

defon_key_press(self, event):
"""处理键盘按键事件"""
        moved = False

# 根据按键方向移动
if event.keysym == 'Up':
            moved = self.move_player(0, -1)
elif event.keysym == 'Down':
            moved = self.move_player(0, 1)
elif event.keysym == 'Left':
            moved = self.move_player(-1, 0)
elif event.keysym == 'Right':
            moved = self.move_player(1, 0)

# 如果移动成功,重新绘制游戏界面
if moved:
            self.draw_game()

# 检查是否获胜
if self.check_win():
                messagebox.showinfo("恭喜", "你成功通关了!")
                self.root.quit()

# 运行游戏
if __name__ == "__main__":
    root = tk.Tk()
    game = SokobanGame(root)
    root.mainloop()

代码解释

  1. 游戏初始化 (__init__):

    • 设置游戏窗口、格子大小、颜色等基本参数
    • 定义游戏地图(二维列表),其中数字代表不同元素
    • 创建画布并绑定键盘事件
    • 绘制初始游戏界面
  2. 核心方法:

    • find_player(): 查找玩家初始位置
    • draw_cell() 和 draw_game(): 负责绘制游戏界面
    • move_player(): 处理玩家移动逻辑,包括推箱子的碰撞检测
    • check_win(): 判断是否所有箱子都推到目标点
    • on_key_press(): 响应键盘按键,控制玩家上下左右移动
  3. 游戏操作:

    • 运行代码后,会弹出游戏窗口
    • 使用方向键(上、下、左、右)控制玩家移动
    • 将所有箱子推到红色目标点上即可获胜

运行条件

  • 无需安装额外库,Python 3.x 环境自带 tkinter
  • 直接复制代码到 .py 文件中运行即可

总结

  1. 这个推箱子游戏使用 tkinter 实现可视化,核心是通过二维列表表示地图,监听键盘事件实现玩家移动。
  2. 游戏的关键逻辑是碰撞检测:玩家移动时要判断目标位置是墙、箱子还是空地,推箱子时还要检查箱子的下一个位置是否合法。
  3. 胜利条件是所有目标点都被箱子覆盖,检测到胜利后会弹出提示框并结束游戏。

你可以根据自己的喜好修改地图布局(修改 self.map 二维列表)、调整颜色(修改 self.colors 字典)或格子大小(修改 self.cell_size)来定制游戏。

最新文章

随机文章