20244102 实验四《Python程序设计》实验报告

课程:《Python程序设计》
班级: 2441
姓名: 丁可
学号:20244102
实验教师:王志强
实验日期:2025年5月29日
必修/选修: 公选课
一、实验内容
Python综合应用:爬虫、数据处理、可视化、机器学习、神经网络、游戏、网络安全等。
在日常的生活中,需要游戏来解压,于是我编写了小游戏:贪吃蛇!!!
二、实验过程

(一)搭建游戏框架
1.导入所需的库:

点击查看代码
import pygame
import time
import random
2.初始化 Pygame:
点击查看代码
pygame.init()
3.设置游戏窗口:
点击查看代码
window_width = 800
window_height = 600
game_window = pygame.display.set_mode((window_width, window_height))
pygame.display.set_caption("贪吃蛇游戏")
4.定义颜色和字体:
点击查看代码
black = (0, 0, 0)
white = (255, 255, 255)
red = (255, 0, 0)
green = (0, 255, 0)
font = pygame.font.SysFont('arial', 50)
(二)实现蛇类 1.定义蛇类的初始化方法,设置蛇的初始位置、移动方向和身体列表:
点击查看代码
class Snake:
    def __init__(self):
        self.body = [[10, 10], [9, 10], [8, 10]]  # 初始身体位置,头部在[10,10]
        self.direction = 'RIGHT'  # 初始方向向右
        self.next_direction = 'RIGHT'  # 下一个方向,用于防止反向移动
2.实现移动方法,根据当前方向更新蛇头的位置,并将蛇尾移除(除非吃掉食物):
点击查看代码
    def move(self):
        self.next_direction = self.direction  # 更新下一个方向为当前方向
        for event in pygame.event.get():
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_LEFT and self.direction != 'RIGHT':
                    self.next_direction = 'LEFT'
                elif event.key == pygame.K_RIGHT and self.direction != 'LEFT':
                    self.next_direction = 'RIGHT'
                elif event.key == pygame.K_UP and self.direction != 'DOWN':
                    self.next_direction = 'UP'
                elif event.key == pygame.K_DOWN and self.direction != 'UP':
                    self.next_direction = 'DOWN'
        self.direction = self.next_direction  # 更新当前方向为下一个方向

        head = self.body[0].copy()  # 获取当前头部位置
        if self.direction == 'RIGHT':
            head[0] += 1
        elif self.direction == 'LEFT':
            head[0] -= 1
        elif self.direction == 'UP':
            head[1] -= 1
        elif self.direction == 'DOWN':
            head[1] += 1

        self.body.insert(0, head)  # 将新头部插入身体列表开头
3.实现增长方法,当蛇吃掉食物时,不移除蛇尾,使蛇身增长:
点击查看代码
    def grow(self):
        pass  # 因为在移动时,只有在没吃到食物时才移除蛇尾,所以增长通过不移除蛇尾实现
4.实现碰撞检测方法,检测蛇头是否碰到边界或自身身体:
点击查看代码
    def check_collision(self):
        head = self.body[0]
        # 检测边界碰撞
        if head[0] < 0 or head[0] >= 40 or head[1] < 0 or head[1] >= 30:
            return True
        # 检测自身碰撞
        for segment in self.body[1:]:
            if head == segment:
                return True
        return False
(三)实现食物类 定义食物类的初始化方法,随机生成食物的位置:
点击查看代码
class Food:
    def __init__(self, snake_body):
        self.position = self.generate_position(snake_body)

    def generate_position(self, snake_body):
        while True:
            x = random.randint(0, 39)
            y = random.randint(0, 29)
            if [x, y] not in snake_body:
                return [x, y]
