20224208 2022-2023-2《Python程序设计入门》实验四报告

20224108金昕怡 2024-05-27 20:25:11

20224208 2022-2023-2《Python程序设计入门》实验四报告

课程:《Python程序设计入门》

班级:2241

姓名:jxy

学号:20224108

实验教师:wzq

实验日期:2024年5月14日

必修/选修: 专选课

 

       (一)实验内容

        例如:编写从社交网络爬取数据,实现可视化舆情监控或者情感分析。

        例如:利用公开数据集,开展图像分类、恶意软件检测等

        例如:利用Python库,基于OCR技术实现自动化提取图片中数据,并填入excel中。

        例如:爬取天气数据,实现自动化微信提醒

        例如:利用爬虫,实现自动化下载网站视频、文件等。

        例如:编写小游戏:坦克大战、贪吃蛇、扫雷等等

        (二)实验过程

        1.实验分析

        该实验的目的是做出每个孩子童年回忆的一部分——扫雷小游戏。实验分为六个部分,分别是游戏进程、环境设置、方块变换、游戏地图、按钮、结束游戏。

        2.实验内容

        步骤一:了解扫雷小游戏的游戏规则。点开一个格子,格子里显示的数字是它周边藏的地雷的数量。要在不踩到地雷的情况下找出所有不埋雷的格子就算成功。

        步骤二:编写程序

        ①Settings.py

        首先定义一个名为setting的类,其次使用构造函数init使程序运行时恢复默认值。在这段程序中设置了屏幕大小、背景色、线条粗细与颜色、方块的宽度、界面的颜色等参数。

        ②covers.py这段代码定义了一个名为Cover的类,该类用于管理一个游戏界面中的“覆盖物”,即游戏中的方块。当玩家点击这些方块时,它们会被删除或移除。首先先用init函数初始化游戏的各个方块覆盖情况,再用self.covers储存未被点击过的方块的位置,设置为刚开始所有方块都是由覆盖的(即未被点击)。当用户点击方块时,用delete传入鼠标点击的位置,以X与Y表示,整个屏幕被分为25x25像素的方块,通过计算得出用户点击的位置是否合法(即是否在方块上),如果合法,就删除当前位置的覆盖物。

        ③map_of_games.py这段代码定义了一个名为Map的类,用于管理一个扫雷游戏中的地图。主要作用是初始化游戏地图、生成地雷、随着游戏的进程更新地图、将地图可视化等。先用“from random import randint”生成随机整数,再倒入pygame库、Over、Button等类保证程序正常运行。首先用init初始化地图,并加入踩雷时游戏的音效(音效加在同一目录下)。通过born map随机生成地雷,同样的,x、y还是代表坐标。再用connect方法更新地雷周围格子的数字。通过add接收鼠标点击的位置并判断其是否合法,并添加到now_show列表中。如果点击的格子没有地雷则调用_add_connect_方法。最后通过show方法将地图可视化,展示到屏幕中。

 

 

         ④button.py这段代码定义了一个名为button的类,这个按钮好像没什么用处,只是为了讲文字显示到屏幕上。

        ⑤game over.py这段代码定义了一个名为Over的类,作用是判断在什么情况下游戏结束并在屏幕上显示“GAME OVER”后退出游戏。在init方法中,先通过逻辑判断表示游戏是否结束,再存储游戏界面,定义了游戏结束时要显示“GAME OVER”,并把该消息放在屏幕中心。show方法的作用是将“GAME OVER”显示到屏幕上,中间暂停三秒,最后退出程序。

        ⑥Game.py 该段代码在我看来是一个集大成者,将之前所写代码统筹起来。主要定义了一个名为Game的类(class),主要作用是初始化游戏、循环游戏、检测鼠标点击了哪些方块、显示哪些方格点击了哪些方格没点击。首先导入前面写好的各个模块和类,比如cover、map、setting、button等,确保程序正确运行。在Game类中,先初始化游戏,再通过run_game方法进入游戏主循环。在_event_check_方法中检测鼠标点击,删除对应位置上的覆盖物,并将该位置的游戏地图添加到待显示队列中。在_update_screen_方法中更新游戏屏幕,显示哪些格子被覆盖哪些未被覆盖,填充背景颜色。最后三行是主程序,若一切正常则创建Game对象并运行游戏。

 

        ⑦实验实现。生成了一个扫雷小游戏。

  源代码如下:

