第 03 章 · 二年级(小学四年级) 上学期

算法基础与Pygame入门

第一次接触真正的算法与游戏引擎,从冒泡排序到弹跳小球,理解「程序是如何动起来的」。

12 课时 14 个知识点 4 大易错点 3 档分层作业
一年级上一年级下二年级上二年级下三年级上三年级下四年级上四年级下五年级上五年级下六年级上六年级下七年级上七年级下
01

情景导航

用故事和生活类比打开这学期的大门,先「知其所以然」再学语法。

上学期小强已经能让程序「跑起来」,这学期他要让程序「动起来」——窗口里小球弹来弹去,键盘一按方块就跑。这背后是两样新东西:算法(程序的头脑)和 Pygame(程序的舞台)。从冒泡排序的可视化开始,到亲手做出贪吃蛇,你会发现「会动的代码」比想象中更有魔力。

💯生活类比:把新知识挂在旧经验上
🫧

冒泡排序 = 水里气泡

大的数像大气泡先浮上去,一轮一轮交换位置,直到整队排好。

相邻比较交换
📖

二分查找 = 翻字典

从中间劈开,每次排除一半,1000 个数据只需 10 步。

折半缩小范围
🎬

帧动画 = 翻页动画书

一秒画 60 张静态图,眼睛就觉得它「活」了。

视觉暂留
🎮

事件循环 = 游戏的心跳

每跳一下就问一次:玩家按了什么键?该重画哪一帧?

监听-响应
核 心 口 诀排序查找算法清,二分一半省时间;
窗口帧率事件环,每秒六十画一帧;
状态机管三界面,关卡数据来通关!
02

知识探究

算法基础与Pygame入门 —— 共 12 课时,全部知识点一网打尽。

🧮算法入门(2 课时)
第1课算法是什么
🎯 趣味项目:冒泡排序可视化📚 教学目标:掌握排序算法,在项目实战中巩固运用
排序算法
Python冒泡排序
def bubble_sort(lst):
    n = len(lst)
    for i in range(n - 1):              # 一共 n-1 轮
        for j in range(n - 1 - i):      # 每轮比较相邻两个
            if lst[j] > lst[j + 1]:
                lst[j], lst[j+1] = lst[j+1], lst[j]  # 交换
    return lst

print(bubble_sort([5, 3, 8, 1, 9, 2]))
运 行 结 果
[1, 2, 3, 5, 8, 9]
第2课查找算法
🎯 趣味项目:猜数字最优策略📚 教学目标:掌握二分查找,在项目实战中巩固运用
二分查找
Python二分查找
def binary_search(lst, target):
    lo, hi = 0, len(lst) - 1
    while lo <= hi:
        mid = (lo + hi) // 2       # 取中间
        if lst[mid] == target:
            return mid             # 找到了
        elif lst[mid] < target:
            lo = mid + 1           # 去右半边
        else:
            hi = mid - 1           # 去左半边
    return -1

print(binary_search([1, 3, 5, 7, 9, 11, 15], 9))
运 行 结 果
4
🎬Pygame 基础(3 课时)
第3课Pygame初体验
🎯 趣味项目:弹出一个窗口📚 教学目标:掌握Pygame基础,在项目实战中巩固运用
Pygame基础
PythonPygame 第一步:弹出游戏窗口
import pygame
pygame.init()                      # 初始化
screen = pygame.display.set_mode((400, 300))
pygame.display.set_caption("我的第一个游戏窗口")
clock = pygame.time.Clock()
running = True
while running:
    for e in pygame.event.get():
        if e.type == pygame.QUIT:  # 点右上角 × 退出
            running = False
    screen.fill((30, 30, 46))      # 每帧刷背景色
    pygame.display.flip()          # 刷新画面
    clock.tick(60)                 # 锁定 60 帧
pygame.quit()
运 行 结 果
(弹出一个 400×300 的深蓝色游戏窗口,
 点关闭按钮正常退出,控制台无报错)