(四)游戏主循环 1.初始化蛇和食物对象:
点击查看代码
snake = Snake()
food = Food(snake.body)
2.设置初始分数和速度:
点击查看代码
score = 0
speed = 150  # 初始速度,单位为毫秒/步
3.进入游戏主循环,处理事件、更新游戏状态和绘制画面:
点击查看代码
game_over = False
while not game_over:
    game_window.fill(black)  # 填充背景颜色

    # 处理事件
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            game_over = True

    # 移动蛇
    snake.move()

    # 检测是否吃到食物
    head = snake.body[0]
    if head == food.position:
        score += 10
        speed -= 20  # 加快速度
        snake.body.append([-1, -1])  # 添加一个无效位置,用于增长,实际在移动时不会移除
        food = Food(snake.body)  # 生成新食物

    # 检测碰撞
    if snake.check_collision():
        game_over = True

    # 绘制蛇
    for segment in snake.body:
        pygame.draw.rect(game_window, green, (segment[0] * 20, segment[1] * 20, 20, 20))

    # 绘制食物
    pygame.draw.rect(game_window, red, (food.position[0] * 20, food.position[1] * 20, 20, 20))

    # 显示分数
    score_text = font.render("分数: " + str(score), True, white)
    game_window.blit(score_text, (10, 10))

    pygame.display.update()  # 更新画面

    time.sleep(speed / 1000)  # 控制游戏速度