Game.py

import sys

import pygame

 

from covers import Cover  # 未点击方块时表面的覆盖物

from map_of_game import Map  # 游戏方块里面的地图

from settings import setting  # 游戏参数设置

 

 

class Game:

 

    def __init__(self):

        pygame.init()

        pygame.mixer.init()

        self.setting = setting()

 

        # 创立游戏主界面

        self.screen = pygame.display.set_mode(self.setting.screen_size)

        self.screen_rect = self.screen.get_rect()

        pygame.display.set_caption('扫雷')

 

        self.covers = Cover(self.setting, self.screen)  # 表面覆盖物

        self.maps = Map(self.setting, self.covers, self.screen)  # 内部地图

 

        # 背景音乐

        # pygame.mixer.music.load('data/bgmusic.wav')

        # pygame.mixer.music.play()

        # pygame.mixer.music.fadeout(3)

 

    def run_game(self):

        while True:

            # if not pygame.mixer.music.get_busy():

            #       pygame.mixer.music.play()

            self._event_check_()  # 检测事件

            self._update_screen_()  # 更新屏幕

 

    def _event_check_(self):

        for event in pygame.event.get():

            if event.type == pygame.QUIT:  # 结束游戏

                sys.exit()

            elif event.type == pygame.MOUSEBUTTONDOWN:

                x, y = pygame.mouse.get_pos()  # 检测到单击鼠标事件,将鼠标的位置传入

                self.covers.delete(x, y)  # 删除对应方块上的覆盖物

                self.maps.add(x, y)  # 将该位置的覆盖物下的游戏地图加入即将要显示的队伍中

 

    def _update_screen_(self):

 

        self.screen.fill(self.setting.background_color)  # 填充背景颜色

 

        for i in range(25):  # 绘制方格

            pygame.draw.line(self.screen, self.setting.line_color, [0, i * 25], [500, i * 25],

                             self.setting.line_width)  # 横线

            pygame.draw.line(self.screen, self.setting.line_color, [i * 25, 0], [i * 25, 500],

                             self.setting.line_width)  # 竖线

 

        self.maps.show()  # 将所有被点击过的方格下的数字展现出来

        self.covers.show()  # 将还没有被点击过的数字展现出来

 

        pygame.display.update()  # 更新屏幕显示,将上面所做的工作展现在游戏界面上

 

 

if __name__ == '__main__':

    my_game = Game()

my_game.run_game()

 

setting.py

class setting:

    """管理游戏中的参数的类"""

 

    def __init__(self):

        self.screen_size = (500, 500)  # 屏幕大小

        self.background_color = (255, 255, 255)  # 背景色

        self.line_width = 1  # 线条粗细

        self.line_color = (120, 120, 120)  # 线条颜色

        self.block_width = 24  # 每一个方格的宽度

        self.screen_color = (150, 150, 150)  # 展示界面的颜色

 

covers.py

import pygame

 

class Cover:

    """管理游戏覆盖物的类"""

 

    def __init__(self, setting, screen):  # 游戏参数设置和游戏主界面

        self.setting = setting

        self.screen = screen

 

        self.covers = []  # 存储未被点击过的方块的覆盖物的位置

        for i in range(20):

            for j in range(20):

                self.covers.append([i, j])  # 刚开始时整个界面都是被覆盖的

 

    def delete(self, x, y):  # 传入单机鼠标的位置,判断是否合法,如果是,删除当前方块

        x = x // 25

        y = y // 25

        if [x, y] in self.covers:

            self.covers.remove([x, y])

 

    def show(self):  # 将所有未被点击过的方块展现出来

        for cur in self.covers:

            pygame.draw.rect(self.screen, self.setting.screen_color, ((cur[0] * 25, cur[1] * 25), (24, 24)))

 

