20242112 2024-2025-2《Python公选课》实验四报告
课程:《Python程序设计》
班级: 2421
姓名: 张童哲
学号:20242112
实验教师:王志强
实验日期:2025年5月14日
必修/选修: 公选课
(一)实验内容
编写一个生成迷宫,有四个难度,简单中等困难和自定义,玩家可以控制小人通过这个迷宫。但是这样一个小游戏还是太简单了,于是我增添了一个迷雾模式,只能看清小人周围5X5的范围,然后凭借自己的记忆力来通关迷宫。
(二)实验过程及结果
1.导入库
导入random,tkinter,messagebox,random用来生成随机迷宫,tkinter用来生成游戏的用户界面,messagebox用来显示游戏的胜利结算和错误提示。
2.游戏设计思路
迷宫选择最普通的方形迷宫,这样方便绘制,先将迷宫全部设定为墙,然后从中间开始挖掘,选用递归回溯算法来保证迷宫路径的唯一性。
def generate_maze(width, height):
maze = [["#" for _ in range(width)] for _ in range(height)]
def carve_path(x, y):
directions = [(0, 1), (1, 0), (0, -1), (-1, 0)]
random.shuffle(directions)
for dx, dy in directions:
nx, ny = x + dx * 2, y + dy * 2
if 0 <= nx < width and 0 <= ny < height and maze[ny][nx] == "#":
maze[ny][nx] = " "
maze[y + dy][x + dx] = " "
carve_path(nx, ny)
start_x = width // 2
start_y = height // 2
maze[start_y][start_x] = " "
carve_path(start_x, start_y)
maze[1][0] = " "
maze[height - 2][width - 1] = " "
maze[0][0] = "S"
maze[height - 1][width - 1] = "E"
if maze[1][0] == "#":
maze[1][0] = " "
if maze[height - 2][width - 1] == "#":
maze[height - 2][width - 1] = " "
return maze
然后是绘制迷宫,由于是方形迷宫,绘制比较简单,只要给像素块填充颜色就行。墙为绿色,路径和起点为白色,终点为红色,玩家是一个蓝色的小点。然后迷雾模式看不见的地方用黑色填充。
def draw_maze(maze, canvas, fog_mode, player_x, player_y):
global cell_size
canvas_width = canvas.winfo_width()
canvas_height = canvas.winfo_height()
cell_size = min(canvas_width / len(maze[0]), canvas_height / len(maze))
canvas.delete("all")
for y, row in enumerate(maze):
for x, cell in enumerate(row):
if fog_mode:
min_x = max(0, player_x - 2)
max_x = min(len(maze[0]), player_x + 3)
min_y = max(0, player_y - 2)
max_y = min(len(maze), player_y + 3)
if min_x <= x < max_x and min_y <= y < max_y:
color = "green" if cell == "#" else "white" if cell in (" ", "S") else "red"
else:
color = "black"
else:
color = "green" if cell == "#" else "white" if cell in (" ", "S") else "red"
canvas.create_rectangle(x * cell_size, y * cell_size,
(x + 1) * cell_size, (y + 1) * cell_size,
fill=color, outline="")
canvas.create_oval(player_x * cell_size + 5, player_y * cell_size + 5,
(player_x + 1) * cell_size - 5, (player_y + 1) * cell_size - 5,
fill="blue", tags="player")
然后再绑定方向键,游戏基本的框架就完成了,难度设定:简单为21X21,中等为31X31,困难为41X41,自定义最高为99,然后输入的一定要是奇数。
3.实验结果
【python结课成果视频展示】 https://www.bilibili.com/video/BV1aT7czEEkt/?share_source=copy_web&vd_source=a5121d1118b478c4607c2e6bcf17eb91
4.源代码
import random
import tkinter as tk
from tkinter import messagebox
fog_mode = False
player_x, player_y = 0, 0
cell_size = 0
def generate_maze(width, height):
maze = [["#" for _ in range(width)] for _ in range(height)]
def carve_path(x, y):
directions = [(0, 1), (1, 0), (0, -1), (-1, 0)]
random.shuffle(directions)
for dx, dy in directions:
nx, ny = x + dx * 2, y + dy * 2
if 0 <= nx < width and 0 <= ny < height and maze[ny][nx] == "#":
maze[ny][nx] = " "
maze[y + dy][x + dx] = " "
carve_path(nx, ny)
start_x = width // 2
start_y = height // 2
maze[start_y][start_x] = " "
carve_path(start_x, start_y)
maze[1][0] = " "
maze[height - 2][width - 1] = " "
maze[0][0] = "S"
maze[height - 1][width - 1] = "E"
if maze[1][0] == "#":
maze[1][0] = " "
if maze[height - 2][width - 1] == "#":
maze[height - 2][width - 1] = " "
return maze
def draw_maze(maze, canvas, fog_mode, player_x, player_y):
global cell_size
canvas_width = canvas.winfo_width()
canvas_height = canvas.winfo_height()
cell_size = min(canvas_width / len(maze[0]), canvas_height / len(maze))
canvas.delete("all")
for y, row in enumerate(maze):
for x, cell in enumerate(row):
if fog_mode:
min_x = max(0, player_x - 2)
max_x = min(len(maze[0]), player_x + 3)
min_y = max(0, player_y - 2)
max_y = min(len(maze), player_y + 3)
if min_x <= x < max_x and min_y <= y < max_y:
color = "green" if cell == "#" else "white" if cell in (" ", "S") else "red"
else:
color = "black"
else:
color = "green" if cell == "#" else "white" if cell in (" ", "S") else "red"
canvas.create_rectangle(x * cell_size, y * cell_size,
(x + 1) * cell_size, (y + 1) * cell_size,
fill=color, outline="")
canvas.create_oval(player_x * cell_size + 5, player_y * cell_size + 5,
(player_x + 1) * cell_size - 5, (player_y + 1) * cell_size - 5,
fill="blue", tags="player")
def move_player(event, maze, canvas, fog_mode):
global player_x, player_y
directions = {'Up': (0, -1), 'Down': (0, 1), 'Left': (-1, 0), 'Right': (1, 0)}
direction = directions.get(event.keysym)
if direction:
dx, dy = direction
new_x, new_y = player_x + dx, player_y + dy
if 0 <= new_x < len(maze[0]) and 0 <= new_y < len(maze) and maze[new_y][new_x] != "#":
canvas.move("player", dx * cell_size, dy * cell_size)
player_x, player_y = new_x, new_y
draw_maze(maze, canvas, fog_mode, player_x, player_y)
if maze[new_y][new_x] == "E":
messagebox.showinfo("胜利", "恭喜你,成功到达出口!")
def on_resize(event, maze, canvas, fog_mode):
draw_maze(maze, canvas, fog_mode, player_x, player_y)
def start_game(width, height, fog_mode):
if width % 2 == 0 or height % 2 == 0:
messagebox.showerror("错误", "宽度和高度必须是奇数!")
return
root.withdraw()
maze = generate_maze(width, height)
game_root = tk.Tk()
game_root.title("迷宫游戏")
canvas = tk.Canvas(game_root)
canvas.pack(fill=tk.BOTH, expand=True)
global player_x, player_y
player_x, player_y = 0, 0
draw_maze(maze, canvas, fog_mode, player_x, player_y)
def back_to_start():
game_root.destroy()
root.deiconify()
back_button = tk.Button(game_root, text="返回开始界面", command=back_to_start)
back_button.pack()
for direction in ["Up", "Down", "Left", "Right"]:
game_root.bind(f"<{direction}>", lambda event, d=direction: move_player(event, maze, canvas, fog_mode))
game_root.bind("<Configure>", lambda event: on_resize(event, maze, canvas, fog_mode))
game_root.mainloop()
def open_custom_dialog():
dialog = tk.Toplevel(root)
dialog.title("自定义难度")
tk.Label(dialog, text="宽度(奇数,小于等于99):").grid(row=0, column=0)
width_entry = tk.Entry(dialog)
width_entry.grid(row=0, column=1)
tk.Label(dialog, text="高度(奇数,小于等于99):").grid(row=1, column=0)
height_entry = tk.Entry(dialog)
height_entry.grid(row=1, column=1)
def start_custom_game():
try:
width = int(width_entry.get())
height = int(height_entry.get())
start_game(width, height, fog_mode)
except ValueError:
messagebox.showerror("错误", "请输入有效的整数!")
tk.Button(dialog, text="开始游戏", command=start_custom_game).grid(row=2, column=0, columnspan=2)
root = tk.Tk()
root.title("迷宫游戏 - 难度选择")
tk.Label(root, text="选择游戏难度:").pack(pady=10)
easy_button = tk.Button(root, text="简单", command=lambda: start_game(21, 21, fog_mode))
easy_button.pack(pady=5)
medium_button = tk.Button(root, text="中等", command=lambda: start_game(31, 31, fog_mode))
medium_button.pack(pady=5)
hard_button = tk.Button(root, text="困难", command=lambda: start_game(41, 41, fog_mode))
hard_button.pack(pady=5)
custom_button = tk.Button(root, text="自定义", command=open_custom_dialog)
custom_button.pack(pady=5)
fog_var = tk.IntVar()
fog_checkbox = tk.Checkbutton(root, text="开启迷雾模式", variable=fog_var,
command=lambda: set_fog_mode(fog_var.get()))
fog_checkbox.pack(pady=5)
def set_fog_mode(value):
global fog_mode
fog_mode = bool(value)
root.mainloop()
(三)课程总结和建议
非常好的python课,使我的大脑旋转!这学期我最愿意上的就是pyhon课。python是我接触到的第一门语言,但当时就学了一点点皮毛,第一门系统学习的语言还是来到大学后学的C语言,但我对python一直包有极大的兴趣,因为简单,好用,所以这学期我毫不犹豫的报了python课。上课后我也是十分喜欢python课的课堂氛围,轻松愉快,老师也相当幽默。python课上也是学到了许多知识。感觉上python课就是在学中玩,在玩中学。
人生苦短,我选python。
建议:建议多留点作业方便巩固所学的知识,python课最大的缺点就是没有缺点。
浙公网安备 33010602011771号