4.游戏结束后显示游戏结束提示:
点击查看代码
game_over_text = font.render("游戏结束!分数: " + str(score), True, red)
game_window.blit(game_over_text, (window_width // 2 - 200, window_height // 2 - 50))
pygame.display.update()
time.sleep(3)  # 等待3秒后退出
5.完整程序:
点击查看代码
import pygame
import time
import random

pygame.init()

window_width = 800
window_height = 600
game_window = pygame.display.set_mode((window_width, window_height))
pygame.display.set_caption("贪吃蛇游戏")

black = (0, 0, 0)
white = (255, 255, 255)
red = (255, 0, 0)
green = (0, 255, 0)

font = pygame.font.SysFont('arial', 50)


class Snake:
    def __init__(self):
        self.body = [[10, 10], [9, 10], [8, 10]]  # 初始身体位置,头部在[10,10]
        self.direction = 'RIGHT'  # 初始方向向右
        self.next_direction = 'RIGHT'  # 下一个方向,用于防止反向移动

    def move(self):
        # 移除了这里的事件处理,改为在主循环中统一处理
        self.direction = self.next_direction  # 更新当前方向为下一个方向

        head = self.body[0].copy()  # 获取当前头部位置
        if self.direction == 'RIGHT':
            head[0] += 1
        elif self.direction == 'LEFT':
            head[0] -= 1
        elif self.direction == 'UP':
            head[1] -= 1
        elif self.direction == 'DOWN':
            head[1] += 1

        self.body.insert(0, head)  # 将新头部插入身体列表开头

    def grow(self):
        pass  # 因为在移动时,只有在没吃到食物时才移除蛇尾,所以增长通过不移除蛇尾实现

    def check_collision(self):
        head = self.body[0]
        # 检测边界碰撞
        if head[0] < 0 or head[0] >= 40 or head[1] < 0 or head[1] >= 30:
            return True
        # 检测自身碰撞
        for segment in self.body[1:]:
            if head == segment:
                return True
        return False


class Food:
    def __init__(self, snake_body):
        self.position = self.generate_position(snake_body)

    def generate_position(self, snake_body):
        while True:
            x = random.randint(0, 39)
            y = random.randint(0, 29)
            if [x, y] not in snake_body:
                return [x, y]


# 游戏初始化
snake = Snake()
food = Food(snake.body)
score = 0
initial_speed = 150  # 初始速度,单位为毫秒/步
speed = initial_speed
game_over = False

# 游戏时钟,用于控制帧率
clock = pygame.time.Clock()

while not game_over:
    # 处理事件
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            game_over = True
        elif event.type == pygame.KEYDOWN:
            # 在主循环中统一处理方向键
            if event.key == pygame.K_LEFT and snake.direction != 'RIGHT':
                snake.next_direction = 'LEFT'
            elif event.key == pygame.K_RIGHT and snake.direction != 'LEFT':
                snake.next_direction = 'RIGHT'
            elif event.key == pygame.K_UP and snake.direction != 'DOWN':
                snake.next_direction = 'UP'
            elif event.key == pygame.K_DOWN and snake.direction != 'UP':
                snake.next_direction = 'DOWN'

    # 移动蛇
    snake.move()

    # 检测是否吃到食物
    head = snake.body[0]
    if head == food.position:
        score += 10
        # 调整速度的方式更合理,避免过快
        speed = max(50, initial_speed - score // 10 * 5)
        # 添加一个无效位置,用于增长,实际在移动时不会移除
        snake.body.append([-1, -1])
        food = Food(snake.body)  # 生成新食物
    else:
        # 如果没吃到食物,移除尾部
        snake.body.pop()

    # 检测碰撞
    if snake.check_collision():
        game_over = True

    # 绘制游戏元素
    game_window.fill(black)  # 填充背景颜色

    # 绘制蛇
    for segment in snake.body:
        pygame.draw.rect(game_window, green, (segment[0] * 20, segment[1] * 20, 20, 20))

    # 绘制食物
    pygame.draw.rect(game_window, red, (food.position[0] * 20, food.position[1] * 20, 20, 20))

    # 显示分数和速度
    score_text = font.render(f"分数: {score}", True, white)
    speed_text = font.render(f"速度: {1000 // speed:.1f} FPS", True, white)
    game_window.blit(score_text, (10, 10))
    game_window.blit(speed_text, (10, 60))

    pygame.display.update()  # 更新画面

    # 使用pygame的时钟控制帧率,替代原来的time.sleep
    clock.tick(1000 / speed)

# 游戏结束画面
game_over_text = font.render(f"游戏结束!分数: {score}", True, red)
game_window.blit(game_over_text, (window_width // 2 - 200, window_height // 2 - 50))
pygame.display.update()
time.sleep(3)  # 等待3秒后退出    

(五)程序运行
【屏幕录制 2025-05-29 212353】 https://www.bilibili.com/video/BV1MH75zjEHa/?share_source=copy_web&vd_source=1b8c219f085f846d6b50bcb3aedd408b
三、问题总结
1.发现了我的pycharm缺少pygame库。于是我手动安装了!!!!

2.发现还是不行,是虚拟环境创建失败。于是我创建虚拟环境。

3.好不容易上两个问题解决了,结果运行的时候发现我的贪吃蛇不受我控制,我的键盘不管用。老师您估计也发现我的完整代码和前面的步骤有所不同了。后来我才发现方向键控制逻辑被重复实现了,导致部分按键失效。问题出在 Snake.move() 方法中处理了按键事件,但主循环中也处理了事件。这导致按键可能被主循环捕获而不是蛇的移动逻辑。于是我移除重复的事件处理,并确保方向控制更加流畅。
四、课程总结与建议
(一)实验总结
通过本次实验,我将课堂中学习的Python知识运用到了日常学习生活,激发了我学习Python语言的热情,帮助我回顾了过去学过的Python知识,也让我拓展了所学,对虚拟环境的创建、pygame安装等模块有了更深的理解。尽管遇到了些许困难,但我体会到了将课堂上的知识应用到实际的感觉,编程能力得到了很大的提高。而且这次游戏成功运行,给我带来了成就感!呜呜呜真的太不容易了,尤其是pygame这一块,我终于调整成功了!
(二)课程总结
首先,我想对您说,您是一个很和蔼可亲的老师!您讲课的方式很幽默轻松,您给我评论过朋友圈,大大拉近了我们之间的距离,我更喜欢听您的课了!您一直在给我们降低难度,充分考虑我们作为文科生的不易,并且你通过英语打卡的方式激励我们学英语,让我不再畏惧四级英语!
几周一晃就过去了,Python 课就像本打开的入门书,从打印 "Hello World" 到摆弄列表字典,再到试着写点小功能,一步一步摸着石头过河。刚开始敲代码总报错,对着屏幕改半天;后来试着用函数把重复的事打包,突然觉得程序像模像样了。我曾经对python没有一点好感,但是今天通过我的努力成功运行一个小游戏,我发现我真的爱上python啦!
感谢您这段时间的付出,听您讲课真的很轻松愉快,尽管以后没有python课,我也会继续运行一些我喜欢的程序的!毕竟真的很有意思哈哈哈哈。真的很开心遇见了您!!!!!!!!
(三)意见建议
能不能签到弄得简单一点呀,我没有一次是自己签成功的哈哈哈

posted @ 2025-05-29 21:53  dk丁可  阅读(56)  评论(0)    收藏  举报