button.py

 

import pygame

 

class Button:

    """生成图形的类"""

 

    def __init__(self, screen, message):

        self.screen = screen

        self.message = message

        self.screen_rect = self.screen.get_rect()

        self.font = pygame.font.SysFont(None, 48)

        self.font_color = (0, 70, 0)

        self.image = self.font.render(self.message, True, self.font_color, None)

        self.image_rect = self.image.get_rect()

        self.image_rect.center = self.screen_rect.center

 

    def place(self, x, y):

        self.image_rect.x = x

        self.image_rect.y = y

 

    def display(self):

        self.screen.blit(self.image, self.image_rect)

 

map_of_game.py

from random import randint

 

import pygame

 

from game_over import Over

 

from pygame.mixer import *

from button import Button

import sys

from time import sleep

 

 

class Map:

    """管理游戏中出现的雷和数字"""

 

    def __init__(self, setting, covers, screen):  # 游戏参数,游戏的覆盖物,游戏界面

        pygame.mixer.init()

        self.setting = setting

        self.bg_color = self.setting.background_color

        self.screen = screen

        self.covers = covers

 

        # 踩雷的背景音乐

        self.boot = pygame.mixer.Sound('Audio.wav')

        pygame.display.set_mode()

        self.boot.set_volume(0.2)

 

        # 开始时全部初始为0,表示当前方块啥都没有

        self.maps = [[0 for _ in range(20)] for _ in range(20)]

 

        # 状态转移数组,所有(x+moves[i][0], y+moves[i][1])表示包围坐标为(x, y)方块的另外8块方块,

        # 用于随机产生地雷后更新它周围方块上的数字

        self.moves = [[-1, -1], [0, -1], [1, -1], [-1, 0], [1, 0], [-1, 1], [0, 1], [1, 1]]

 

        # 存储当前需要被显示出来数字方块

        self.now_show = []

 

        # 点击到地雷后结束游戏

        self.over = Over(self.screen)

 

        # 随机生成游戏地图

        self._born_map()

         def _born_map(self):

        """随机生成地图"""

        for i in range(40):

            x = randint(0, 19)

            y = randint(0, 19)

            while self.maps[x][y] != 0:

                x = randint(0, 19)

                y = randint(0, 19)

            self.maps[x][y] = 'X'

            self._connect_(x, y)  # 更新地雷周围的数字

 

    def _connect_(self, x, y):

        """更新地雷周围数字的函数"""

        for cur in self.moves:

            i = x + cur[0]

            j = y + cur[1]

            if i >= 0 and i < 20 and j >= 0 and j < 20 and self.maps[i][j] != 'X':

                self.maps[i][j] += 1

 

    def add(self, x, y):  # 传入当前鼠标点击的位置,判断合法性,合法则将对应的方块左边传入要展示的列表中

        i = x // 25

        j = y // 25

 

        # 鼠标位置合法性判断

        if i < 0 and i >= 20 and j < 0 and j >= 20:

            return

 

        # 避免重复添加

        if [i, j] not in self.now_show:

            self.now_show.append([i, j])

            if self.maps[i][j] == 0:

                self._add_connect_(i, j)

 

        # 如果当前点击到了地雷,将地雷标记为红色方块,并展示出来,暂停游戏3秒,自动退出游戏

        if self.maps[i][j] == 'X':

            pygame.draw.rect(self.screen, (255, 0, 0), ((i * 25, j * 25), (25, 25)))

            # self.boot.play()

            self.over.show()

    def _add_connect_(self, x, y):

        que = []

        que.append([x, y])

        while que:

            cur = que[-1]

            del (que[-1])

            for k in range(8):

                i, j = cur[0] + self.moves[k][0], cur[1] + self.moves[k][1]

                if i >= 0 and i < 20 and j >= 0 and j < 20 and self.maps[i][j] != 'X' and [i,

                                                                                           j] not in self.now_show:

                    self.now_show.append([i, j])

                    self.covers.delete(i * 25, j * 25)

                    if self.maps[i][j] == 0:

                        que.append([i, j])

 

    def show(self):

        """将生成的地图展现到屏幕上"""

        for cur in self.now_show:

            i = cur[0]

            j = cur[1]

            if self.maps[i][j] == 0:

                continue

            else:

                self.msg = str(self.maps[i][j])

                self.font = pygame.font.SysFont(None, 45)

                self.font_image = self.font.render(self.msg, True, (60, 0, 0), None)

                self.image_ract = self.font_image.get_rect()

                self.image_ract.x = i * 25

                self.image_ract.y = j * 25

                self.image_ract.width = 24

                self.image_ract.height = 24

                self.screen.blit(self.font_image, self.image_ract)

 

