20241313 2024-2025-2 《Python程序设计》实验四报告

20241313 2024-2025-2 《Python程序设计》实验四报告

课程:《Python程序设计》
班级: 2413
姓名:刘鸣宇
学号:20241313
实验教师:王志强
实验日期:2025年5月14日
必修/选修: 公选课

1.实验内容

Python综合应用:爬虫、数据处理、可视化、机器学习、神经网络、游戏、网络安全等。
课代表和各小组负责人收集作业(源代码、视频、综合实践报告)

Python综合应用:爬虫、数据处理、可视化、机器学习、神经网络、游戏、网络安全等。
例如:编写从社交网络爬取数据,实现可视化舆情监控或者情感分析。
例如:利用公开数据集,开展图像分类、恶意软件检测等
例如:利用Python库,基于OCR技术实现自动化提取图片中数据,并填入excel中。
例如:爬取天气数据,实现自动化微信提醒
例如:利用爬虫,实现自动化下载网站视频、文件等。
例如:编写小游戏:坦克大战、贪吃蛇、扫雷等等

2. 实验过程及结果

(1)选题:Python综合应用选择:编写小游戏。刚开始一直不知道做什么,后来在B站看到一个有意思的Python小游戏且恰好有教学,就想着做这样一个Python小游戏并且结合自己在玩的游戏《鸣潮》做一个鸣潮二创小游戏。
(2)过程:
首先是制作二创小游戏的素材制作和整理,在网络上搜集二创图片抠图收集素材,制作背景图;
然后根据教学视频自己编写Python小游戏的基础版代码并在基础版代码上添加备注
之后去运行基础版代码来查错,有不理解的问题询问AI对我的代码进行改正并解释出错的原因
再之后因为素材没有使用完,通过AI去补充进阶代码:首先是增加主界面和游戏成功的判定以及游戏结束界面,再然后增加了自主选择游戏人物的功能
(3)代码编写与AI改进:
前期基础准备:通过pip install pygame在终端安装pygame软件包

基础版代码:

import pygame
import sys

from matplotlib.pyplot import pause
from pygame.examples.scrap_clipboard import screen
from pygame.examples.sprite_texture import group
from pygame.locals import *
from random import randint

#pygame初始化
pygame.init()
pygame.mixer.init()#为音频做准备
pygame.mixer.music.load('背景音乐.mp3')#导入音乐
pygame.mixer.music.set_volume(0.2)#设置音量大小为20%
pygame.mixer.music.play(loops=-1)#设置为-1使音乐循环播放

bg=pygame.image.load('开始背景图.jpg')#设置开始封面
bg_position=bg.get_rect()

#设置游戏窗口大小
size = width,height = 1600,900
screen = pygame.display.set_mode(size)
pygame.display.set_caption('逃离莫塔里的土豆雷')#标题

