110
社区成员
发帖
与我相关
我的任务
分享20232301郑好 2023-2024-2 《Python程序设计》实验四报告
课程:《Python程序设计》
班级: 2323
姓名: 郑好
学号:20232301
实验教师:王志强
实验日期:2024年5月26日
必修/选修: 公选课
1.实验内容
Python综合应用:爬虫、数据处理、可视化、机器学习、神经网络、游戏、网络安全等
本次实验我使用python来编写扫雷游戏
import tkinter as tk
import random
import tkMessageBox
这段代码导入了必要的模块tkinter用于GUI界面的创建,tkMessageBox用于显示消息框,以及random用于生成随机数。
2.初始化
class Minesweeper:
def __init__(self, master, rows=10, cols=10, mines=10):
self.master = master
self.rows = rows
self.cols = cols
self.mines = mines
self.clicked = [[False for _ in range(cols)] for _ in range(rows)]
self.flags = [[False for _ in range(cols)] for _ in range(rows)]
self.board = [[0 for _ in range(cols)] for _ in range(rows)]
self.buttons = [[None for _ in range(cols)] for _ in range(rows)]
self.create_board()
self.place_mines()
self.calculate_numbers()
self.draw()
这段代码定义了一个Minesweeper类,__init__方法用于初始化游戏的参数,包括行数、列数和地雷数量,以及创建游戏界面,并初始化游戏板、点击记录、插旗记录等数据结构。
3.创建按钮
def create_board(self):
for i in range(self.rows):
for j in range(self.cols):
button = tk.Button(self.master, text=" ", width=2, height=1)
button.grid(row=i, column=j)
button.bind("<Button-1>", lambda event, row=i, col=j: self.left_click(event, row, col))
button.bind("<Button-3>", lambda event, row=i, col=j: self.toggle_flag(event, row, col))
self.buttons[i][j] = button
这段代码定义了create_board方法,用于在游戏界面上创建按钮,通过bind方法绑定左键点击和右键点击事件。
4.放置地雷
def place_mines(self):
mines = self.mines
while mines > 0:
row = random.randint(0, self.rows - 1)
col = random.randint(0, self.cols - 1)
if self.board[row][col] == 0:
self.board[row][col] = -1
mines -= 1
这段代码定义了place_mines方法,用于在游戏板上随机放置地雷。
5.计算地雷数
def calculate_numbers(self):
for i in range(self.rows):
for j in range(self.cols):
if self.board[i][j] == -1:
continue
count = 0
for ii in range(max(0, i-1), min(self.rows, i+2)):
for jj in range(max(0, j-1), min(self.cols, j+2)):
if self.board[ii][jj] == -1:
count += 1
self.board[i][j] = count
这段代码定义了calculate_numbers方法,用于计算每个格子周围的地雷数量,并更新游戏板。
6.展示状态
def draw(self):
for i in range(self.rows):
for j in range(self.cols):
if self.clicked[i][j]:
if self.board[i][j] == -1:
self.buttons[i][j]['text'] = '*'
elif self.board[i][j] == 0:
self.buttons[i][j]['text'] = ' '
else:
self.buttons[i][j]['text'] = str(self.board[i][j])
elif self.flags[i][j]:
self.buttons[i][j]['text'] = 'P'
else:
self.buttons[i][j]['text'] = ' '
这段代码定义了draw方法,根据游戏状态更新界面显示,展示点击过的格子的状态和数字,以及插旗状态。
7.处理左键点击事件
def left_click(self, event, row, col):
if self.clicked[row][col] or self.flags[row][col]:
return
if self.board[row][col] == -1:
tkMessageBox.showinfo("Game Over", "You clicked on a mine! Game Over.")
else:
self.clicked[row][col] = True
if self.board[row][col] == 0:
self.clear_empty_cells(row, col)
self.draw()
这段代码定义了left_click方法,处理左键点击事件。如果点击的是地雷,则游戏结束,显示游戏结束的消息;否则标记该格子为已点击,并清除周围的空格子。最后更新游戏界面。
8.标记功能
def toggle_flag(self, event, row, col):
if self.clicked[row][col]:
return
self.flags[row][col] = not self.flags[row][col]
self.draw()
这段代码定义了toggle_flag方法,处理右键点击事件。如果点击的是已经点击的格子,则不做任何操作。否则,在插旗状态和非插旗状态之间切换,并更新游戏界面。
9.清除空格
def clear_empty_cells(self, row, col):
for i in range(max(0, row-1), min(self.rows, row+2)):
for j in range(max(0, col-1), min(self.cols, col+2)):
if not self.clicked[i][j]:
self.clicked[i][j] = True
if self.board[i][j] == 0:
self.clear_empty_cells(i, j)
这段代码定义了clear_empty_cells方法,用于清除周围的空格子。在点击到一个空格子后,递归地清除其周围的其他空格子,直到所有与空格子相邻的空格子都被清除。
10.主函数
if __name__ == '__main__':
root = Tk()
root.title('Minesweeper')
rows, cols, mines = 10, 10, 10
game = Minesweeper(root, rows, cols, mines)
root.mainloop()
这段代码是主函数部分,用于创建游戏的窗口并运行游戏。首先创建了一个Tk实例作为游戏窗口,设置窗口标题为'Minesweeper'。然后初始化游戏的行数、列数和地雷数,创建Minesweeper类的实例并将游戏窗口和参数传入。最后通过调用root.mainloop()来启动游戏的主循环,使游戏界面显示出来并等待用户与游戏交互。
完整代码
import tkinter as tk
import tkinter.messagebox as tkMessageBox
import random
class Minesweeper:
def __init__(self, master, rows=10, cols=10, mines=10):
self.master = master
self.rows = rows
self.cols = cols
self.mines = mines
self.board = [[0 for _ in range(cols)] for _ in range(rows)]
self.clicked = [[False for _ in range(cols)] for _ in range(rows)]
self.flags = [[False for _ in range(cols)] for _ in range(rows)]
self.buttons = [[None for _ in range(cols)] for _ in range(rows)]
self.create_board()
self.place_mines()
self.calculate_numbers()
self.draw()
def create_board(self):
for i in range(self.rows):
for j in range(self.cols):
button = tk.Button(self.master, width=2, command=lambda i=i, j=j: self.left_click(i, j))
button.grid(row=i, column=j)
button.bind("<Button-3>", lambda event, i=i, j=j: self.toggle_flag(event, i, j))
self.buttons[i][j] = button
def place_mines(self):
mines_placed = 0
while mines_placed < self.mines:
row = random.randint(0, self.rows - 1)
col = random.randint(0, self.cols - 1)
if self.board[row][col] != -1:
self.board[row][col] = -1
mines_placed += 1
def calculate_numbers(self):
for i in range(self.rows):
for j in range(self.cols):
if self.board[i][j] == -1:
continue
count = 0
for r in range(i-1, i+2):
for c in range(j-1, j+2):
if 0 <= r < self.rows and 0 <= c < self.cols and self.board[r][c] == -1:
count += 1
self.board[i][j] = count
def draw(self):
for i in range(self.rows):
for j in range(self.cols):
if self.clicked[i][j]:
if self.board[i][j] == -1:
self.buttons[i][j].config(text="X", state=tk.DISABLED)
else:
self.buttons[i][j].config(text=str(self.board[i][j]), state=tk.DISABLED)
elif self.flags[i][j]:
self.buttons[i][j].config(text="F", state=tk.NORMAL, fg="red")
else:
self.buttons[i][j].config(text="", state=tk.NORMAL, fg="black")
def left_click(self, row, col):
if not self.clicked[row][col] and not self.flags[row][col]:
self.clicked[row][col] = True
if self.board[row][col] == -1:
tkMessageBox.showinfo("Game Over", "You clicked on a mine! Game over.")
self.reveal_all_mines()
elif self.board[row][col] == 0:
self.expand_empty(row, col)
self.draw()
if self.check_win():
tkMessageBox.showinfo("Congratulations", "You win!")
def toggle_flag(self, event, row, col):
if not self.clicked[row][col]:
self.flags[row][col] = not self.flags[row][col]
self.draw()
def expand_empty(self, row, col):
if self.board[row][col] == 0:
self.buttons[row][col].config(text="", state=tk.DISABLED)
for r in range(row - 1, row + 2):
for c in range(col - 1, col + 2):
if 0 <= r < self.rows and 0 <= c < self.cols:
self.left_click(r, c)
def reveal_all_mines(self):
for i in range(self.rows):
for j in range(self.cols):
if self.board[i][j] == -1:
self.buttons[i][j].config(text="X", state=tk.DISABLED)
def check_win(self):
for i in range(self.rows):
for j in range(self.cols):
if not self.clicked[i][j] and self.board[i][j] != -1:
return False
return True
def main():
root = tk.Tk()
root.title('Minesweeper')
game = Minesweeper(root)
root.mainloop()
if __name__ == "__main__":
main()
演示视频
屏幕录制 2024-05-28 221536.mp4
https://www.alipan.com/s/NFMoM6DuQGE
点击链接保存,或者复制本段内容,打开「阿里云盘」APP ,无需下载极速在线查看,视频原画倍速播放。
实验四感想体会
通过在实验四编写这段代码,我对Python的基本语法和数据结构有了更深入的了解。在编写扫雷游戏的过程中,我学到了很多关于Python编程和游戏开发的具体知识,:
我学习了如何使用Python的GUI库,如tkinter或pygame,设计游戏界面,包括绘制游戏界面、响应用户操作等。
首先,在编写扫雷游戏时,涉及到了一些算法设计,如雷区生成算法、周围雷数计算等,通过解决这些问题,提升了算法设计和优化能力。我还复习了如何使用Python的调试工具进行代码调试,定位和解决bug。了解了Minesweeper类游戏逻辑,同时,通过优化代码逻辑和算法,提高代码执行效率。这也是我第一次编写游戏,是一次全新的体验,不禁让我感叹很多看上去很简单的游戏,背后是一个程序员无尽的脱发和艰辛【哭】
这些具体知识和技能的学习,让我在Python编程和游戏开发方面有了更深入的了解和实践经验,为我的学习打下了坚实的基础。
课程总结
在过去的几个月里,我参与了Python程序设计这门课程的学习,可谓是受益匪浅。最初我选择这门课的原因在于,我们的大学生创业项目要求利用python进行相关研究,包括音频分析与图谱生成,恰好学校开设了这门课程,我便欣然选择了这门课程。由于有c语言学习的基础,在学习python时能够理解编程的基本思想,例如面向用户和面向对象的编程,这是我们的一大优势,但是在学习的过程中我也认识到他与c语言编程存在显著的区别,总体看上去,python的库相对较多,语法也相对更好理解,例如print的输出不强制要求规定格式,但是其格式相对严格,对于缩进有着很严格的要求,两者各有优势,同时,在后续的学习中,我学习了python中函数的定义、调用、参数传递、返回值等高级知识,提高了代码的可读性和可维护性,同时也使代码更为灵活,同时我还学习了之前所没有学过的web编程和爬虫技术,使我了解到python在功能上的多样性,其应用范围更广更宽,这也是为什么近年来python的使用率在逐年上升。总的来讲,python是一名使用且相对简明的语言,十分值得学习,通过这次的课程,我很自豪我获得了一项新的技能,拓宽了新的视野,了解了一门新的编程语言,去实现更多的功能,我们的项目也得以进行了有力推进,我十分感谢这门课程所带给我的丰富的知识!
以那句话结尾吧——“人生苦短,我用Python!”