20244209 2024-2025-2 《Python程序设计》实验4报告

课程:《Python程序设计》
班级: 2442
姓名: 韩仕炜
学号:20244209
实验教师:王志强
实验日期:2025年5月13日
必修/选修: 公选课

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

2、实验内容
我选择了用 Python 制作贪吃蛇小游戏。根据上课所学和b站视频内容,我通过 Pygame 库设置窗口与颜色,用列表存储蛇身坐标,以此实现方向控制、食物随机生成及碰撞检测等。玩家则可控制蛇的前进方向让它吃到食物实现蛇身变长,若蛇撞到边界或撞到自己游戏结束。

3、实验过程
(1)导入模块与初始化

首先,我导入游戏开发所需的pygame库和随机数生成库random,并初始化 Pygame 的所有模块。实现了自定义窗口尺寸和单元格大小、游戏中的颜色、文本语言等。
其中,结合课上所学与网络视频教学,我运用到了多种代码。如运用变量赋值的代码,定义一个元组类型的变量window_size,实现存储游戏窗口的宽度(640像素)和高度(480像素)信息;运用变量赋值的代码,分别定义四个元组类型的变量,以RGB格式存储黑色、白色、绿色、红色的颜色值,实现为游戏中不同元素(如背景、蛇身、食物等)提供颜色定义;运用函数调用的代码,调用pygame.display.set_caption函数,传入字符串参数"Snake Game",实现设置游戏窗口的标题。
(2)游戏变量初始化

在这一部分里,我多次运用变量赋值的代码格式定义了游戏的核心变量,如蛇的位置、方向、食物位置、游戏状态等。如snake_position = [(100, 100), (80, 100), (60, 100)]
用变量赋值的代码格式,定义了一个列表类型的变量snake_position,列表元素为元组,实现存储贪吃蛇初始状态下,各个身体部分在游戏窗口中的坐标位置。其中,clock = pygame.time.Clock()运用函数调用并赋值的代码,调用pygame.time.Clock函数,实现创建一个时钟对象clock,用于控制游戏的帧率。
(3)游戏辅助函数

在该部分,我使用了循环语句、条件判断语句等实现游戏搭建。
使用while True循环语句,作为游戏主循环,持续监听用户输入(如按键、窗口关闭)并更新游戏状态,持续生成食物位置坐标,直到找到不与蛇身重叠的位置。
使用if-elif 条件判断,处理方向控制(如按上键时改变蛇的移动方向),并防止蛇 180 度转向(如向右移动时不能直接向左转)。
运用列表操作知识,运用snake.insert(0, new_head) 和 snake.pop(),实现蛇的移动逻辑 —— 添加新头部并移除尾部,若吃到食物则不移除尾部(蛇身增长)。
(4)游戏主循环
在游戏主循环中,控制游戏帧率,处理用户事件(如关闭窗口),绘制游戏背景、蛇和食物,实现蛇的移动逻辑以及蛇与食物的碰撞检测和处理 ,并更新屏幕显示。

综合使用多种语句构建主循环。
首先,使用while True 循环语句,构建游戏的主循环,让游戏持续运行,不断处理游戏中的各种事件(如用户输入、游戏状态更新等),直到满足特定的退出条件(即发生碰撞)。
其次,使用for循环语句,结合 Pygame 的pygame.event.get()函数。pygame.event.get()用于获取当前所有的事件(如窗口关闭、键盘按键等),for循环对获取到的事件序列进行遍历,以便针对不同类型的事件(如退出事件、按键事件等)进行相应处理,实现游戏与用户的交互。
然后,我还使用if-elif-if 条件判断,根据条件判断是否执行相应代码块,elif用于添加额外的条件分支,多个if可以实现更复杂的并列条件判断。以便在事件处理过程中,对不同类型的事件以及同一类型事件下的不同情况(如不同按键按下)进行分类处理。比如,判断用户是否按下关闭窗口按钮来退出游戏;根据按下的方向键改变蛇的移动方向,同时避免蛇反向移动;在游戏结束后,判断用户按下的是重新开始键(r)还是退出键(q),并执行相应的操作(重置游戏或退出游戏 )。

