编程启蒙|Scratch 转 Python 系列第 12 天:记忆翻牌游戏实战(AI 图案主题包 + 存档排行榜)
一、本篇摘要
Day 11 我们学会了让 Python “记住昨天”——把数据存进文件。今天就用这个能力做一款经典的记忆翻牌游戏——关掉游戏,最高纪录依然在。
本篇是串联复习大合集:Day 6 列表画卡牌矩阵、Day 9 字典管 AI 图案主题包、Day 11 文件存排行榜。学完这一篇,孩子第一次感受到"多个知识点合作做一个真项目"的乐趣。
二、本节课学习目标
- 用二维列表表示卡牌矩阵,理解"游戏地图"的编程本质。
- 用字典管理 AI 生成的多套图案主题包(动物/水果/交通工具/
emoji),可自由切换。 - 用文件读写实现排行榜持久化,理解"游戏存档"的最小可行方案。
- 掌握
random.shuffle()洗牌技巧,理解"程序随机性"是所有小游戏的灵魂。
三、专业名词通俗释义
| 专业名词 | 通俗解释 |
|---|---|
| 二维列表 | 列表里套列表,用来表示"行 × 列"的表格/地图 |
| 洗牌 | 打乱列表顺序的操作,Python 用random.shuffle(list) |
| 翻牌状态 | 每张卡有三种状态:未翻 / 已翻开 / 已配对 |
| 主题包 | 一组同类图案的集合,用字典{主题名: [图案列表]}组织 |
| 排行榜 | 记录玩家最好成绩的表格文件(CSV) |
四、分模块双向对照
模块 1:卡牌矩阵——用二维列表画游戏地图
# 【Scratch积木】新建列表 [board],用一个大列表装 4 个小列表# 【Scratch积木】每个小列表代表一行 4 张卡board=[["🐶","🐱","🐰","🐼"],["🐶","🐱","🐰","🐼"],["🦁","🐸","🐵","🐷"],["🦁","🐸","🐵","🐷"],]# 访问某一张卡:board[行][列]print(board[0][2])# 🐰核心易错说明:二维列表访问必须双方括号board[row][col];row和col都从0开始数。
模块 2:AI 图案主题包——字典分类管理
# 【Scratch积木】新建字典 [themes],键是主题名,值是图案列表themes={"动物":["🐶","🐱","🐰","🐼","🦁","🐸","🐵","🐷"],"水果":["🍎","🍌","🍇","🍉","🍓","🍑","🍒","🥝"],"交通":["🚗","🚕","🚙","🚌","🚑","🚒","🚚","✈️"],"emoji":["😀","😎","🥳","🤖","👻","🎃","🎁","⭐"],}# 【Scratch积木】询问 "选择主题" 并等待,从字典中取出对应列表theme_name=input("选择主题(动物/水果/交通/emoji):")icons=themes.get(theme_name,themes["动物"])核心易错说明:.get(key, default)比dict[key]安全——键不存在时返回默认值而不是报错。
模块 3:洗牌——random.shuffle 实战![]()
importrandom# 【Scratch积木】将列表 [cards] 打乱顺序cards=["🐶","🐶","🐱","🐱","🐰","🐰","🐼","🐼"]random.shuffle(cards)# 原地打乱,不返回新列表print(cards)# 每次运行结果都不同核心易错说明:random.shuffle()是原地修改,不像sorted()返回新列表;x = random.shuffle(cards)得到的是None,是新手大坑。
模块 4:翻牌与配对逻辑
# 【Scratch积木】定义积木 flip(row, col) → 翻开某张卡# 【Scratch积木】如果 两张卡相同 → 保持翻开,否则盖回defflip_and_check(board,revealed,r1,c1,r2,c2):ifboard[r1][c1]==board[r2][c2]:revealed[r1][c1]=Truerevealed[r2][c2]=TruereturnTrue# 配对成功returnFalse# 配对失败模块 5:排行榜持久化——CSV 读写(复习 Day 11)
importcsv,os RANK_FILE="memory_rank.csv"# 【Scratch积木】读取排行榜文件到列表defload_rank():ifnotos.path.exists(RANK_FILE):return[]withopen(RANK_FILE,"r",encoding="utf-8")asf:reader=csv.reader(f)next(reader,None)returnlist(reader)# 【Scratch积木】追加一条成绩defsave_rank(name,flips,theme):exists=os.path.exists(RANK_FILE)withopen(RANK_FILE,"a",encoding="utf-8",newline="")asf:writer=csv.writer(f)ifnotexists:writer.writerow(["玩家","翻牌次数","主题"])writer.writerow([name,flips,theme])五、综合实战项目:4×4 记忆翻牌完整游戏
游戏规则:4×4 共 16 张卡(8 对图案),每回合输入两张卡坐标翻开。相同保持翻开,不同盖回。全部配对后记录翻牌次数入排行榜。
Scratch 积木流程:
- 选择主题 → 从字典取图案 →
random.shuffle洗牌 - 展开成 4×4 二维列表
board - 建立同尺寸的
revealed状态矩阵(全 False) - 重复执行直到 全部配对:
- 打印当前牌面(配对的显示图案,未配对显示❓)
- 询问两张卡坐标 → 翻开对比 → 更新 revealed
- 翻牌次数 +1
- 记录成绩 → 显示排行榜
Python 完整可运行源码:
importrandomimportcsvimportos THEMES={"动物":["🐶","🐱","🐰","🐼","🦁","🐸","🐵","🐷"],"水果":["🍎","🍌","🍇","🍉","🍓","🍑","🍒","🥝"],"交通":["🚗","🚕","🚙","🚌","🚑","🚒","🚚","✈️"],"emoji":["😀","😎","🥳","🤖","👻","🎃","🎁","⭐"],}RANK_FILE="memory_rank.csv"# 【Scratch积木】定义积木 build_board(theme) → 返回 4×4 洗牌后的二维列表defbuild_board(theme):icons=THEMES[theme][:]cards=icons+icons# 每个图案配一对random.shuffle(cards)return[cards[i*4:(i+1)*4]foriinrange(4)]# 【Scratch积木】定义积木 print_board(board, revealed)defprint_board(board,revealed):print("\n 0 1 2 3")forrinrange(4):row_str=f"{r}"forcinrange(4):row_str+=f"[{board[r][c]ifrevealed[r][c]else'❓'}] "print(row_str)# 【Scratch积木】定义积木 ask_coord(prompt) → 返回 (row, col)defask_coord(prompt):whileTrue:raw=input(prompt).strip().split()iflen(raw)==2andall(x.isdigit()forxinraw):r,c=int(raw[0]),int(raw[1])if0<=r<4and0<=c<4:returnr,cprint("⚠️ 请输入两个 0-3 的数字,用空格分隔,例如:1 2")# 【Scratch积木】定义积木 save_rank(name, flips, theme)defsave_rank(name,flips,theme):exists=os.path.exists(RANK_FILE)withopen(RANK_FILE,"a",encoding="utf-8",newline="")asf:writer=csv.writer(f)ifnotexists:writer.writerow(["玩家","翻牌次数","主题"])writer.writerow([name,flips,theme])# 【Scratch积木】定义积木 show_rank()defshow_rank():ifnotos.path.exists(RANK_FILE):print("📭 暂无排行榜")returnwithopen(RANK_FILE,"r",encoding="utf-8")asf:reader=csv.reader(f)next(reader,None)rows=[rowforrowinreader]# 【Scratch积木】按翻牌次数升序排序(次数越少越靠前)rows.sort(key=lambdax:int(x[1]))print("\n"+"="*30)print(" 🏆 记忆翻牌排行榜")print("="*30)fori,(name,flips,theme)inenumerate(rows[:10],1):print(f"{i}.{name}{flips}次 [{theme}]")print("="*30)# 【Scratch积木】主循环:一局游戏defplay_one_round():print("\n可选主题:","、".join(THEMES.keys()))theme=input("选择图案主题:").strip()ifthemenotinTHEMES:theme="动物"print("默认使用「动物」主题")board=build_board(theme)revealed=[[False]*4for_inrange(4)]flips=0pairs_found=0whilepairs_found<8:print_board(board,revealed)print(f"🎯 已配对{pairs_found}/8 | 翻牌{flips}次")r1,c1=ask_coord("翻开第 1 张(行 列):")ifrevealed[r1][c1]:print("⚠️ 这张卡已经配对啦,换一张")continuer2,c2=ask_coord("翻开第 2 张(行 列):")if(r2,c2)==(r1,c1)orrevealed[r2][c2]:print("⚠️ 两张卡不能相同或已配对")continue# 【Scratch积木】临时翻开两张卡展示给玩家看print(f"翻开:[{board[r1][c1]}] 和 [{board[r2][c2]}]")flips+=1ifboard[r1][c1]==board[r2][c2]:print("🎉 配对成功!")revealed[r1][c1]=Truerevealed[r2][c2]=Truepairs_found+=1else:print("❌ 不匹配,再想想")# 全部配对print_board(board,revealed)print(f"\n🏆 恭喜通关!共翻牌{flips}次")name=input("请输入你的昵称:").strip()or"匿名玩家"save_rank(name,flips,theme)show_rank()# 【Scratch积木】游戏总入口defmain():print("="*40)print(" 🎴 记忆翻牌游戏 · AI 主题包版")print("="*40)whileTrue:play_one_round()again=input("\n再来一局?(y/n):")ifagain.lower()!="y":print("👋 下次见!")breakif__name__=="__main__":main()运行方式:保存为day12_code.py→ 命令行python day12_code.py→ 按提示输入两张卡的行列坐标。
💡 三大数据结构会师:卡牌矩阵是二维列表、主题包是字典、排行榜是文件——一款翻牌游戏把 Day 6/9/11 三个知识点全部串起来。这就是"综合项目"的味道——不再是学一个用一个,而是几个知识点合作解决一个真问题。
六、高频易错点总结
1. 二维列表初始化陷阱
# ❌ 错误:所有行共享同一个引用board=[[False]*4]*4board[0][0]=True# 结果所有行第 0 列都变 True# ✅ 正确:每行独立创建board=[[False]*4for_inrange(4)]2.random.shuffle返回值是None
新手常写cards = random.shuffle(cards),然后cards变成None——shuffle原地修改,不返回。
3. 字典取值用.get()更安全
themes[key]键不存在直接崩溃;themes.get(key, default)优雅兜底。
4. CSV 排序前要转数字
rows.sort(key=lambda x: x[1])是字符串排序,“10” 会排在 “2” 前面;必须key=lambda x: int(x[1])。
八、💡 学习提示
为鼓励大家动手练习、吃透编程逻辑,本篇不提供 Scratch 成品源码,请对照截图亲手搭建积木完成复刻!
配套 Python 代码可直接复制运行学习。
九、往期历史笔记
编程启蒙|Scratch 转 Python 系列第 1 天:变量、数字运算积木双向对照(AI 基础数值计算实战)
编程启蒙|Scratch 转 Python 系列第 2 天:分支判断 if 积木双向对照(AI 指令条件过滤实战)
编程启蒙|Scratch 转 Python 系列第 3 天:循环重复积木双向对照(AI 批量循环处理,已收录 AI Agent 技术社区)
编程启蒙|Scratch 转 Python 系列第 4 天:字符串文本积木双向对照(AI 提示词拼接、文本清洗实战)
编程启蒙|Scratch 转 Python 系列第 5 天:自定义积木 / 函数双向对照(AI 工具封装、重复指令简化实战)
编程启蒙|Scratch 转 Python 系列第 6 天:列表、数组积木双向对照(AI 底层语法 / AI 批量数据处理实战)
编程启蒙|Scratch 转 Python 系列第 7 天:猜数字大挑战·升级版实战(AI 出题 + 二分查找最优解 + 完整命令行游戏)
编程启蒙|Scratch 转 Python 系列第8天:节奏敲击机游戏实战(AI节奏谱生成实战)
编程启蒙|Scratch 转 Python 系列第9天:字典/哈希表积木双向对照(AI大模型参数配置表实战)
编程启蒙|Scratch 转 Python 系列第 10 天:问答闯关游戏实战(AI 题库管理 + 多关卡剧本)
编程启蒙|Scratch 转 Python 系列第 11 天:文件读写积木双向对照(AI 训练数据存取实战)
十、下一章预告
Scratch 转 Python 系列第 13 天:异常处理 try/except 积木双向对照(AI 接口调用容错实战)
当程序遇到"不听话"的输入或网络出错,如何优雅兜底?——try/except会告诉你答案,这也是所有 AI API 调用的必备技能。
十一、原创声明
本文为「梅雅达编程笔记」原创启蒙教程,禁止私自搬运、二次转载,转发请标注来源。
想要系统学完整套 Scratch 转 Python 课程,欢迎订阅下方专栏持续追更。