当前位置:首页>python>少儿编程教案:Python推箱子,4步讲透核心逻辑

少儿编程教案:Python推箱子,4步讲透核心逻辑

  • 2026-10-11 07:53:26
少儿编程教案:Python推箱子,4步讲透核心逻辑

温馨提示

本教程源码素材已更新至公众号菜单栏【源码素材】

如果文章对您有一点点帮助,点、点,万分感谢

推箱子程序能跑起来,靠的不是什么高深的技术,就是把几个基本模块拼在一起:窗口怎么开、图片怎么加载、角色类怎么写、关卡怎么加载、移动怎么判断、键盘怎么绑定。听着多,代码其实不长,今天一段段讲清楚。

【第一关效果】
【所需素材】

窗口设置

开头这段是固定套路,做 turtle 项目基本都要写:

ms = turtle.Screen()ms.setup(650, 650, 200, 0)ms.title('推箱子小游戏')ms.bgcolor("yellow")

Screen() 创建窗口,setup(宽, 高, x, y) 设置窗口大小和打开位置,这里是 650×650 像素。bgcolor("yellow") 把背景设成黄色。

接下来注册四张图片,turtle 只认 gif 格式:

ms.register_shape('wall.gif')   # 墙ms.register_shape('o.gif')      # 目标点ms.register_shape('p.gif')      # 小人ms.register_shape('boxc.gif')    # 箱子(推到目标点后显示的那张)

最后一行 ms.tracer(0) 关掉 turtle 的自动刷新,改成手动控制,画完再一次性显示出来。这个技巧在 turtle 动画里很常见,不开的话画面会一格一格跳。


Pen 类:角色的模板

class Pen(turtle.Turtle):    def __init__(self, pic):        super().__init__()        self.shape(pic)        self.penup()

所有角色(墙、目标点、小人、箱子)都用同一个类来创建。继承 turtle.Turtle 是为了直接拿画笔的功能,绑定图片用 shape(),然后 penup() 抬笔——抬笔之后 goto() 移动才不会画线。


move():移动判断的核心

这是整个程序最核心的部分,也是最难理解的。小人按方向键移动,到底能不能走,要分三种情况判断:

def move(self, x, gx, y, gy):    gox = x + gx    goy = y + gy    has_box = False    if (gox, goy) in list_space:        for i in list_box:            if i.pos() == (gox, goy):                has_box = True                gox2 = x + gx * 2                goy2 = y + gy * 2                if (gox2, goy2) in list_space:                    self.goto(gox, goy)                    i.goto(gox2, goy2)        if has_box == False:            self.goto(gox, goy)

第一步:算目标格子坐标。当前位置 (x, y) 加上方向增量 (gx, gy),得到 (gox, goy)。

第二步:目标格子在不在可通行列表里。不在的话就是撞墙,谁都不动。

第三步:目标格子上有没有箱子。遍历 list_box 里所有箱子,如果某个箱子的坐标等于目标格子,说明前面有箱子。

第四步:箱子前面还有没有空位。算箱子要去的格子 (gox2, goy2),就是当前位置再加一格。如果这个格子也在可通行列表里,就小人往前走一格、箱子被推到前面一格。

第五步:目标格子上没有箱子,直接走过去。

四个方向方法的区别只在于增量参数不同:

def go_up(self):    self.move(self.xcor(), +0, self.ycor(), +50)def go_down(self):    self.move(self.xcor(), +0, self.ycor(), -50)def go_left(self):    self.move(self.xcor(), -50, self.ycor(), +0)def go_right(self):    self.move(self.xcor(), +50, self.ycor(), +0)

往哪个方向走,就在对应的坐标上加或减 50(每个格子的像素宽度)。


Game 类:关卡加载

class Game():    def show(self):        for i in range(8):            for j in range(8):                x = -175 + j * 50                y =  175 - i * 50                if level_1[i][j] == " ":                    list_space.append((x, y))                elif level_1[i][j] == 'X':                    wall.goto(x, y)                    wall.stamp()                elif level_1[i][j] == 'O':                    list_space.append((x, y))                    box.goto(x, y)                    box.stamp()                elif level_1[i][j] == 'P':                    player.goto(x, y)                    list_space.append((x, y))                elif level_1[i][j] == 'B':                    box1 = Pen('boxc.gif')                    box1.goto(x, y)                    list_space.append((x, y))                    list_box.append(box1)

遍历 8×8 的地图字符串列表,根据每个字符决定画什么。其中两件事是同步做的:

一是盖印章,wall.stamp() 和 box.stamp() 画墙和目标点。它们只画不动,用 stamp 省事。

二是记录可通行坐标,所有空地、目标点、小人位置、箱子初始位置都加进 list_space。这样后面小人走动时就能查这个列表判断能不能走。

遇到箱子字符 B 时,除了画箱子,还要把箱子对象本身加进 list_box,因为推箱子时要遍历这个列表找到箱子再让它移动。


关卡地图

level_1 = [    'CCXXXCCC',    'CCXOXCCC',    'CCX XXXX',    'XXXB BOX',    'XO BPXXX',    'XXXXBXCC',    'CCCXOXCC',    'CCCXXXCC']

字符含义:

  • X 墙

  • O 目标点(箱子要去的地方)

  • B 箱子

  • P 小人

  • 空格 游戏里的空地,可以走过去

  • C 边角背景色,不算空地

用字符来表示地图是个很实用的技巧,不需要写一堆坐标数据,直接看字符串就能想象出地图长什么样。


对象创建和主循环

list_box  = []list_space = []wall   = Pen('wall.gif')box    = Pen('o.gif')player = Pen('p.gif')game = Game()game.show()ms.listen()ms.onkey(player.go_up,    "Up")ms.onkey(player.go_left,  "Left")ms.onkey(player.go_down,  "Down")ms.onkey(player.go_right, "Right")while True:    ms.update()ms.mainloop()

list_box 和 list_space 在创建角色之前要先定义成空列表,因为 Game.show() 里会往这两个列表里添加内容。

ms.listen() 让窗口开始监听键盘输入,onkey() 把四个方向函数绑定到方向键上。

最后 while 循环不断调用 update(),保证画面持续刷新、键盘响应一直在线。程序会一直运行,直到关闭窗口。


常见问题

运行后图片找不到

图片文件要和 Python 文件放在同一个文件夹里,从那个文件夹里双击运行,不要在其他目录调用。

方向键按了没反应

先在窗口里点一下鼠标,让窗口获得焦点,再按方向键。

推过去的箱子还能穿过去

list_space 加载时只记了一次,箱子推走后没有实时更新列表。完整版需要在每次推箱子成功后,把旧坐标从列表移除、把新坐标对应的逻辑改掉。先跑通,再优化。


推箱子这个程序,把基本模块拼在一起就能跑。把代码自己敲一遍,改一改关卡地图,再试着自己加个步数统计或者过关提示,就算真正掌握了。

【参考讲义】

最新文章

随机文章