上学期小强已经能让程序「跑起来」,这学期他要让程序「动起来」——窗口里小球弹来弹去,键盘一按方块就跑。这背后是两样新东西:算法(程序的头脑)和 Pygame(程序的舞台)。从冒泡排序的可视化开始,到亲手做出贪吃蛇,你会发现「会动的代码」比想象中更有魔力。
第一次接触真正的算法与游戏引擎,从冒泡排序到弹跳小球,理解「程序是如何动起来的」。
用故事和生活类比打开这学期的大门,先「知其所以然」再学语法。
上学期小强已经能让程序「跑起来」,这学期他要让程序「动起来」——窗口里小球弹来弹去,键盘一按方块就跑。这背后是两样新东西:算法(程序的头脑)和 Pygame(程序的舞台)。从冒泡排序的可视化开始,到亲手做出贪吃蛇,你会发现「会动的代码」比想象中更有魔力。
大的数像大气泡先浮上去,一轮一轮交换位置,直到整队排好。
相邻比较交换从中间劈开,每次排除一半,1000 个数据只需 10 步。
折半缩小范围一秒画 60 张静态图,眼睛就觉得它「活」了。
视觉暂留每跳一下就问一次:玩家按了什么键?该重画哪一帧?
监听-响应算法基础与Pygame入门 —— 共 12 课时,全部知识点一网打尽。
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]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))4import 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 的深蓝色游戏窗口,
点关闭按钮正常退出,控制台无报错)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()(白色画布上出现一张黄色圆脸:
两颗黑眼睛 + 一条上扬的微笑弧线)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 帧,肉眼看就是连续动画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))(方块随方向键平滑移动,且不会出界)# 核心逻辑:监听 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)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」)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("音乐:循环播放(背景氛围)")音效:短促触发(跳跃/得分)
音乐:循环播放(背景氛围)
(游戏瞬间有了灵魂)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 结束,三态切换)# 关卡 = 数据,引擎 = 代码:换关只需改数据
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关# 贪吃蛇 = 移动 + 吃食物 + 撞墙判定
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每个知识点都要落到能跑、能玩、能演示的作品上。
期末项目是整学期知识点的综合检验场:综合运用。学生将独立完成需求拆解 → 功能实现 → 调试打磨 → 上台演示的完整闭环。
| 课次 | 主题 | 趣味项目 | 知识点 |
|---|---|---|---|
| 1 | 算法是什么 | 冒泡排序可视化 | 排序算法 |
| 2 | 查找算法 | 猜数字最优策略 | 二分查找 |
| 3 | Pygame初体验 | 弹出一个窗口 | Pygame基础 |
| 4 | 图形绘制 | 画一个笑脸 | 绘图函数 |
| 5 | 动画效果 | 弹跳的小球 | 帧动画、碰撞检测 |
| 6 | 键盘控制 | 移动的小方块 | 事件处理 |
| 7 | 鼠标交互 | 点击变色的按钮 | 鼠标事件 |
| 8 | 文字与图片 | 带图片的游戏界面 | 文字渲染、图片加载 |
| 9 | 声音效果 | 播放背景音乐 | 音效播放 |
| 10 | 游戏状态 | 开始/暂停/结束界面 | 状态机思想 |
| 11 | 关卡设计 | 多关卡游戏 | 关卡数据结构 |
| 12 | 期末项目 | 贪吃蛇游戏 | 综合运用 |
把一学期的知识点串成体系,看清来路与去向。
◀ 上一章:一年级 下学期 · 数据集合与函数封装
下一章 ▶:二年级 下学期 · 完整游戏开发与数据处理
第一次接触真正的算法与游戏引擎,从冒泡排序到弹跳小球,理解「程序是如何动起来的」。
结业时你将带走:3 个可玩游戏作品 + 一套算法思维 + NOAI 初赛参赛能力。
避开高频易错点,再用速查表把语法焊进肌肉记忆。
# 程序结束
sys.exit()pygame.quit()
sys.exit()while True:
小球移动() # 快到看不清clock = pygame.time.Clock()
while True:
clock.tick(60)
小球移动()while True:
画图() # 窗口无响应for e in pygame.event.get():
if e.type == pygame.QUIT:
exit()
画图()rect.x = 900 # 窗口宽只有800rect.x = min(780, rect.x)| 功能 | 写法 | 一句话理解 |
|---|---|---|
| 初始化 | 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 组。