game_over.py

import sys  # 结束游戏

from time import sleep  # 暂停游戏

 

import pygame

 

 

class Over:

    """控制游戏结束的类"""

 

    def __init__(self, screen):  # 游戏主界面

        self.is_over = False

        self.screen = screen

        self.screen_rect = self.screen.get_rect()

 

        self.msg = 'GAME OVER'

        # 渲染文字'GAME OVER'到游戏主界面上

        self.font = pygame.font.SysFont(None, 48)

        self.image = self.font.render(self.msg, True, (100, 0, 0), (0, 0, 60))

        self.rect = self.image.get_rect()

        self.rect.center = self.screen_rect.center  # 将文字放在界面中心

 

    def show(self):  # 遇见炸弹,游戏结束,结束前将玩家遇到的炸弹标记未红色方块并在结束前绘制出来

        self.screen.blit(self.image, self.rect)

        pygame.display.update()

        sleep(3)

        sys.exit()

 

        3.实验过程中遇到的问题和解决

        问题1:试玩游戏时,在踩雷后,“GAME OVER”飞快闪过,游戏立马退出,没有留有反应时间。

        问题1解决方案:在观看BiliBili上教程后,加入“sleep(3)”等代码,使得游戏失败界面停留三秒再退出。

        问题2:因目录下缺少wav文件导致运行程序时报错。

       问题2解决方案:在网上下载一段匹配的音乐,加到同一个目录下,并把代码中插入的音乐名字改为实际插入的名字,程序运行成功。

        问题3:编写代码时“pygame”一直标红,按照提示安装插件后显示插件安装失败。

        问题3解决方案:求助老师后,老师帮忙手动安装插件。

        4.实验心得

        在做实验四之前,我犹豫了许久,纠结要不要做扫雷小游戏。在查阅资料时,我发现利用爬虫自动发天气预报等程序较为简单,而扫雷小游戏的代码长、实现对我来说较为困难。但出于对扫雷这个童年游戏的怀念和对自己的挑战,我依旧选择了扫雷小游戏。

        在编写代码前,我上网搜索了扫雷的游戏规则与大致形式,心中基本有个方向。后来,列举出想要实现的功能,在BiliBili和CSDN上搜索相关内容,为编写程序作准备。在编写好程序后,再对其细节修改完善,例如增添背景音乐、修改游戏界面大小、延长退出时间等。在编写代码的过程中我也遇到了许多挑战,令我焦头烂额,但在老师的帮助指导下一一完成了。总的来说,这次实验是个不小的挑战,它涉及到了许多上课没讲过的知识点,也是我第一次接触一个小游戏需要5个py文件这样复杂的情况;但它也是一次自我成长的过程,加深了我对类、方法、循环等基础知识的理解,增加了我对python的兴趣,训练了我的专注力和耐心。虽然本学期课程已经结束,但学习python的脚步不会停滞。今后我会在课余时间搜集python有关知识,继续学习!

        5.课程感想与体会

        在当下掌握一门编程语言成为许多人提升自我、拓宽视野的重要途径。我也很高兴学校能给我们文科生提供学习Python的机会。通过这段时间的学习,我被Python的魅力所折服,同时也收获了许多宝贵的经验和体会。

        与高中时学习过的Visual Basic相比,Python的语法更加直观易懂,使我能够快速入门并上手。在课程中,老师生动有趣的讲解使我掌握了变量、数据类型、控制结构、函数、模块、序列等知识点,受益匪浅。我也知道了编程不只是高中的我眼中有数学思维就能写的“小case”,而是一个需要系统学习、了解计算机多方面知识、不断超越自己才能完成的“大事情”。当然在学习的过程中,我也遇到了一些困难和挑战。有时候我会因为某个问题而陷入困境,但正是这些困难让我更加珍惜每一次解决问题的过程。我学会了查阅资料、请教他人、不断尝试新的方法,这些经历不仅锻炼了我的解决问题的能力,也让我变得更加自信和坚韧。

        很荣幸能够拥有王老师作为我Python上的引路人。作为一名文科生,学习python的难度是显而易见的,但老师努力用更加通俗易懂的语言使我们理解这些知识点,还在课堂中加入“爬虫——有入门到入狱”等活泼的例子引入课堂,让枯燥的知识点生动起来。在学习python的过程中,也会不可避免遇到难题。每次向老师求救时,老师都不会嫌弃我们,会说“不行就来509”,花费大量时间帮我耐心地解决了上传Gitee、编写代码等难题。上课提问时,看到那么多同学回答不上来,但老师依旧耐心地和我们讲解一遍又一遍,始终没有“放弃”我们,说心里不感动是假的。如果下次有幸还能上老师您教的课,我一定下课认真回顾每堂课知识点,勇敢举手回答问题,让老师知道他讲的知识牢牢记载了我们心里。

        Python这门课也再次燃起了我对编程的兴趣。把一串串代码变成网页、app是一件很酷的事情,特别是每次老师在电脑上敲了一连串代码,按下回车键,电脑屏幕上就自动弹出了许多话,和电影里的黑客一样。这次编写扫雷小程序时,我在网上搜索教程并在电脑上编写,看到屏幕上显示出的扫雷的界面时十分激动,感觉自己离变成小时候向往的、能通过电脑改变世界的人又进了一步。高中时我选的科目是化学生物计算机,但大学我却因为种种原因读了文科专业,慢慢在轻松的文科课程中躺平了,懒得动脑思考了。此次Python课程也算是重新点燃了我对编程的兴趣,希望我以后能够在课余时间继续深入学习相关知识,练就过硬本领。

        最后很感谢老师一学期的辛勤付出。老师在课程的末尾祝愿所有同学未来的人生,一路繁华似锦。那我也送老师一个小小的、朴实无华的祝福:祝愿老师的教育之路,岁岁桃李芬芳。

        6.课程建议

        首先是增加课后练习。Python知识点较细,对于文科生而言掌握难度大,很容易在下一节课上课时忘记老师所讲内容,也有很少的同学会在课下主动复习课堂知识点。课后练习可以帮助同学更好掌握课堂知识点,增加学习热情。

        其次,课堂提问时采取主动发言为主、被动提问为辅的模式,让想发言的同学多发言,调动同学学习积极性。

        最后是老师可以适当严厉一些,不要太温柔,也不要太过纵容我们~

...全文
85 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

93

社区成员

发帖
与我相关
我的任务
社区描述
Python程序设计作业
软件构建 高校 北京·丰台区
社区管理员
  • blackwall0321
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