#主函数
def main():
    class Up(pygame.sprite.Sprite):#定义要选择的游戏人物
        def __init__(self):
            pygame.sprite.Sprite.__init__(self)
            position=100,100#设置初始位置
            self.image=pygame.image.load('角色5.jpg')#加载游戏人物的图像
            self.rect=self.image.get_rect()#获取游戏人物的矩形区域
            self.rect.center=position#把区域设置为默认位置

        #人物的移动方法
        #向左移动
        def move_left(self):
            self.speed=[-5,0]#向左移动速度为5个像素点每秒
            # 如果移动到左边界就将人物固定在左边界
            if self.rect.left<=0:
                self.rect.left=0
            # 否则正常移动
            else:
                self.rect=self.rect.move(self.speed)
        #向右移动
        def move_right(self):
            self.speed=[5,0]
            if self.rect.right>=1600:
                self.rect.right=1600
            else:
                self.rect=self.rect.move(self.speed)
        #向上移动
        def move_up(self):
            self.speed=[0,-5]
            if self.rect.top<=0:
                self.rect.top=0
            else:
                self.rect=self.rect.move(self.speed)
        #向下移动
        def move_down(self):
            self.speed=[0,5]
            if self.rect.bottom<=900:
                self.rect.bottom=900
            else:
                self.rect=self.rect.move(self.speed)

    #定义土豆雷
    class KLT(pygame.sprite.Sprite):
        #定义初始化方法
        def __init__(self):
            pygame.sprite.Sprite.__init__(self)
            y=randint(0,900)#设置y坐标,在0到900随机出现
            position=[1600,y]#初始位置

            self.image=pygame.image.load('土豆雷.jpg')#加载土豆雷图片
            self.rect=self.image.get_rect()#获取土豆雷的矩形区域
            self.rect.center=position#获取土豆雷初始位置

            self.speed=[-3,0]#定义土豆雷的初始速度

        #设置土豆雷移动方法
        def move(self):
            self.rect=self.move(self.speed)

    #对主循环进行初始化
    up=Up()#创建人物实例
    i=0#计数器
    group=pygame.sprite.Group()#经营组管理土豆雷
    state=True#游戏状态设置为True运行中

    #设置主循环
    while state:
        for event in pygame.event.get():#用以获取所有事件
            if event.type==pygame.QUIT:#如果点击关闭按钮
                sys.exit()#退出游戏
        #设置键盘控制
        key=pygame.key.get_pressed()#获取键盘按键状态
        if key[K_LEFT]:#按下左箭头
            up.move_left()#调用人物移动左方法
        if key[K_RIGHT]:
            up.move_right()
        if key[K_UP]:
            up.move_up()
        if key[K_DOWN]:
            up.move_down()

        #设置游戏画面更新,以防出现延后问题
        screen.blit(bg,bg_position)#绘制背景图片
        screen.blit(up.image,up.rect)#绘制人物图片

        #让土豆雷在屏幕右侧随机大量出现
        i=i+1#计数器递增
        if i%10==0:#每十帧出现一只土豆雷
            klt=KLT()
            group.add(klt)#将土豆雷添加到经营组

        #判断功能,当人物碰到土豆雷时游戏结束
        for k in group.sprites():#遍历每一个土豆雷
            k.move()
            screen.blit(k.image,k.rect)#绘制土豆雷形象
            if pygame.sprite.collide_mask(up,k):#检测是否发生碰撞
                state=False
                pause()#调用结束函数



        #设置画面刷新和帧率控制
        pygame.display.flip()#更新显示画面
        pygame.time.Clock().tick(60)#设置帧率为60


#设置游戏结束函数 pause
def pause():
    bg_go=pygame.image.load('莫塔里的大手.jpg')#加载游戏结束图片
    bg_go_pos=bg_go.get_rect()
    size=width,height=1600,900#设置游戏结束窗口
    screen=pygame.display.set_mode(size)
    screen=pygame.display.set_caption('GameOver')#设置游戏结束标题

    #用于控制游戏结束流程
    while True:
        for event in pygame.event.get():
            if event.type==pygame.QUIT:
                sys.exit()
            #重玩功能
            if event.type==pygame.KEYDOWN:
                if event.key==pygame.K_ESCAPE:
                    sys.exit()

        img_src=pygame.image.load('重来按钮.jpg')#加载重玩按钮图片
        img_src_pos=img_src.get_rect()
        mouse_press=pygame.mouse.get_pressed()#获取鼠标状态
        mouse_pos=pygame.mouse.get_pos()#获取鼠标位置
        #设置鼠标边界
        left=img_src_pos.left
        right = img_src_pos.right
        top = img_src_pos.top
        bottom = img_src_pos.bottom
        #鼠标触碰重玩按钮时亮度提高
        if left+100<mouse_pos[0]<right+100 and top+185<mouse_pos[1]<bottom+185:
            img_src=pygame.image.load('重来按钮.jpg')
            if mouse_press[0]:
                main()
            #设计按钮位置
            img_src_pos=img_src.get_rect().center=100,185
            screen.blit(bg_go,bg_go_pos)#绘制游戏结束背景
            screen.blit(img_src,img_src_pos)#绘制重玩按钮
            pygame.display.flip()#更新显示