第4课图形绘制
🎯 趣味项目:画一个笑脸📚 教学目标:掌握绘图函数,在项目实战中巩固运用
绘图函数
PythonPygame 图形绘制:画一个笑脸
import pygame
pygame.init()
screen = pygame.display.set_mode((300, 300))
screen.fill((255, 255, 255))
c = pygame.Color(255, 200, 40)
pygame.draw.circle(screen, c, (150, 150), 100)        # 脸
pygame.draw.circle(screen, (0, 0, 0), (115, 120), 12) # 左眼
pygame.draw.circle(screen, (0, 0, 0), (185, 120), 12) # 右眼
pygame.draw.arc(screen, (0, 0, 0), (100, 130, 100, 80),
               3.4, 6.0, 3)                            # 微笑
pygame.display.flip()
pygame.time.wait(2000)
pygame.quit()
运 行 结 果
(白色画布上出现一张黄色圆脸:
 两颗黑眼睛 + 一条上扬的微笑弧线)
第5课动画效果
🎯 趣味项目:弹跳的小球📚 教学目标:掌握帧动画、碰撞检测,在项目实战中巩固运用
帧动画碰撞检测
Python动画的奥秘:帧 + 位移 + 反弹
import pygame
pygame.init()
screen = pygame.display.set_mode((300, 200))
x, dx = 20, 4                     # 位置 与 每帧位移
clock = pygame.time.Clock()
for _ in range(5):                # 演示前 5 帧
    x += dx
    if x > 260 or x < 20:         # 碰到边界就反弹
        dx = -dx
    print("第%2d帧后:小球 x = %d,速度 dx = %+d" % (pygame.time.get_ticks()//1000, x, dx))
    clock.tick(60)
运 行 结 果
第 0帧后:小球 x = 24,速度 dx = +4
第 0帧后:小球 x = 28,速度 dx = +4
……每秒 60 帧,肉眼看就是连续动画
🖱️交互与媒体(4 课时)
第6课键盘控制
🎯 趣味项目:移动的小方块📚 教学目标:掌握事件处理,在项目实战中巩固运用
事件处理
Python键盘控制移动方块
keys = pygame.key.get_pressed()      # 每帧取按键状态
if keys[pygame.K_LEFT]:  rect.x -= 5
if keys[pygame.K_RIGHT]: rect.x += 5
if keys[pygame.K_UP]:    rect.y -= 5
if keys[pygame.K_DOWN]:  rect.y += 5
# 边界限制,别跑出窗口
rect.x = max(0, min(600 - 50, rect.x))
运 行 结 果
(方块随方向键平滑移动,且不会出界)
第7课鼠标交互
🎯 趣味项目:点击变色的按钮📚 教学目标:掌握鼠标事件,在项目实战中巩固运用
鼠标事件
Python鼠标交互:点击变色的按钮
# 核心逻辑:监听 MOUSEBUTTONDOWN,判断点击是否落在按钮矩形里
import pygame
rect = pygame.Rect(100, 80, 100, 40)   # 按钮区域
colors = [(70, 130, 240), (240, 100, 90), (90, 200, 100)]
idx = 0
# for e in pygame.event.get():
#     if e.type == pygame.MOUSEBUTTONDOWN:
#         if rect.collidepoint(e.pos):   # 点在按钮内
#             idx = (idx + 1) % len(colors)
print("按钮初始色:", colors[idx])
idx = (idx + 1) % len(colors)           # 模拟点击一次
print("点击一次后:", colors[idx])
运 行 结 果
按钮初始色: (70, 130, 240)
点击一次后: (240, 100, 90)
第8课文字与图片
🎯 趣味项目:带图片的游戏界面📚 教学目标:掌握文字渲染、图片加载,在项目实战中巩固运用
文字渲染图片加载
Python游戏里的文字与图片
import pygame
pygame.init()
screen = pygame.display.set_mode((300, 150))
font = pygame.font.SysFont("simhei", 28)     # 加载中文字体
text = font.render("得分:100", True, (255, 255, 255))
# img = pygame.image.load("hero.png")        # 加载图片
# img = pygame.transform.scale(img, (64, 64)) # 缩放
screen.blit(text, (60, 60))                  # 贴到屏幕上
print("文字 Surface 尺寸:", text.get_size())
运 行 结 果
文字 Surface 尺寸: (120, 33)
(画面上出现白色文字「得分:100」)
第9课声音效果
🎯 趣味项目:播放背景音乐📚 教学目标:掌握音效播放,在项目实战中巩固运用
音效播放
Python让游戏有声音
import pygame
pygame.mixer.init()
# sound = pygame.mixer.Sound("jump.wav")   # 加载音效
# sound.set_volume(0.5)                    # 音量 0~1
# sound.play()                             # 播放
# pygame.mixer.music.load("bgm.mp3")       # 背景音乐
# pygame.mixer.music.play(-1)              # -1 = 无限循环
print("音效:短促触发(跳跃/得分)")
print("音乐:循环播放(背景氛围)")
运 行 结 果
音效:短促触发(跳跃/得分)
音乐:循环播放(背景氛围)
(游戏瞬间有了灵魂)
🏗️游戏架构(3 课时)
第10课游戏状态
🎯 趣味项目:开始/暂停/结束界面📚 教学目标:掌握状态机思想,在项目实战中巩固运用
状态机思想
Python游戏状态机:开始/暂停/结束
state = "menu"          # 当前游戏状态
while True:
    for e in pygame.event.get():
        if e.type == pygame.KEYDOWN:
            if state == "menu" and e.key == pygame.K_RETURN:
                state = "playing"        # 回车开始
            elif state == "playing" and e.key == pygame.K_p:
                state = "paused"         # P 暂停
    if state == "playing":
        update_game()                    # 只有玩时才更新
    draw_everything(state)               # 画面按状态画
运 行 结 果
(按回车开始 → P 键暂停 → ESC 结束,三态切换)
第11课关卡设计
🎯 趣味项目:多关卡游戏📚 教学目标:掌握关卡数据结构,在项目实战中巩固运用
关卡数据结构
Python关卡设计:用数据描述每一关
# 关卡 = 数据,引擎 = 代码:换关只需改数据
levels = [
    {"name": "第1关", "enemies": 3, "speed": 2, "bg": "sky.png"},
    {"name": "第2关", "enemies": 6, "speed": 3, "bg": "city.png"},
    {"name": "BOSS关", "enemies": 1, "speed": 5, "boss": True},
]
lv = levels[1]
print(f"进入{lv['name']}:敌人数 {lv['enemies']},速度 {lv['speed']}")
print("通关流程:", " → ".join(l["name"] for l in levels))
运 行 结 果
进入第2关:敌人数 6,速度 3
通关流程: 第1关 → 第2关 → BOSS关
🏆 期末项目期末项目
🎯 趣味项目:贪吃蛇游戏📚 教学目标:掌握综合运用,在项目实战中巩固运用
综合运用
Python期末项目:贪吃蛇核心逻辑
# 贪吃蛇 = 移动 + 吃食物 + 撞墙判定
snake = [(5, 5), (4, 5), (3, 5)]      # 蛇身(头在前)
food = (8, 5)
dir_ = (1, 0)                          # 向右爬
head = (snake[0][0] + dir_[0], snake[0][1] + dir_[1])
snake.insert(0, head)                  # 头前进一格
if head == food:                       # 吃到食物
    print("吃到食物!蛇变长,得分 +1")
else:
    snake.pop()                        # 没吃到就砍掉尾巴
print("蛇身:", snake)
print("撞墙?", not (0 <= head[0] < 20))
运 行 结 果
吃到食物!蛇变长,得分 +1
蛇身: [(6, 5), (5, 5), (4, 5), (3, 5)]
撞墙? False
03

实践应用

每个知识点都要落到能跑、能玩、能演示的作品上。

🏆 期末项目贪吃蛇游戏

期末项目是整学期知识点的综合检验场:综合运用。学生将独立完成需求拆解 → 功能实现 → 调试打磨 → 上台演示的完整闭环。

💡 验收标准:功能完整可运行、代码结构清晰、能给同学讲明白实现原理。
📊本学期课时一览表(可打印)
课次主题趣味项目知识点
1算法是什么冒泡排序可视化排序算法
2查找算法猜数字最优策略二分查找
3Pygame初体验弹出一个窗口Pygame基础
4图形绘制画一个笑脸绘图函数
5动画效果弹跳的小球帧动画、碰撞检测
6键盘控制移动的小方块事件处理
7鼠标交互点击变色的按钮鼠标事件
8文字与图片带图片的游戏界面文字渲染、图片加载
9声音效果播放背景音乐音效播放
10游戏状态开始/暂停/结束界面状态机思想
11关卡设计多关卡游戏关卡数据结构
12期末项目贪吃蛇游戏综合运用
04

总结提升

把一学期的知识点串成体系,看清来路与去向。

📌知识点体系图
🧮 算法入门
排序算法二分查找
🎬 Pygame 基础
Pygame基础绘图函数帧动画碰撞检测
🖱️ 交互与媒体
事件处理鼠标事件文字渲染图片加载音效播放
🏗️ 游戏架构
状态机思想关卡数据结构综合运用
🔄承上启下

◀ 上一章:一年级 下学期 · 数据集合与函数封装

下一章 ▶:二年级 下学期 · 完整游戏开发与数据处理

💪 学完这学期,你将获得

第一次接触真正的算法与游戏引擎,从冒泡排序到弹跳小球,理解「程序是如何动起来的」。

结业时你将带走:3 个可玩游戏作品 + 一套算法思维 + NOAI 初赛参赛能力。

05

学习检测

避开高频易错点,再用速查表把语法焊进肌肉记忆。

易错点 1

忘了 pygame.quit()

✗ 错误写法
# 程序结束
sys.exit()
✓ 正确写法
pygame.quit()
sys.exit()
💡 为什么:不调用 pygame.quit(),窗口进程可能残留,游戏关闭后再开就报错。
易错点 2

没设帧率,游戏飞快

✗ 错误写法
while True:
    小球移动()  # 快到看不清
✓ 正确写法
clock = pygame.time.Clock()
while True:
    clock.tick(60)
    小球移动()
💡 为什么:用 Clock.tick(60) 锁定每秒 60 帧,速度才稳定可控。
易错点 3

事件循环里不处理事件

✗ 错误写法
while True:
    画图()  # 窗口无响应
✓ 正确写法
for e in pygame.event.get():
    if e.type == pygame.QUIT:
        exit()
画图()
💡 为什么:不消费事件队列,系统认为程序「卡死」,窗口直接未响应。
易错点 4

坐标系搞混

✗ 错误写法
rect.x = 900  # 窗口宽只有800
✓ 正确写法
rect.x = min(780, rect.x)
💡 为什么:Pygame 的 y 轴向下为正;坐标超出窗口,图片就「跑丢」了。
📋语法速查表
功能写法一句话理解
初始化pygame.init()启动 Pygame 引擎
建窗口screen = pygame.display.set_mode((800, 600))宽800 高600 的画布
锁帧率clock.tick(60)每秒最多 60 帧
取事件for e in pygame.event.get():拿到玩家所有操作
画矩形pygame.draw.rect(screen, 蓝, (x, y, 50, 50))(x,y,宽,高)
刷新屏幕pygame.display.flip()把画好的东西显示出来
按键判断keys = pygame.key.get_pressed()keys[K_LEFT] 为真即左键按住
碰撞检测a.colliderect(b)两个矩形是否重叠
分 层 作 业

练习作业

按 A / B / C 三档难度自主选择:保底完成 A 组,学有余力挑战 B、C 组。

A组·基础任选其一深入完成
  1. 手算:对 [5, 3, 8, 1, 9] 做一轮冒泡排序,写出每步交换。
  2. 用 Pygame 画一个笑脸(圆 + 两个小圆眼睛 + 弧线嘴)。
  3. 键盘控制小方块上下左右移动,不能出窗口边界。
B组·提高任选其一深入完成
  1. 打砖块:3 行砖块 + 球拍 + 反弹球。
  2. 限时反应小游戏:随机位置出现目标,点击得分,10 秒结算。
  3. 把二分查找做成可视化:每次折半高亮剩余区间。
C组·挑战任选其一深入完成
  1. 贪吃蛇进阶:吃到食物加速 + 场上随机障碍物。
  2. 多关卡平台跳跃小游戏:设计 3 张关卡地图。
  3. 弹幕躲避游戏:密集弹幕 + 三条命 + 最高分记录。