110
社区成员




课程:《Python程序设计》
班级: 2222
姓名: 阎如玉
学号:20222201
实验教师:王志强
实验日期:2024年5月25日
必修/选修: 公选课
推箱子小游戏的实现。
Python环境:pycharm软件
python库:pygame,numpy等
定义游戏规则:玩家通过上下左右键控制角色移动,推动箱子到指定位置,完成所有箱子的放置即获胜。不能将箱子推到墙或另一个箱子无法到达的位置。
设计游戏元素:
地图:二维数组表示,0为空地,1为墙壁,2为目标点,3为箱子,4为带箱子的目标点。
玩家:可移动,能推动箱子。
箱子:可被玩家推动,遇墙停止。
确定游戏界面:考虑使用图形界面(如tkinter库)展示游戏状态。
Map类:负责地图的加载、显示和更新。
Player类:包含玩家位置、移动方法。
Box类:包含箱子位置、推动逻辑。
def createWidget(self): # 创建并配置游戏界面
if self.can: # 若画布存在,则先销毁旧画布
self.can.destroy()
self.can = tk.Canvas(self.master, bg='LightYellow', width=1000, height=600) # 新建画布
self.lbl = tk.Label(self.can, text=f'关卡:{self.gq} 返回上一步:b', bg='LightYellow', fg='red', font=('', 17))
self.lbl.place(x=5, y=5) # 显示当前关卡标签
map_shape = np.array(self.maps.maps_list[self.gq - 1]).shape # 获取地图尺寸
for r in range(map_shape[0]): # 遍历地图,绘制地图元素
for c in range(map_shape[1]):
cell_type = self.maps.maps_list[self.gq - 1][r][c]
if cell_type == 9: # 跳过特殊标记(假设9为不需要绘制的元素)
continue
elif cell_type == 34: # 玩家在终点
self.can.create_image((c + 1) * 50, (r + 1) * 50, anchor='nw', image=self.list2[5])
elif cell_type == 23: # 箱子在非终点
self.can.create_image((c + 1) * 50, (r + 1) * 50, anchor='nw', image=self.list2[2])
else:
img = self.list2[cell_type]
self.can.create_image((c + 1) * 50, (r + 1) * 50, anchor='nw', image=img)
self.can.focus_set() # 设置画布焦点,以便接收键盘事件
self.can.bind("<Key>", self.move) # 绑定键盘事件处理函数
self.can.pack() # 将画布添加至窗口
def get_person_position(self): # 获取玩家当前位置
for row_index, row in enumerate(self.maps.maps_list[self.gq - 1]):
for col_index, cell in enumerate(row):
if cell == 4: # 找到玩家位置
self.px, self.py = row_index, col_index
return
监听键盘事件,根据玩家输入改变角色位置。
我这里为了游戏的舒适体验,还设置了回退功能,可以退回到上一步。
def move(self, event):
keysym = event.keysym
print('你按了', keysym, '键')
y = copy.deepcopy(self.maps.maps_list[self.gq - 1])
self.old_list.append(y)
if keysym == 'Right' or keysym == 'Down' or keysym == 'd' or keysym == 's':
a_d = 1
else:
a_d = -1
if keysym == 'Right' or keysym == 'Left' or keysym == 'd' or keysym == 'a': #左右
uy = self.py
self.py += a_d
……
# 向上或向下
elif keysym == 'Down' or keysym == 'Up' or keysym == 'w' or keysym == 's':
ux = self.px
self.px += a_d
……
def roll_back(self): # 回退功能
if len(self.old_list) == 0:
return
self.maps.maps_list[self.gq - 1] = self.old_list.pop()
self.get_person_position()
self.createWidget()
检查玩家或箱子移动后是否碰到墙壁或其他障碍。以及对人物和箱子移动后位置的判断。
# 人物移动后的位置是否是箱子处在终点上,是的话尝试移动箱子
if self.maps.maps_list[self.gq - 1][self.px][self.py] == 23:
# 箱子移动后的位置是否是墙,是的话就撤销
if self.maps.maps_list[self.gq - 1][self.px][self.py + a_d] == 1:
self.py = uy
self.old_list.pop()
# 箱子移动后的位置是否有箱子处在终点上,是的话撤销
elif self.maps.maps_list[self.gq - 1][self.px][self.py + a_d] == 23:
self.py = uy
self.old_list.pop()
# 箱子移动后的位置是否是终点,是的话移动
elif self.maps.maps_list[self.gq - 1][self.px][self.py + a_d] == 3:
self.maps.maps_list[self.gq - 1][self.px][self.py + a_d] = 23
self.maps.maps_list[self.gq - 1][self.px][self.py] = 34
if self.maps.maps_list[self.gq - 1][self.px][uy] == 34:
self.maps.maps_list[self.gq - 1][self.px][uy] = 3
else:
self.maps.maps_list[self.gq - 1][self.px][uy] = 0
# 箱子移动后的位置为空
else:
self.maps.maps_list[self.gq - 1][self.px][self.py + a_d] = 2
self.maps.maps_list[self.gq - 1][self.px][self.py] = 34
if self.maps.maps_list[self.gq - 1][self.px][uy] == 34:
self.maps.maps_list[self.gq - 1][self.px][uy] = 3
else:
self.maps.maps_list[self.gq - 1][self.px][uy] = 0
# 人物移动后的位置是否为空,是的话移动
elif self.maps.maps_list[self.gq - 1][self.px][self.py] == 0:
self.maps.maps_list[self.gq - 1][self.px][self.py] = 4
if self.maps.maps_list[self.gq - 1][self.px][uy] == 34:
self.maps.maps_list[self.gq - 1][self.px][uy] = 3
else:
self.maps.maps_list[self.gq - 1][self.px][uy] = 0
# 人物移动后的位置是否有箱子,有的话尝试移动箱子
elif self.maps.maps_list[self.gq - 1][self.px][self.py] == 2:
# 箱子移动后位置是否是墙,是的话撤销
if self.maps.maps_list[self.gq - 1][self.px][self.py + a_d] == 1:
self.py = uy
self.old_list.pop()
# 箱子移动后位置是否是终点,是的话移动
elif self.maps.maps_list[self.gq - 1][self.px][self.py + a_d] == 3:
self.maps.maps_list[self.gq - 1][self.px][self.py + a_d] = 23
self.maps.maps_list[self.gq - 1][self.px][self.py] = 4
self.maps.maps_list[self.gq - 1][self.px][uy] = 0
elif self.maps.maps_list[self.gq - 1][self.px][self.py + a_d] == 0:
self.maps.maps_list[self.gq - 1][self.px][self.py + a_d] = 2
self.maps.maps_list[self.gq - 1][self.px][self.py] = 4
if self.maps.maps_list[self.gq - 1][self.px][uy] == 34:
self.maps.maps_list[self.gq - 1][self.px][uy] = 3
else:
self.maps.maps_list[self.gq - 1][self.px][uy] = 0
else:
self.py = uy
self.old_list.pop()
elif self.maps.maps_list[self.gq - 1][self.px][self.py] == 1:
self.py = uy
self.old_list.pop()
else:
self.maps.maps_list[self.gq - 1][self.px][self.py] = 34
if self.maps.maps_list[self.gq - 1][self.px][uy] == 34:
self.maps.maps_list[self.gq - 1][self.px][uy] = 3
else:
self.maps.maps_list[self.gq - 1][self.px][uy] = 0
每一张地图都有设置目标点,判断所有箱子是否都位于目标点上,来判断是否过关。
def is_win(self): # 判断是否获胜
for row in self.maps.maps_list[self.gq - 1]: # 检查每行
if 34 in row or 3 in row: # 存在箱子未推到终点或玩家未站在终点
return False
return True
实现游戏的主循环,包括画面刷新、用户输入处理、游戏状态更新。
if __name__ == '__main__':
root = tk.Tk()
root.title('推箱子')
# 初始化
py.mixer.init()
# 文件加载
py.mixer.music.load(r'.\music\1.mp3')
# 播放 第一个是播放值 -1 代表循环播放, 第二个参数代表开始播放的时间
py.mixer.music.play(-1)
wall = tk.PhotoImage(file='image/墙.png')
person = tk.PhotoImage(file='image/人物.png')
box = tk.PhotoImage(file='image/箱子.png')
flag = tk.PhotoImage(file='image/可放位置.png')
blank = tk.PhotoImage(file='image/空.png')
person_flag = tk.PhotoImage(file='image/人物与旗帜.png')
Window(root)
root.mainloop()
我用的是txt文档为关卡地图文件,用maps函数用来控制关卡地图的读取和建设。
class Maps(object):
def __init__(self):
with open('maps.txt', 'r', encoding='utf-8') as f:
datas = f.readlines()
self.maps_list = []
for i in datas:
i = json.loads(i)
self.maps_list.append(i)
完成Python学习之旅后,我亲自动手开发了一款经典的推箱子小游戏,这一实践不仅让我深刻体会到了编程的乐趣与挑战,更赋予了我巨大的成就感。通过这个过程,我将所学知识转化为实际作品,亲眼见证了理论到实践的跨越,这种从无到有的创造过程异常宝贵。这次经历不仅是对自我能力的一次验证,也是对Python语言强大灵活性和易用性的再次肯定,它进一步激发了我对编程的热爱与探索欲。由此,我深切感受到,掌握Python这样强大的工具,能够让我们在实现创意与解决问题的道路上行得更远,成就感满满的同时,也更加坚定了我在编程领域持续探索和成长的决心。
在这段宝贵的Python学习旅程中,我有幸遇到了一位极其出色的教师,他不仅拥有深厚的专业知识,更难能可贵的是,他对待学生亲切友善,营造了一个积极向上、鼓励探索的学习氛围。老师的教学方法独到而高效,他擅长将复杂的编程概念拆解成易于理解的小块,通过生动的实例、有趣的互动和适时的引导,让我们能够逐步消化吸收,将抽象的理论知识转化为实际操作技能。
课程设计巧妙,从Python的基础语法入门,到函数、模块的使用,再到面向对象编程等高级主题,每一步都循序渐进,既注重基础知识的巩固,又鼓励我们探索实践,解决实际问题。课堂上,老师经常采用项目驱动的方式,比如指导我们动手开发小程序,比如那个令人难忘的猜数字游戏,这些实践不仅加深了我们对知识的理解,更激发了学习的热情,让我们在实践中收获满满,成就感倍增。
此外,老师还非常注重培养我们的自学能力和批判性思维,鼓励我们在遇到难题时先独立思考,再小组讨论,最后才是求助于他,这样的教学策略极大地提升了我们的解决问题能力。在他的引领下,我不仅掌握了Python这门强大语言的精髓,更学会了如何高效学习,如何在编程的世界里持续探索和创新。
总之,这门Python课程不仅是一次知识的积累,更是一次思维的飞跃,老师的优秀与课程的精心设计使我受益匪浅,这段学习经历无疑为我的编程生涯奠定了坚实的基础,让我对未来充满了信心和期待。