110
社区成员




20232226赵锦 2023-2024-2 《Python程序设计》实验四报告
课程:《Python程序设计》
班级: 2322班
姓名: 赵锦
学号: 20232226
实验教师:王志强
实验日期:2024年5月15日
必修/选修: 公选课
Python综合应用:爬虫、数据处理、可视化、机器学习、神经网络、游戏、网络安全等。
例如:编写从社交网络爬取数据,实现可视化舆情监控或者情感分析。
例如:利用公开数据集,开展图像分类、恶意软件检测等
例如:利用Python库,基于OCR技术实现自动化提取图片中数据,并填入excel中。
例如:爬取天气数据,实现自动化微信提醒
例如:利用爬虫,实现自动化下载网站视频、文件等。
例如:编写小游戏:坦克大战、贪吃蛇、扫雷等等
注:在Windows/Linux系统上使用VIM、PDB、IDLE、Pycharm等工具编程实现。
1.利用Python库,基于OCR技术实现自动化提取图片中数据,并填入excel中。
2.编写俄罗斯方块小游戏。
3.编写贪吃蛇游戏。
在日常生活和学习中常常会碰到想借用图片上的数据,却懒得写的情况,恰巧看到老师实验内容中有该项目,因此想尝试一下,既巩固了知识,又方便了自己。
● PIL库安装,因版本更新问题,安装失败,后安装了pillow-PIL
● 起初在pycharm库中安装,后利用命令行进行了安装。
● 安装成功后,进行了pytesseract库的安装,安装完成后,遇到‘tesseract is not installed or it’s not in your path’问题,后借助博客,下载了tesseract.exe,在安装完成后,打开pytesseract源码查找 tesseract_cmd = ‘tesseract’,并进行了路径的修改。
● 安装完成后,仍然显示路径出错,后借助AI进行修改,仍然出错,尝试失败,后又进行了两个小游戏的编写。
在小时候无智能手机的情况下,只有小灵通上的俄罗斯方块此类游戏,而在学习python和听完王志强老师的讲课后,内心有了一个尝试——自己写自己曾经玩的最多的游戏,这个过程中,既有利于加深我对python知识的理解,同时提高了编程能力。
● 在学期初始,自己刷博客时看到许多python小游戏,当即便进行了收藏,后来在课程期间,一直根据博客上的代码,进行理解并默写乃至自己编写。
● 函数分析:
● fangk 类:
__init__(self, huabu, col, row):初始化函数,用于创建方块对象。huabu 是画布对象,col 和 row 分别代表方块所在列和行。
setvisible(self, statu):设置方块的可见性。当 statu 大于 0 时,创建方块并展示在画布上;当 statu 等于 0 时,删除方块;否则返回 -1。
set_color(self, color):设置方块的颜色。
● elsfk 类:
__init__(self):初始化函数,用于创建不同形状的方块。
创建了一个窗口self.win,并设置了标题为"俄罗斯方块",尺寸为450x610,并且不允许用户改变窗口大小。
创建了一个Canvas组件self.huabu用于绘制游戏界面。
创建了几个Button组件self.pauseBut、self.startBut、self.restartBut和self.quitBut分别用于暂停、开始、重新开始和退出游戏。
创建了两个Label组件self.lab_score和self.lab_grade用于显示分数和等级。
创建了一个Checkbutton组件self.check_box1用于设置难度。
● 设置菜单:
创建了一个Menu对象self.menu,并添加了游戏、退出和设置三个子菜单。
在游戏子菜单中添加了开始和重新开始两个命令。
在设置子菜单中添加了颜色和难度两个命令。
● 绑定事件:
使用bind_all方法将按键事件与相应的函数进行绑定,例如按下a、d、j、s键对应调用move_left、move_right、rotate、quick_drop等函数。
● 创建方块对象:
通过嵌套列表推导式创建了一个二维数组self.fangkuai_map,并初始化了其中的元素为fangk类的实例,用于表示游戏中的方块。
● 运行游戏:
调用self.win.mainloop()启动了窗口的主循环,使得窗口能够响应用户操作并进行游戏逻辑的处理。
● nandu(self):
这个函数用于控制游戏难度的变化,当积累的行数超过10时,会重置nandu_line,并更新base_map和color_map。最后调用combind()和draw_map()来重新绘制游戏地图。
● set_color(self):
这个函数用于设置是否启用多色彩模式,通过改变muti_color的值来实现。
● pause(self):
这个函数用于暂停游戏,调用messagebox.showinfo()显示一个提示框表明游戏暂停中。
● restart(self):
这个函数用于重新开始游戏,首先弹出确认框询问用户是否确定重新开始,然后清空画布上的所有元素,重新初始化游戏并开始游戏。
● cal_score(self, row):
这个函数用于计算得分和等级,根据消除的行数更新得分和等级,并根据难度状态更新nandu_line。
● initgame(self):
这个函数用于初始化游戏参数,包括初始化地图、分数、速度、级别等各种变量。
● quitgame(self):
这个函数用于退出游戏,弹出确认框询问用户是否确定退出,如果确定则关闭游戏窗口。
● startgame(self):
这个函数用于开始游戏,首先禁用难度选择按钮和开始按钮,然后进入游戏循环,不断调用drop()函数进行方块下落,同时更新游戏窗口。
● flash(self, del_rows):
这个函数用于在消除行的时候进行动画效果,通过改变方块的可见性来实现闪烁效果,使得消除行的操作更加直观。
● next_fk(self):
这个函数用于生成并展示下一个方块,首先将当前的颜色和方块类型更新为下一个方块的颜色和类型,然后随机生成下一个方块的颜色和类型。接着清空右侧画布上的所有元素,并根据下一个方块的类型和颜色在右侧画布上绘制下一个方块的预览。最后更新当前方块的类型、位置等信息,调用combind()和draw_map()来更新游戏地图。
● rotate(self, event):
这个函数用于旋转当前方块,根据当前方块的类型进行相应的旋转操作,如果旋转后的位置不合法,则撤销旋转操作。最后调用combind()和draw_map()来更新游戏地图。
● combind(self):
这个函数用于将当前方块的位置和颜色信息合并到游戏地图中,更新地图上的方块和颜色信息。
● test_map(self):
这个函数用于检测当前方块的位置是否合法,即是否与地图上已有的方块重叠。
● draw_map(self):
这个函数用于根据游戏地图的变化更新画布上的方块显示,通过比较当前地图和上一帧的地图状态,更新需要更新的方块的颜色和可见性,实现画布的刷新。
● quick_drop(self, event):
这个函数用于快速下落方块,如果当前没有锁定操作(即可以操作),则调用drop()函数进行下落。
● drop(self):
这个函数用于处理方块的下落逻辑,首先将当前方块的y坐标增加1,然后检查是否超出游戏区域或与已有方块重叠。如果是,则撤销下落操作,并执行消行等操作;否则将当前方块合并到游戏地图中,并生成新的方块。
● delete_row(self):
这个函数用于检查并消除完整的行,如果有完整的行则进行消除,并更新得分等信息。
● move_left(self, event):
这个函数用于处理方块向左移动的逻辑,如果当前没有锁定操作,则将当前方块的x坐标减1,并检查是否与已有方块重叠,如果不重叠则进行移动。
● move_right(self, event):
这个函数用于处理方块向右移动的逻辑,与move_left类似,只是将当前方块的x坐标增加1。
● down_straight(self, event):
这个函数用于快速直降方块,当当前没有锁定操作且方块还能够下落时,持续调用drop()函数,直到方块无法下落为止。
###(3).实验结果
对于本人来讲,第一次编写如此大的程序,非常具有挑战性,虽然借助了博客,但还是非常之困难,不过在这个过程中,收获了很多,对于代码有了更深的理解,增强了编程的整体意识。
该游戏是在课程开始时,老师上课讲到python的强大与广泛时开始有所思考,而实验内容中有这一项,因此在报告中也体现了出来。(借助CSDN博客代码)
● 基础设置:
定义了游戏窗口的高度、宽度和小方块的大小,并设置了游戏区域的坐标范围。
● 食物的初步设置:
定义了不同食物分值和对应的颜色,用于生成不同分值的食物。
● 整体颜色设置:
定义了游戏中使用的颜色。
● 文本输出格式设置:
提供了一个函数Print_Txt用于在游戏窗口中输出文本。
● 初始化蛇:
提供了一个函数init_snake用于初始化蛇的位置。
● 食物设置:
提供了一个函数Creat_Food用于生成食物的位置,并避免食物出现在蛇身上的情况。
pygame.init():初始化pygame库。
pygame.display.set_mode((Screen_Width,Screen_Height)):设置游戏窗口大小。
pygame.display.set_caption('贪吃蛇'):设置游戏窗口标题。
● 字体设置:
font1和font2用于设置得分和游戏结束字体的样式。
● 变量设置:
b用于防止特定情况下的游戏结束。
snake初始化贪吃蛇的位置。
food初始化食物的位置。
pos定义贪吃蛇的初始移动方向。
game_over标志游戏是否结束。
game_start标志游戏是否开始。
score记录游戏得分。
speed记录贪吃蛇移动的速度。
last_move_time记录上一次移动的时间。
pause标志游戏是否暂停。
● 主循环:
主循环不断监听事件,如退出事件、键盘按下事件等。
当按下回车键时,如果游戏结束,重置游戏参数并开始新游戏。
当按下空格键时,切换游戏暂停状态。
当按下方向键时,改变贪吃蛇的移动方向,同时防止特定情况下的游戏结束。
● 填充背景色:使用screen.fill(Back_Ground)来填充背景色。
● 画网格线:通过循环绘制横线和竖线,生成游戏区域的网格线。
● 贪吃蛇的爬行过程:
根据时间控制贪吃蛇的移动速度。
判断贪吃蛇是否吃到食物,并处理得分、贪吃蛇身体的变化以及食物的重新生成。
判断贪吃蛇是否在游戏区域内以及是否与自身相撞,若发生碰撞则游戏结束。
● 画食物:根据食物的位置绘制矩形作为食物。
● 画贪吃蛇:根据贪吃蛇每节身体的位置绘制矩形作为贪吃蛇的身体。
● 显示速度和得分:在游戏界面上显示当前的速度和得分。
● 游戏结束提示:如果游戏结束,则在屏幕中央显示"GAME OVER"。
● pygame.display.update():更新游戏界面,使得最新的绘制内容显示在屏幕上。
'''
思路:用列表存储蛇的身体;用浅色表示身体,深色背景将身体凸显出来;
蛇的移动:仔细观察,是:身体除头和尾不动、尾部消失,头部增加,所以,新添加的元素放在列表头部、删除尾部元素;
游戏结束判定策略:超出边界;触碰到自己的身体:蛇前进的下一格子为身体的一部分(即在列表中)。
'''
#注:因为在列表中需要频繁添加和删除元素,所以用deque容器代替列表;是因为deque具有高效的插入和删除效率
#初始化蛇,长度为3,放置在屏幕左上角;
#导包
import random
import sys
import time
import pygame
from pygame.locals import *
from collections import deque
#基础设置
Screen_Height=480
Screen_Width=600
Size=20#小方格大小
Line_Width=1
#游戏区域的坐标范围
Area_x=(0,Screen_Width//Size-1) #0是左边界,1是右边界 #注:python中//为整数除法;/为浮点数除法
Area_y=(2,Screen_Height//Size-1)
#食物的初步设置
#食物的分值+颜色
Food_Style_List=[(10,(255,100,100)),(20,(100,255,100)),(30,(100,100,255))]
#整体颜色设置
Light=(100,100,100)
Dark=(200,200,200)
Black=(0,0,0)
Red=(200,30,30)
Back_Ground=(40,40,60)
#文本输出格式设置
def Print_Txt(screen,font,x,y,text,fcolor=(255,255,255)):
#font.render参数意义:.render(内容,是否抗锯齿,字体颜色,字体背景颜色)
Text=font.render(text,True,fcolor)
screen.blit(Text,(x,y))
#初始化蛇
def init_snake():
snake=deque()
snake.append((2,Area_y[0]))
snake.append((1,Area_y[0]))
snake.append((0,Area_y[0]))
return snake
#食物设置
#注意需要对食物出现在蛇身上的情况进行判断
def Creat_Food(snake):
'''
注:randint 产生的随机数区间是包含左右极限的,
也就是说左右都是闭区间的[1, n],能取到1和n。
而 randrange 产生的随机数区间只包含左极限,
也就是左闭右开的[1, n),1能取到,而n取不到。randint
产生的随机数是在指定的某个区间内的一个值,
而 randrange 产生的随机数可以设定一个步长,也就是一个间隔。
'''
food_x=random.randint(Area_x[0],Area_x[1]) #此处有疑问
food_y=random.randint(Area_y[0],Area_y[1])
#如果食物出现在蛇上,重来;
while(food_x,food_y)in snake:
food_x = random.randint(Area_x[0], Area_x[1])
food_y = random.randint(Area_y[[0], Area_y[1]])
return food_x,food_y
#食物风格
def Food_Style():
return Food_Style_List[random.randint(0,2)] #返回随机的分值和颜色
def main():
pygame.init()
screen=pygame.display.set_mode((Screen_Width,Screen_Height)) #初始化一个准备显示的窗口或屏幕
pygame.display.set_caption('贪吃蛇') #Set the current window caption
#得分字体设置
font1=pygame.font.SysFont('SimHei',24)
#GO字体设置
font2 = pygame.font.SysFont(None, 72)
fwidth, fheight = font2.size('GAME OVER') ###
#程序bug修复:如果蛇在向右移动,快速点击分别施加向下、向左的命令,向下的命令会被覆盖,只有向左的命令被接受,直接GameOver
# b变量为了防止这个情况发生
b=True
#蛇
snake=init_snake()
#食物
food=Creat_Food(snake)
food_style=Food_Style()
#方向控制
pos=(1,0) ###
#启动游戏相关变量初始化
game_over=True #结束标志 # 是否开始,当start = True,game_over = True 时,才显示 GAME OVER
game_start=False #开始标志
score=0 #得分
orispeed=0.3 #蛇初始速度
speed=orispeed #蛇速度
last_move_time=None
pause=False #暂停
while True:
for event in pygame.event.get():
if event.type==QUIT:
sys.exit()
elif event.type==KEYDOWN:
if event.key==K_RETURN:
if game_over:
game_start=True
game_over=False
b=True
snake=init_snake()
food=Creat_Food(snake)
food_style=Food_Style()
pos=(1,0)
#得分
score=0
last_move_time=time.time()
elif event.key==K_SPACE:
if not game_over:
pause=not pause
#以下为防止蛇在向右移动时按向左键,导致GameOver
elif event.key in (K_UP,K_w):
if b and not pos[1]: ###
pos=(0,-1)
b=False
elif event.key in (K_DOWN,K_s):
if b and not pos[1]:
pos = (0, 1)
b = False
elif event.key in (K_LEFT,K_a):
if b and not pos[0]:
pos = (-1, 0)
b = False
elif event.key in (K_RIGHT,K_d):
if b and not pos[0]:
pos = (1, 0)
b = False
#填充背景色
screen.fill(Back_Ground)
###
#画网格线、竖线
for x in range(Size, Screen_Width, Size):
pygame.draw.line(screen, Black, (x, Area_y[0] * Size), (x, Screen_Height), Line_Width)
#画网格线、横线
for y in range(Area_y[0] * Size, Screen_Height, Size):
pygame.draw.line(screen, Black, (0, y), (Screen_Width, y), Line_Width)
#蛇的爬行过程
if not game_over:
curTime=time.time()
if curTime-last_move_time>speed: ###
if not pause:
b=True
last_move_time=curTime
next_s = (snake[0][0] + pos[0], snake[0][1] + pos[1])
#如果吃到了食物
if next_s==food:
snake.appendleft(next_s)
score+=food_style[0]
speed = orispeed - 0.03 * (score // 100)
food = Creat_Food(snake)
food_style = Food_Style()
else:
#在区域内
if Area_x[0]<=next_s[0]<=Area_x[1] and Area_y[0]<=next_s[1]<=Area_y[1] and next_s not in snake:
snake.appendleft(next_s)
snake.pop()
else :
game_over=True
#画食物
if not game_over:
'''
rect(Surface,color,Rect,width=0)
第一个参数指定矩形绘制到哪个Surface对象上
第二个参数指定颜色
第三个参数指定矩形的范围(left,top,width,height)
第四个参数指定矩形边框的大小(0表示填充矩形)
例如绘制三个矩形:
pygame.draw.rect(screen, BLACK, (50, 50, 150, 50), 0)
pygame.draw.rect(screen, BLACK, (250, 50, 150, 50), 1)
pygame.draw.rect(screen, BLACK, (450, 50, 150, 50), 10)
'''
# 避免 GAME OVER 的时候把 GAME OVER 的字给遮住了
pygame.draw.rect(screen, food_style[1], (food[0] * Size, food[1] * Size, Size, Size), 0)
#画蛇
for s in snake:
pygame.draw.rect(screen, Dark, (s[0] * Size + Line_Width, s[1] * Size + Line_Width,
Size - Line_Width * 2, Size - Line_Width * 2), 0)
Print_Txt(screen, font1, 30, 7, f'速度: {score // 100}')
Print_Txt(screen, font1, 450, 7, f'得分: {score}')
#画GameOver
if game_over:
if game_start:
#print('GameOver')
Print_Txt(screen, font2, (Screen_Width - fwidth) // 2, (Screen_Height - fheight) // 2, 'GAME OVER',Red)
pygame.display.update()
if __name__=='__main__':
main()
1.问题1:PIL库安装,因版本更新问题,安装失败
解决方案:后查阅资料,在pycharm库中安装pillow-PIL函数,仍安装失败,最后运用命令行进行了安装。
2.问题2:安装库函数问题,部分库函数不清楚应该使用怎样的命令去安装。
解决方案:在CSDN上查阅相关的资料后,了解到在本实验中代码所需要的库函数的安装方式(pip install +库函数名字)
3.问题3:环境变量未添加正确,pytesseract 无法找到 Tesseract OCR 的可执行文件 tesseract.exe。
解决方案:修改pytesseract.py文件中的tesseract_cmd 命令行。
1.本次实验的感悟
该实验主要包含三个部分,基于OCR技术实现自动化提取图片中数据以及两个小游戏的编写,在实验过程中,我发现Python拥有丰富的标准库和第三方库,而我在连接与下载过程中也遇到了许多问题,通过查阅资料与思考解决方案,极大提高了我的编程能力,同时对于python有了更深刻的理解,python的广泛性与强大的功能且又简单的语法,令人着迷,在接下来的学习中,我会继续学习python相关的知识,提高自己的编程能力。
2.对于python课的感悟
(1)人生苦短,我用python。
(2)语法方面,Python的语法简洁清晰,易于学习和理解,使得初学者能够快速上手。同时,Python也拥有丰富的标准库和第三方库,能够支持各种开发需求,为编程提供了强大的工具。
(3)学习Python可通过编写小型项目或解决实际问题,能够使我更好地理解Python的各种概念和用法,并提升编程技能。
(4)Python是一门广泛应用于不同领域的编程语言,涵盖的知识面非常广泛。因此,学习Python是一个持续不断的过程,需要不断地学习新知识、掌握新技能,并且保持对技术发展的关注。
(5)在学习Python的过程中,我经常会遇到各种错误和bug,但是通过分析错误、查找解决方案和调试代码,极大提升了我自己的问题解决能力和编程水平。
(6)同时,老师诙谐幽默的讲课方式也引人入胜,在摸鱼的时候,还要担心老师突然提问,实质上极大调动了学生的积极性,促进了学习,希望王老师明年新生来时也这样提问哦!
● https://blog.csdn.net/xs1997/article/details/104504746
● https://blog.csdn.net/obullxl/article/details/139192429
● https://blog.csdn.net/weixin_46277553/article/details/124566711
● https://blog.csdn.net/username666/article/details/113598726
● https://blog.csdn.net/weixin_47822556/article/details/110421620