main()

基础版代码的问题分析:
首先是存在一个类初始化的代码错误,通过AI分析问题,修正了类初始化时对父类方法的调用,使用super().init()替代错误的写法,其次是未考虑素材中图片的大小和图片尺寸与游戏窗口的贴合问题,于是通过AI帮助我添加实现调节图片大小功能的代码,在此过程中AI还对我的基础版代码进行了一些地方的完善:1.修正了类初始化时对父类方法的调用,使用super().init()替代错误的写法2.为所有图像加载添加了异常处理,确保游戏在找不到图像时仍能运行3.修正了土豆雷移动方法中的错误4.使用变量width和height替代硬编码的屏幕尺寸值5.修正了游戏结束检测,使用pygame.sprite.collide_rect进行碰撞检测6.改进了游戏结束界面的按钮交互逻辑,使用事件处理替代轮询检测7.优化了土豆雷的生成和移除逻辑,移除了已经移出屏幕的土豆雷8.修正了游戏退出时的资源释放顺序9.统一使用了更具描述性的变量名klt_group替代可能与内置函数冲突的group

第二版代码:

import pygame
import sys
from pygame.locals import *
from random import randint

# pygame初始化
pygame.init()
pygame.mixer.init()  # 为音频做准备
try:
    pygame.mixer.music.load('背景音乐.mp3')  # 导入音乐
    pygame.mixer.music.set_volume(0.2)  # 设置音量大小为20%
    pygame.mixer.music.play(loops=-1)  # 设置为-1使音乐循环播放
except:
    print("无法加载背景音乐")

# 尝试加载并缩放背景图片
try:
    original_bg = pygame.image.load('背景.jpg')
    # 缩放背景图片以适应窗口大小
    bg = pygame.transform.scale(original_bg, (1600, 900))
except:
    print("无法加载开始背景图")
    # 创建一个临时背景
    bg = pygame.Surface((1600, 900))
    bg.fill((255, 255, 255))
bg_position = bg.get_rect()

# 设置游戏窗口大小
size = width, height = 1600, 900
screen = pygame.display.set_mode(size)
pygame.display.set_caption('逃离莫塔里的土豆雷')  # 标题
clock = pygame.time.Clock()  # 创建时钟对象用于控制帧率


