小强发现游戏写大了就乱成一团:敌人代码复制了 20 份,改一个属性要改 20 处。学会「类」之后,他像造物主一样定义「敌人」这个物种,然后批量生产。数据三件套 NumPy / Pandas / Matplotlib,则让他第一次用图表「看见」数据背后的规律。这个学期结束,你将交出一个完整的 RPG 游戏。
用面向对象重构游戏架构,做出带粒子特效和地图的完整 RPG;同时跨入数据分析三件套。
用故事和生活类比打开这学期的大门,先「知其所以然」再学语法。
小强发现游戏写大了就乱成一团:敌人代码复制了 20 份,改一个属性要改 20 处。学会「类」之后,他像造物主一样定义「敌人」这个物种,然后批量生产。数据三件套 NumPy / Pandas / Matplotlib,则让他第一次用图表「看见」数据背后的规律。这个学期结束,你将交出一个完整的 RPG 游戏。
图纸(class)画一次,照着造出无数只猫(实例),只改图纸全体更新。
模板与实例动物有的本领猫都有,猫还能长出自己的新招(方法重写)。
代码复用一行行数据任你筛选、排序、汇总,比手翻表格快一万倍。
结构化数据一行代码把一列数字变成折线图、柱状图。
数据可视化完整游戏开发与数据处理 —— 共 12 课时,全部知识点一网打尽。
class Cat:
def __init__(self, name, color): # 造猫说明书
self.name = name # 自己的名字
self.color = color
def meow(self): # 猫的本领
print(f"{self.name}({self.color}):喵~")
mimi = Cat("咪咪", "橘色") # 造出一只真猫
mimi.meow()咪咪(橘色):喵~class Animal:
def __init__(self, name):
self.name = name
def speak(self):
print("……")
class Dog(Animal): # 狗是动物(继承)
def speak(self): # 重写:狗有自己的叫声
print(f"{self.name}:汪汪!")
class Duck(Animal):
def speak(self): # 同一方法,不同表现
print(f"{self.name}:嘎嘎!")
for a in [Dog("旺财"), Duck("唐老鸭")]:
a.speak()旺财:汪汪!
唐老鸭:嘎嘎!class Enemy(pygame.sprite.Sprite):
def __init__(self, x, y):
super().__init__() # 父类先初始化!
self.image = pygame.Surface((30, 30))
self.image.fill((248, 113, 113))
self.rect = self.image.get_rect(topleft=(x, y))
self.speed = 2
def update(self): # 每帧自动被调用
self.rect.y += self.speed
enemies = pygame.sprite.Group()
for i in range(5): # 一键生成 5 个敌人
enemies.add(Enemy(i * 60, 0))
enemies.update() # 集体移动
enemies.draw(screen) # 集体绘制(5 个红色方块整齐下落,代码只写了一份)import pygame
ball = pygame.Rect(50, 50, 10, 10) # 球
brick = pygame.Rect(40, 60, 40, 20) # 砖块
pad = pygame.Rect(30, 280, 80, 12) # 挡板
print("球撞上砖块?", ball.colliderect(brick))
print("球撞上挡板?", ball.colliderect(pad))
# 像素级碰撞:先矩形粗判,再用碰撞掩码精判
# mask1 = pygame.mask.from_surface(ball_img)
# hit = mask1.overlap(mask2, offset)球撞上砖块? True
球撞上挡板? Falseimport random
# 爆炸 = 一次性生成一批「带寿命的粒子」
particles = []
for _ in range(8):
particles.append({
"x": 150, "y": 100, # 出生点
"vx": random.randint(-5, 5), # 随机速度
"vy": random.randint(-8, -2),
"life": random.randint(20, 50), # 寿命帧数
"color": random.choice([(255,120,40), (255,220,80)]),
})
# 每帧更新:位置 += 速度,重力下坠,寿命 -1,寿命归零就删除
for p in particles[:3]:
p["x"] += p["vx"]; p["y"] += p["vy"]; p["life"] -= 1
print("粒子 (%3d,%3d) 剩余寿命 %2d" % (p["x"], p["y"], p["life"]))粒子 (149, 94) 剩余寿命 47
粒子 (152, 92) 剩余寿命 49
粒子 (146, 97) 剩余寿命 38
(几十个粒子同时飞散 = 绚丽爆炸)# 一张地图 = 一个二维列表(1=墙,0=路,2=终点)
maze = [
[1, 1, 1, 1, 1],
[1, 0, 0, 0, 1],
[1, 0, 1, 0, 1],
[1, 0, 0, 2, 1],
[1, 1, 1, 1, 1],
]
for row in maze:
print("".join("█" if c == 1 else ("◎" if c == 2 else "·") for c in row))
# 寻路:从起点 BFS 一层层探索,第一次到达终点就是最短路█████
█···█
█·█·█
█··◎█
█████import json
save = {"level": 3, "coins": 250, "pos": [10, 20]}
with open("save.json", "w", encoding="utf-8") as f:
json.dump(save, f, ensure_ascii=False) # 存档
with open("save.json", encoding="utf-8") as f:
loaded = json.load(f) # 读档
print("读到关卡:", loaded["level"])读到关卡: 3import numpy as np
a = np.array([[1, 2], [3, 4]])
b = np.array([[5, 6], [7, 8]])
print("相加:\n", a + b) # 对应位置相加
print("乘以2:\n", a * 2)
print("整体求和:", a.sum())相加:
[[ 6 8]
[10 12]]
乘以2:
[[2 4]
[6 8]]
整体求和: 10import pandas as pd
df = pd.DataFrame({
"姓名": ["小明", "小红", "小刚", "小丽"],
"数学": [92, 88, 75, 95],
"英语": [85, 94, 80, 90],
})
print("平均分:\n", df[["数学","英语"]].mean())
print("\n数学>80 的同学:\n", df[df["数学"] > 80])平均分:
数学 87.5
英语 87.25
dtype: float64
数学>80 的同学:
姓名 数学 英语
0 小明 92 85
1 小红 88 94
3 小丽 95 90import matplotlib.pyplot as plt
names = ["小明", "小红", "小刚", "小丽"]
scores = [92, 88, 75, 95]
plt.bar(names, scores, color="#04A3F0") # 柱状图
plt.title("数学成绩")
plt.ylabel("分数")
plt.show()(弹出一个窗口,显示 4 根蓝色柱子)import pandas as pd
df = pd.DataFrame({"姓名": ["小明", "小红", None, "小刚"],
"分数": [90, None, 85, 90]})
print("缺失统计:\n", df.isnull().sum(), sep="")
df = df.dropna() # ① 删除缺失行
df = df.drop_duplicates(subset="分数") # ② 去重
df["分数"] = df["分数"].astype(int) # ③ 统一类型
print("清洗后:\n", df, sep="")缺失统计:
姓名 1
分数 1
dtype: int64
清洗后:
姓名 分数
0 小明 90
2 小刚 85# RPG = 角色 + 地图 + 战斗 + 剧情 四大系统
class Hero:
def __init__(self, name):
self.name, self.hp, self.atk = name, 100, 15
def attack(self, enemy):
enemy.hp -= self.atk
print(f"{self.name} 攻击 {enemy.name},剩 {enemy.hp} 血")
hero = Hero("勇者")
slime = type("Slime", (), {"__init__": lambda s: None})()
slime.name, slime.hp = "史莱姆", 30
hero.attack(slime) # 战斗循环 → 剧情推进 → 通关勇者 攻击 史莱姆,剩 15 血
(把四个系统串起来,就是一个完整 RPG)每个知识点都要落到能跑、能玩、能演示的作品上。
期末项目是整学期知识点的综合检验场:综合运用。学生将独立完成需求拆解 → 功能实现 → 调试打磨 → 上台演示的完整闭环。
| 课次 | 主题 | 趣味项目 | 知识点 |
|---|---|---|---|
| 1 | 面向对象入门 | 定义一个「猫」类 | class、对象 |
| 2 | 继承与多态 | 动物家族 | 继承、方法重写 |
| 3 | 精灵系统 | 多个敌人同时出现 | Sprite类、Group |
| 4 | 碰撞检测进阶 | 打砖块游戏 | 矩形碰撞、像素碰撞 |
| 5 | 粒子效果 | 爆炸特效 | 粒子系统 |
| 6 | 地图与瓦片 | 迷宫探险游戏 | 瓦片地图、寻路 |
| 7 | 存档与读档 | 游戏进度保存 | JSON文件 |
| 8 | Numpy入门 | 矩阵运算小工具 | ndarray、基本运算 |
| 9 | Pandas入门 | 班级成绩分析表 | DataFrame、数据筛选 |
| 10 | Matplotlib入门 | 成绩可视化图表 | 折线图、柱状图、饼图 |
| 11 | 数据清洗 | 处理脏数据 | 缺失值、重复值处理 |
| 12 | 期末项目 | 完整的RPG小游戏 | 综合运用 |
把一学期的知识点串成体系,看清来路与去向。
◀ 上一章:二年级 上学期 · 算法基础与Pygame入门
下一章 ▶:三年级 上学期 · 算法进阶与NOAI初赛备战
用面向对象重构游戏架构,做出带粒子特效和地图的完整 RPG;同时跨入数据分析三件套。
结业时你将带走:3 个可玩游戏作品 + 一套算法思维 + NOAI 初赛参赛能力。
避开高频易错点,再用速查表把语法焊进肌肉记忆。
class Enemy(Sprite):
def __init__(self):
self.image = … # 父类没初始化class Enemy(Sprite):
def __init__(self):
super().__init__()
self.image = …cat = Cat # 少了括号cat = Cat()df[df.分数>90]["姓名"] = "x"df.loc[df.分数>90, "姓名"] = "x"plt.plot(x, y)
# 什么都没出现plt.plot(x, y)
plt.show()| 功能 | 写法 | 一句话理解 |
|---|---|---|
| 定义类 | class Cat: | 开始画猫的图纸 |
| 初始化 | def __init__(self, name): | 造猫时自动执行的准备动作 |
| 继承 | class Dog(Animal): | 动物会的狗都会 |
| 调父类 | super().__init__() | 先执行父类的准备动作 |
| 精灵组 | enemies = pygame.sprite.Group() | 批量管理/更新/绘制敌人 |
| NumPy 数组 | a = np.array([[1, 2], [3, 4]]) | 矩阵运算一步到位 |
| 筛选数据 | df[df.成绩 > 90] | 一行筛出所有高分行 |
| 画柱状图 | df.plot(kind='bar') | 数据直接变图表 |
按 A / B / C 三档难度自主选择:保底完成 A 组,学有余力挑战 B、C 组。