接着,我使用了赋值运算符的知识,将变量change_to 的值赋给snake_direction,更新蛇的移动方向。使游戏可依据用户按键操作,实时更新蛇在游戏中的移动方向。
我还通过 if-elif 结构进行多条件判断,根据 snake_direction 的不同取值("UP"、"DOWN"、"LEFT"、"RIGHT" ),执行相应的坐标计算代码块。游戏根据当前蛇的移动方向,计算蛇头在游戏界面中的新坐标位置,实现蛇的移动逻辑。
最后,根据教学,我运用if 条件判断语句,在边界检测中,判断蛇头坐标是否超出游戏窗口边界,若超出则将游戏状态标记为结束(game_over = True );在自身碰撞检测中,判断新蛇头位置是否在蛇身(除蛇头外部分,通过切片 snake[1:] 表示 )中,若在则将游戏状态标记为结束,以此实现游戏结束条件的检测。

pygame.draw.rect(screen, RED, (food_position[0], food_position[1], CELL_SIZE, CELL_SIZE)) 函数调用
最后一部分同样,我先调用 Pygame 库中的绘图函数pygame.draw.rect ,在游戏窗口指定位置,以指定大小绘制红色矩形来表示食物,完成食物的可视化呈现。
再调用自定义函数show_score ,执行show_score函数内的代码逻辑,在游戏界面上渲染并显示当前分数,让玩家能够看到游戏得分情况。
最后使用if语句进行条件判断,当游戏结束(game_over为True )时,调用show_game_over()函数,在游戏界面上显示游戏结束相关信息,如提示重新开始或退出的文字、最终分数等。
4、实验成果展示

通过上下左右键可以实现对蛇行动方向的改变,若蛇碰到边缘或自己游戏便终止,总体结果理想。
视频链接:https://www.bilibili.com/video/BV1sm7SzLESK?t=15.6
程序源代码如下:

import pygame
import random

# 初始化游戏
pygame.init()

# 游戏窗口设置
WIDTH, HEIGHT = 640, 480
CELL_SIZE = 20
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("贪吃蛇游戏")

# 颜色定义
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GREEN = (0, 255, 0)  # 蛇身颜色
RED = (255, 0, 0)  # 食物颜色
BLUE = (0, 0, 255)  # 边框颜色
GRAY = (100, 100, 100)  # 背景网格

# 确保中文显示正常
font = pygame.font.SysFont(["SimHei", "WenQuanYi Micro Hei", "Heiti TC"], 30)

# 游戏变量初始化
snake = [(100, 100), (80, 100), (60, 100)]  # 蛇的初始位置
snake_direction = "RIGHT"
change_to = snake_direction
food_position = (300, 200)
food_spawned = True
score = 0
game_over = False
clock = pygame.time.Clock()