# 主函数
def main():
    class Up(pygame.sprite.Sprite):  # 定义要选择的游戏人物
        def __init__(self):
            super().__init__()  # 正确调用父类初始化方法,AI帮助我修改此处
            position = 100, 100  # 设置初始位置
            try:
                original_image = pygame.image.load('角色5.jpg')  # 加载原始游戏人物图像
                # 缩放人物图片为原始大小的10%
                self.image = pygame.transform.scale(original_image,
                                                    (int(original_image.get_width() * 0.1),
                                                     int(original_image.get_height() * 0.1)))
            except:
                print("无法加载游戏人物图像")
                # 创建一个临时人物
                self.image = pygame.Surface((50, 50))
                self.image.fill((0, 255, 0))
            self.rect = self.image.get_rect()  # 获取游戏人物的矩形区域
            self.rect.center = position  # 把区域设置为默认位置

        # 人物的移动方法
        # 向左移动
        def move_left(self):
            self.speed = [-5, 0]  # 向左移动速度为5个像素点每秒
            # 如果移动到左边界就将人物固定在左边界
            if self.rect.left <= 0:
                self.rect.left = 0
            # 否则正常移动
            else:
                self.rect = self.rect.move(self.speed)

        # 向右移动
        def move_right(self):
            self.speed = [5, 0]
            if self.rect.right >= width:
                self.rect.right = width
            else:
                self.rect = self.rect.move(self.speed)

        # 向上移动
        def move_up(self):
            self.speed = [0, -5]
            if self.rect.top <= 0:
                self.rect.top = 0
            else:
                self.rect = self.rect.move(self.speed)

        # 向下移动
        def move_down(self):
            self.speed = [0, 5]
            if self.rect.bottom >= height:
                self.rect.bottom = height
            else:
                self.rect = self.rect.move(self.speed)

    # 定义土豆雷
    class KLT(pygame.sprite.Sprite):
        # 定义初始化方法
        def __init__(self):
            super().__init__()  # 正确调用父类初始化方法,AI帮助我修改
            y = randint(0, height - 100)  # 设置y坐标,在0到窗口高度随机出现
            position = [width, y]  # 初始位置

            try:
                original_image = pygame.image.load('土豆雷.jpg')  # 加载原始土豆雷图片
                # 缩放土豆雷图片为原始大小的5%
                self.image = pygame.transform.scale(original_image,
                                                    (int(original_image.get_width() * 0.05),
                                                     int(original_image.get_height() * 0.05)))
            except:
                print("无法加载土豆雷图片")
                # 创建一个临时土豆雷
                self.image = pygame.Surface((50, 50))
                self.image.fill((255, 0, 0))
            self.rect = self.image.get_rect()  # 获取土豆雷的矩形区域
            self.rect.center = position  # 获取土豆雷初始位置

            self.speed = [-3, 0]  # 定义土豆雷的初始速度

        # 设置土豆雷移动方法
        def move(self):
            self.rect = self.rect.move(self.speed)

    # 对主循环进行初始化
    up = Up()  # 创建人物实例
    i = 0  # 计数器
    klt_group = pygame.sprite.Group()  # 管理土豆雷的组
    state = True  # 游戏状态设置为True运行中

    # 设置主循环
    while state:
        for event in pygame.event.get():  # 用以获取所有事件
            if event.type == pygame.QUIT:  # 如果点击关闭按钮
                pygame.quit()
                sys.exit()  # 退出游戏

        # 设置键盘控制
        key = pygame.key.get_pressed()  # 获取键盘按键状态
        if key[K_LEFT]:  # 按下左箭头
            up.move_left()  # 调用人物移动左方法
        if key[K_RIGHT]:
            up.move_right()
        if key[K_UP]:
            up.move_up()
        if key[K_DOWN]:
            up.move_down()

        # 设置游戏画面更新
        screen.blit(bg, bg_position)  # 绘制背景图片
        screen.blit(up.image, up.rect)  # 绘制人物图片

        # 让土豆雷在屏幕右侧随机大量出现
        i = i + 1  # 计数器递增
        if i % 10 == 0:  # 每十帧出现一只土豆雷
            klt = KLT()
            klt_group.add(klt)  # 将土豆雷添加到组

        # 判断功能,当人物碰到土豆雷时游戏结束
        for k in klt_group.sprites():  # 遍历每一个土豆雷
            k.move()
            # 移除已经移出屏幕的土豆雷
            if k.rect.right < 0:
                klt_group.remove(k)
                continue
            screen.blit(k.image, k.rect)  # 绘制土豆雷形象
            if pygame.sprite.collide_rect(up, k):  # 检测是否发生碰撞
                state = False
                pause()  # 调用结束函数

        # 设置画面刷新和帧率控制
        pygame.display.flip()  # 更新显示画面
        clock.tick(60)  # 设置帧率为60


# 设置游戏结束函数 pause
def pause():
    global screen, width, height  # 声明使用全局变量
    try:
        original_bg_go = pygame.image.load('莫塔里的大手.jpg')  # 加载原始游戏结束图片
        # 缩放游戏结束背景图片以适应窗口大小
        bg_go = pygame.transform.scale(original_bg_go, (width, height))
    except:
        print("无法加载游戏结束图片")
        # 创建一个临时结束背景
        bg_go = pygame.Surface((width, height))
        bg_go.fill((0, 0, 0))
    bg_go_pos = bg_go.get_rect()

    pygame.display.set_caption('GameOver')  # 设置游戏结束标题

    try:
        original_button = pygame.image.load('重来按钮.jpg')  # 加载原始重玩按钮图片
        # 缩放按钮图片为原始大小的10%
        img_src = pygame.transform.scale(original_button,
                                         (int(original_button.get_width() * 0.1),
                                          int(original_button.get_height() * 0.1)))
    except:
        print("无法加载重玩按钮图片")
        # 创建一个临时按钮
        img_src = pygame.Surface((200, 100))
        img_src.fill((255, 255, 0))

    img_src_pos = img_src.get_rect()
    img_src_pos.center = (width // 2, height // 2 + 100)  # 设置按钮位置在屏幕中央偏下

    # 用于控制游戏结束流程
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            # 重玩功能
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    pygame.quit()
                    sys.exit()
            # 鼠标点击事件处理
            if event.type == pygame.MOUSEBUTTONDOWN:
                if event.button == 1:  # 左键点击
                    if img_src_pos.collidepoint(event.pos):  # 检查是否点击了按钮
                        main()  # 重新开始游戏

        # 始终绘制普通按钮,移除了鼠标悬停效果
        screen.blit(bg_go, bg_go_pos)  # 绘制游戏结束背景
        screen.blit(img_src, img_src_pos)  # 绘制普通按钮

        pygame.display.flip()  # 更新显示


if __name__ == "__main__":
    main()

第二版代码到最终版代码的完善与进一步改进:完成第二版代码后我有许多准备的素材并没有使用,于是添加了更加完善与丰富的功能来使我的素材充分使用,我添加了游戏的主界面,主界面有开始游戏和退出游戏的按钮,添加了结束界面和游戏成功的判定条件,并最终增加了自主选择游戏人物的功能,至此,最终版代码完成。

最终版代码:

import pygame
import sys
from pygame.locals import *
from random import randint

# pygame初始化
pygame.init()
pygame.mixer.init()  # 为音频做准备

# 设置游戏窗口大小
size = width, height = 1600, 900
screen = pygame.display.set_mode(size)
pygame.display.set_caption('逃离莫塔里的土豆雷')  # 标题
clock = pygame.time.Clock()  # 创建时钟对象用于控制帧率


# 图片缩放函数
def scale_image(image, target_width, target_height):
    """按目标尺寸缩放图片,确保完全贴合窗口"""
    return pygame.transform.scale(image, (target_width, target_height))


# 游戏主界面
def game_menu():
    """显示游戏主界面,包含开始和退出按钮"""
    # 加载背景
    try:
        menu_bg = pygame.image.load('开始背景图.jpg')
        menu_bg = scale_image(menu_bg, width, height)  # 缩放至窗口大小
    except:
        print("无法加载游戏主界面图片")
        menu_bg = pygame.Surface((width, height))
        menu_bg.fill((0, 0, 100))  # 蓝色背景作为替代

    # 加载按钮
    try:
        start_button = pygame.image.load('开始按钮.jpg')
        # 按原始尺寸的10%缩放
        start_button = scale_image(start_button,
                                   int(start_button.get_width() * 0.1),
                                   int(start_button.get_height() * 0.1))
        exit_button = pygame.image.load('退出按钮.jpg')
        exit_button = scale_image(exit_button,
                                  int(exit_button.get_width() * 0.1),
                                  int(exit_button.get_height() * 0.1))
    except:
        print("无法加载按钮图片")
        start_button = pygame.Surface((300, 100))
        start_button.fill((0, 255, 0))  # 绿色按钮
        exit_button = pygame.Surface((300, 100))
        exit_button.fill((255, 0, 0))  # 红色按钮

    # 设置按钮位置
    start_rect = start_button.get_rect(center=(width // 2, height // 2 - 100))
    exit_rect = exit_button.get_rect(center=(width // 2, height // 2 + 100))

    # 主界面循环
    while True:
        screen.blit(menu_bg, (0, 0))
        screen.blit(start_button, start_rect)
        screen.blit(exit_button, exit_rect)

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            elif event.type == pygame.MOUSEBUTTONDOWN:
                if event.button == 1:  # 左键点击
                    if start_rect.collidepoint(event.pos):
                        return character_selection()  # 进入角色选择界面
                    elif exit_rect.collidepoint(event.pos):
                        pygame.quit()
                        sys.exit()

        pygame.display.flip()
        clock.tick(60)


# 角色选择界面
def character_selection():
    """角色选择界面,显示六个角色供玩家选择"""
    # 加载背景
    try:
        select_bg = pygame.image.load('背景.jpg')
        select_bg = scale_image(select_bg, width, height)  # 缩放至窗口大小
    except:
        print("无法加载角色选择背景图")
        select_bg = pygame.Surface((width, height))
        select_bg.fill((200, 200, 200))  # 灰色背景作为替代

    # 加载角色图片
    characters = []
    character_rects = []
    for i in range(1, 7):  # 加载6个角色
        try:
            character_img = pygame.image.load(f'角色{i}.jpg')
            # 按原始尺寸的10%缩放
            character_img = scale_image(character_img,
                                        int(character_img.get_width() * 0.1),
                                        int(character_img.get_height() * 0.1))
            characters.append(character_img)
        except:
            print(f"无法加载角色{i}图片")
            # 创建临时角色图片
            temp_img = pygame.Surface((100, 150))
            temp_img.fill((i * 30 % 255, i * 50 % 255, i * 70 % 255))
            characters.append(temp_img)

    # 计算角色排列位置(三行三列)
    spacing_x = width // 8
    spacing_y = height // 5
    start_x = spacing_x * 2
    start_y = spacing_y * 2

    for i, char in enumerate(characters):
        x = start_x + (i % 3) * (width - start_x * 2) // 2
        y = start_y + (i // 3) * spacing_y
        rect = char.get_rect(center=(x, y))
        character_rects.append(rect)

    # 角色选择界面循环
    while True:
        screen.blit(select_bg, (0, 0))

        # 绘制角色和选择提示
        font = pygame.font.Font(None, 50)
        title = font.render("请选择游戏角色", True, (255, 255, 255))
        screen.blit(title, (width // 2 - title.get_width() // 2, spacing_y))

        for i, char in enumerate(characters):
            screen.blit(char, character_rects[i])

        # 事件处理
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            elif event.type == pygame.MOUSEBUTTONDOWN:
                if event.button == 1:  # 左键点击
                    for i, rect in enumerate(character_rects):
                        if rect.collidepoint(event.pos):
                            return i + 1  # 返回选择的角色编号

        pygame.display.flip()
        clock.tick(60)


# 游戏成功结束界面
def game_success():
    """显示游戏成功结束界面,包含退出按钮"""
    # 加载背景
    try:
        success_bg = pygame.image.load('莫塔里小丑.jpg')
        success_bg = scale_image(success_bg, width, height)  # 缩放至窗口大小
    except:
        print("无法加载游戏成功图片")
        success_bg = pygame.Surface((width, height))
        success_bg.fill((0, 100, 0))  # 绿色背景作为替代

    # 加载按钮
    try:
        exit_button = pygame.image.load('退出按钮.jpg')
        # 按原始尺寸的10%缩放
        exit_button = scale_image(exit_button,
                                  int(exit_button.get_width() * 0.1),
                                  int(exit_button.get_height() * 0.1))
    except:
        print("无法加载退出按钮图片")
        exit_button = pygame.Surface((300, 100))
        exit_button.fill((255, 0, 0))  # 红色按钮

    # 设置按钮位置
    exit_rect = exit_button.get_rect(center=(width // 2, height // 2 + 150))

    # 成功界面循环
    while True:
        screen.blit(success_bg, (0, 0))
        screen.blit(exit_button, exit_rect)

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            elif event.type == pygame.MOUSEBUTTONDOWN:
                if event.button == 1 and exit_rect.collidepoint(event.pos):
                    pygame.quit()
                    sys.exit()

        pygame.display.flip()
        clock.tick(60)


# 主函数
def main():
    # 显示游戏主界面并获取选择的角色
    selected_character = game_menu()

    # 游戏背景音乐
    try:
        pygame.mixer.music.load('背景音乐.mp3')
        pygame.mixer.music.set_volume(0.2)
        pygame.mixer.music.play(loops=-1)
    except:
        print("无法加载背景音乐")

    # 加载并缩放开始背景图
    try:
        bg = pygame.image.load('背景.jpg')
        bg = scale_image(bg, width, height)  # 缩放至窗口大小
    except:
        print("无法加载开始背景图")
        bg = pygame.Surface((width, height))
        bg.fill((255, 255, 255))
    bg_position = bg.get_rect()

    class Up(pygame.sprite.Sprite):  # 定义要选择的游戏人物
        def __init__(self, character_id):
            super().__init__()  # 正确调用父类初始化方法
            position = 100, 100  # 设置初始位置

            # 加载选择的角色图片
            try:
                character_img = pygame.image.load(f'角色{character_id}.jpg')
                # 缩放人物图片为原始大小的5%
                self.image = scale_image(character_img,
                                         int(character_img.get_width() * 0.05),
                                         int(character_img.get_height() * 0.05))
            except:
                print(f"无法加载角色{character_id}图片")
                # 创建一个临时人物
                self.image = pygame.Surface((50, 50))
                self.image.fill((character_id * 30 % 255, character_id * 50 % 255, character_id * 70 % 255))
            self.rect = self.image.get_rect()  # 获取游戏人物的矩形区域
            self.rect.center = position  # 把区域设置为默认位置

        # 人物的移动方法
        def move_left(self):
            self.speed = [-5, 0]
            if self.rect.left <= 0:
                self.rect.left = 0
            else:
                self.rect = self.rect.move(self.speed)

        def move_right(self):
            self.speed = [5, 0]
            if self.rect.right >= width:
                self.rect.right = width
            else:
                self.rect = self.rect.move(self.speed)

        def move_up(self):
            self.speed = [0, -5]
            if self.rect.top <= 0:
                self.rect.top = 0
            else:
                self.rect = self.rect.move(self.speed)

        def move_down(self):
            self.speed = [0, 5]
            if self.rect.bottom >= height:
                self.rect.bottom = height
            else:
                self.rect = self.rect.move(self.speed)

    # 定义土豆雷
    class KLT(pygame.sprite.Sprite):
        def __init__(self):
            super().__init__()
            y = randint(0, height - 100)
            position = [width, y]

            try:
                original_image = pygame.image.load('土豆雷.jpg')
                # 缩放土豆雷图片为原始大小的5%
                self.image = scale_image(original_image,
                                         int(original_image.get_width() * 0.05),
                                         int(original_image.get_height() * 0.05))
            except:
                print("无法加载土豆雷图片")
                self.image = pygame.Surface((50, 50))
                self.image.fill((255, 0, 0))
            self.rect = self.image.get_rect()
            self.rect.center = position
            self.speed = [-3, 0]

        def move(self):
            self.rect = self.rect.move(self.speed)

    # 对主循环进行初始化
    up = Up(selected_character)
    i = 0
    klt_group = pygame.sprite.Group()
    state = True

    # 设置主循环
    while state:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()

        # 设置键盘控制
        key = pygame.key.get_pressed()
        if key[K_LEFT]:
            up.move_left()
        if key[K_RIGHT]:
            up.move_right()
        if key[K_UP]:
            up.move_up()
        if key[K_DOWN]:
            up.move_down()

        # 游戏成功判定:人物到达窗口右侧
        if up.rect.right >= width:
            game_success()
            state = False

        # 设置游戏画面更新
        screen.blit(bg, bg_position)
        screen.blit(up.image, up.rect)

        # 让土豆雷在屏幕右侧随机大量出现
        i = i + 1
        if i % 10 == 0:
            klt = KLT()
            klt_group.add(klt)

        # 判断功能,当人物碰到土豆雷时游戏结束
        for k in klt_group.sprites():
            k.move()
            if k.rect.right < 0:
                klt_group.remove(k)
                continue
            screen.blit(k.image, k.rect)
            if pygame.sprite.collide_rect(up, k):
                state = False
                pause()  # 调用结束函数

        pygame.display.flip()
        clock.tick(60)


# 设置游戏结束函数 pause
def pause():
    global screen, width, height
    try:
        original_bg_go = pygame.image.load('莫塔里的大手.jpg')
        bg_go = scale_image(original_bg_go, width, height)  # 缩放至窗口大小
    except:
        print("无法加载游戏结束图片")
        bg_go = pygame.Surface((width, height))
        bg_go.fill((0, 0, 0))
    bg_go_pos = bg_go.get_rect()

    pygame.display.set_caption('GameOver')

    try:
        original_button = pygame.image.load('重来按钮.jpg')
        # 缩放按钮图片为原始大小的10%
        img_src = scale_image(original_button,
                              int(original_button.get_width() * 0.1),
                              int(original_button.get_height() * 0.1))
    except:
        print("无法加载重玩按钮图片")
        img_src = pygame.Surface((200, 100))
        img_src.fill((255, 255, 0))

    img_src_pos = img_src.get_rect()
    img_src_pos.center = (width // 2, height // 2 + 100)

    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    pygame.quit()
                    sys.exit()
            if event.type == pygame.MOUSEBUTTONDOWN:
                if event.button == 1:
                    if img_src_pos.collidepoint(event.pos):
                        main()  # 重新开始游戏

        screen.blit(bg_go, bg_go_pos)
        screen.blit(img_src, img_src_pos)

        pygame.display.flip()
        clock.tick(60)


if __name__ == "__main__":
    main()

代码运行展示视频:

第二版代码:
第二版
最终版代码:
最终版

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

因为是在观看完教学视频的基础上完成我的代码的,因此在代码的基础版存在的问题较少,大多是在后续的优化与改进上通过AI去实现改进与完善,一些存在的问题,通过询问AI基本得到解决与理解。

  • 问题1:基础版代码运行后闪退的问题
  • 问题1解决方案:通过询问AI得到解决,是因为我类初始化时代码有误,使用super().init()替代错误的写法
    从第二版代码开始,AI在完成我所要求的功能的同时为我的代码增加了大量的异常处理,使我的代码更加完善。

其他(感悟、思考等)

在自己独立完成一个Python小游戏的制作与完善全过程(虽然观看了教学视频并且很多优化都是AI实现我去理解AI为我添加的代码)中我才发现只有自己亲手去从零开始完成一个程序才能切身的体会到一个从学习到应用的过程,在前期的素材准备中我就已经用来很多的时间,编写基础版代码的过程是很煎熬痛苦的,好几次不想写了但还是坚持了下来,在程序成功运行时就觉得之前的努力都是值得的,尤其是在后续的一步步优化代码,去运行查看优化效果,看着自己做的小游戏越来越符合自己一开始的预期,心里是很开心的,这学期的Python课程的收获很多,感谢王老师!!!

课程总结

在这一学期的python公选课中,在王老师的带领下我学习了python的一系列知识,我了解到 Python 是一种高级、解释型的编程语言,具有简洁易读的语法,可以广泛应用于 Web 开发、数据分析、人工智能等多个领域,简洁易学,也学习了Python的基础语法、运算符、控制结构、数据结构(列表、元组、字典)、函数、模块与包等一系列知识,在四次实验中逐步将所学习的知识运用到实践中,更深一步的体会到python的强大能力和对比于C语言的巨大简洁性。王老师的python公选课课堂气氛轻松诙谐,与我们交流就像彼此的朋友一样,教授知识也通俗易懂,感谢王老师这一学期的陪伴与教导!

补码云平台仓库代码:(256为基础版代码,000为第二版代码,001为最终版代码,实验四文件中有全部代码和素材照片)
码云平台

posted @ 2025-06-10 13:04  Camellia×  阅读(32)  评论(0)    收藏  举报