def generate_food():
    """随机生成食物位置,确保不与蛇身重叠"""
    while True:
        x = random.randint(1, (WIDTH - CELL_SIZE) // CELL_SIZE) * CELL_SIZE
        y = random.randint(1, (HEIGHT - CELL_SIZE) // CELL_SIZE) * CELL_SIZE
        food_pos = (x, y)

        # 检查食物是否生成在蛇身上
        if food_pos not in snake:
            return food_pos


def show_score():
    """显示当前分数"""
    score_text = font.render(f"分数: {score}", True, WHITE)
    screen.blit(score_text, (10, 10))


def show_game_over():
    """显示游戏结束画面"""
    over_text = font.render("游戏结束!按 R 重新开始,按 Q 退出", True, RED)
    final_score_text = font.render(f"最终分数: {score}", True, WHITE)
    screen.blit(over_text, (WIDTH // 4, HEIGHT // 2 - 30))
    screen.blit(final_score_text, (WIDTH // 2 - 50, HEIGHT // 2 + 30))


def draw_grid():
    """绘制背景网格(可选美化)"""
    for x in range(0, WIDTH, CELL_SIZE):
        pygame.draw.line(screen, GRAY, (x, 0), (x, HEIGHT))
    for y in range(0, HEIGHT, CELL_SIZE):
        pygame.draw.line(screen, GRAY, (0, y), (WIDTH, y))


# 游戏主循环
while True:
    # 事件处理
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            quit()
        elif event.type == pygame.KEYDOWN:
            # 方向控制
            if event.key == pygame.K_UP and snake_direction != "DOWN":
                change_to = "UP"
            if event.key == pygame.K_DOWN and snake_direction != "UP":
                change_to = "DOWN"
            if event.key == pygame.K_LEFT and snake_direction != "RIGHT":
                change_to = "LEFT"
            if event.key == pygame.K_RIGHT and snake_direction != "LEFT":
                change_to = "RIGHT"
            # 游戏结束后重新开始或退出
            if event.key == pygame.K_r and game_over:
                # 重置游戏状态
                snake = [(100, 100), (80, 100), (60, 100)]
                snake_direction = "RIGHT"
                change_to = snake_direction
                score = 0
                game_over = False
                food_position = generate_food()
                food_spawned = True
            if event.key == pygame.K_q and game_over:
                pygame.quit()
                quit()

    # 更新蛇的方向
    snake_direction = change_to

    if not game_over:
        # 计算新的蛇头位置
        head_x, head_y = snake[0]
        if snake_direction == "UP":
            head_y -= CELL_SIZE
        elif snake_direction == "DOWN":
            head_y += CELL_SIZE
        elif snake_direction == "LEFT":
            head_x -= CELL_SIZE
        elif snake_direction == "RIGHT":
            head_x += CELL_SIZE

        # 边界检测
        if (head_x < 0 or head_x >= WIDTH or
                head_y < 0 or head_y >= HEIGHT):
            game_over = True

        # 自身碰撞检测
        new_head = (head_x, head_y)
        if new_head in snake[1:]:  # 检查是否撞到自己
            game_over = True

        # 更新蛇的位置
        snake.insert(0, new_head)

        # 检测是否吃到食物
        if new_head == food_position:
            score += 10
            food_spawned = False
        else:
            snake.pop()  # 如果没吃到食物,移除尾部

        # 生成新食物
        if not food_spawned:
            food_position = generate_food()
            food_spawned = True

    # 绘制游戏界面
    screen.fill(BLACK)
    draw_grid()  # 绘制背景网格

    # 绘制蛇
    for i, segment in enumerate(snake):
        # 蛇头用不同颜色
        if i == 0:
            pygame.draw.rect(screen, BLUE, (segment[0], segment[1], CELL_SIZE, CELL_SIZE))
        else:
            pygame.draw.rect(screen, GREEN, (segment[0], segment[1], CELL_SIZE, CELL_SIZE))
        # 绘制边框
        pygame.draw.rect(screen, WHITE, (segment[0], segment[1], CELL_SIZE, CELL_SIZE), 1)

    # 绘制食物
    pygame.draw.rect(screen, RED, (food_position[0], food_position[1], CELL_SIZE, CELL_SIZE))

    # 显示分数
    show_score()

    # 游戏结束画面
    if game_over:
        show_game_over()

    pygame.display.update()
    clock.tick(10)  # 控制游戏速度(帧率)

5、实验中遇到的问题和解决过程
问题一:代码太复杂,我不会写
解决方案一:通过看书本和b站的教学视频以及询问ai最终学会了
问题二:运行不成功
解决方案二:没有安装pygame,最后询问同学成功安装pygame,运行成功
其他(感悟、思考等)
(1)实验总结
本次 Python 实验课给予我们自由编写程序的机会,起初我满心迷茫,不知从何下手。在浏览了众多B站教学视频及参考学长学姐的经验分享后,结合自己对休闲游戏的喜爱,我决定挑战编写贪吃蛇游戏。
从构思蛇的移动逻辑、食物的随机生成,到实现碰撞检测与计分系统,每一项任务都如同关卡,考验着我对 Python 知识的掌握与运用能力。实验途中,我遭遇了形形色色的难题,从一开始无从下手,到实验过程中遇到的像是在处理蛇的身体增长时,如何精准更新蛇身位置与列表数据,还有在优化游戏帧率,确保蛇移动流畅等问题都令我十分苦恼。当然,结合视频教学和课上所学知识以及询问ai大数据每个代码的意思我最终较为顺利地编写成功。最终呈现出的贪吃蛇游戏虽不完美,却饱含我的心血,令我深感欣慰哈哈哈哈哈。
在这不断探索、解决问题的过程中,我不仅提升了编程能力,更养成了独立思考和坚韧不拔的精神。如今,我对Python的语法规则、数据结构运用更为娴熟,也明白了编程不仅是代码堆砌,更是逻辑思维与创造力的结晶。虽然python课是短暂的,但一学期的python课教给我的道理确实终身的~
(2)课程总结
在Python课程的学习之旅中,我收获颇丰。从最初懵懂了解变量、数据类型,到熟练运用函数、循环、条件语句搭建复杂程序架构,每一节课都有所收获,有所进步。
起初,作为编程小白,面对复杂代码逻辑常感力不从心,课堂上老师的提问我一个也不会。但通过老师耐心细致的讲解,从原理剖析到实例演示,逐步为我拨开迷雾。每堂课的知识点梳理与课后实验作业的巩固练习,助力我不断夯实基础,取得进步。如今,我已能完成贪吃蛇游戏这类小型项目,让我领略到Python在游戏开发领域的魅力。
Python 的学习重塑了我的思维与习惯。它赋予我严谨的逻辑思维,让我学会从问题本质出发,拆解任务、分析流程,以高效算法解决问题。同时,也磨炼了我的耐心与专注力,编写代码时一个小错误都可能导致程序出错,如一开始的格式问题、符号全角半角问题等,这些都促使我更加细心严谨,反复检查、调试代码,确保最后可以成功运行。面对难题时,我不再轻易退缩,而是积极尝试不同方法,在挫折中积累经验,培养出越挫越勇的精神。
最后,经过大一上计算机基础和大一下python课的学习,让我意识到,作为文科生想要适应科学技术飞速发展的今天,我们必须在学好文科课程的基础上兼修类似计算机基础和python的技术性课程,这样才能更有利于我们适应时代发展,在将来的工作和生活中越走越远。
最最后,老师在最后一节课送给大家的话令我十分感动:脚踏实地时,抬头看路!(送给迷茫的你)!刚步入大学,面对陌生的城市、课程、学习方式,我感到十分迷茫与无措,学生工作与学习兼顾让我十分疲惫,但或许每个人都会有这样迷茫的时候,当身处这样的迷茫与焦虑中,我们便更应该放缓脚步,仔细思考未来的方向与道路,让一切努力都变得有意义有价值。我相信,只要把握好脚踏实地与抬头看路这两者的平衡,终能在这看似迷茫的旅程中,找到属于自己的清晰路径,收获成长与进步!
(3)意见和建议
学习Python过程中,前期基础知识的讲解循序渐进,让我能轻松跟上节奏,逐步建立起编程思维。但随着课程推进,涉及如服务端客户端监听等内容时,我便没有那么得心应手。老师可以在后续讲解此类复杂知识点时,能适当放慢节奏,多引入生活实例或趣味案例,帮助我们理解。同时,可以向大家提供一些优质的网络教学视频,让在课上没有完全明白的同学自行查缺补漏。
最后最后最后,老师讲的特别好,谢谢特别特别幽默特别特别包容特别特别认真的王老师!我永远是blackwall老师的粉丝哈哈哈哈哈~
参考资料
《python程序设计》、b站、小红书

posted @ 2025-06-02 22:54  skkaa  阅读(38)  评论(0)    收藏  举报