一、本篇摘要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开始数。模块 2AI 图案主题包——字典分类管理# 【Scratch积木】新建字典 [themes]键是主题名值是图案列表themes{动物:[,,,,,,,],水果:[,,,,,,,],交通:[,,,,,,,✈️],emoji:[,,,,,,,⭐],}# 【Scratch积木】询问 选择主题 并等待从字典中取出对应列表theme_nameinput(选择主题动物/水果/交通/emoji)iconsthemes.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 11importcsv,os RANK_FILEmemory_rank.csv# 【Scratch积木】读取排行榜文件到列表defload_rank():ifnotos.path.exists(RANK_FILE):return[]withopen(RANK_FILE,r,encodingutf-8)asf:readercsv.reader(f)next(reader,None)returnlist(reader)# 【Scratch积木】追加一条成绩defsave_rank(name,flips,theme):existsos.path.exists(RANK_FILE)withopen(RANK_FILE,a,encodingutf-8,newline)asf:writercsv.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_FILEmemory_rank.csv# 【Scratch积木】定义积木 build_board(theme) → 返回 4×4 洗牌后的二维列表defbuild_board(theme):iconsTHEMES[theme][:]cardsiconsicons# 每个图案配一对random.shuffle(cards)return[cards[i*4:(i1)*4]foriinrange(4)]# 【Scratch积木】定义积木 print_board(board, revealed)defprint_board(board,revealed):print(\n 0 1 2 3)forrinrange(4):row_strf{r}forcinrange(4):row_strf[{board[r][c]ifrevealed[r][c]else❓}] print(row_str)# 【Scratch积木】定义积木 ask_coord(prompt) → 返回 (row, col)defask_coord(prompt):whileTrue:rawinput(prompt).strip().split()iflen(raw)2andall(x.isdigit()forxinraw):r,cint(raw[0]),int(raw[1])if0r4and0c4:returnr,cprint(⚠️ 请输入两个 0-3 的数字用空格分隔例如1 2)# 【Scratch积木】定义积木 save_rank(name, flips, theme)defsave_rank(name,flips,theme):existsos.path.exists(RANK_FILE)withopen(RANK_FILE,a,encodingutf-8,newline)asf:writercsv.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,encodingutf-8)asf:readercsv.reader(f)next(reader,None)rows[rowforrowinreader]# 【Scratch积木】按翻牌次数升序排序次数越少越靠前rows.sort(keylambdax: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()))themeinput(选择图案主题).strip()ifthemenotinTHEMES:theme动物print(默认使用「动物」主题)boardbuild_board(theme)revealed[[False]*4for_inrange(4)]flips0pairs_found0whilepairs_found8:print_board(board,revealed)print(f 已配对{pairs_found}/8 | 翻牌{flips}次)r1,c1ask_coord(翻开第 1 张行 列)ifrevealed[r1][c1]:print(⚠️ 这张卡已经配对啦换一张)continuer2,c2ask_coord(翻开第 2 张行 列)if(r2,c2)(r1,c1)orrevealed[r2][c2]:print(⚠️ 两张卡不能相同或已配对)continue# 【Scratch积木】临时翻开两张卡展示给玩家看print(f翻开[{board[r1][c1]}] 和 [{board[r2][c2]}])flips1ifboard[r1][c1]board[r2][c2]:print( 配对成功)revealed[r1][c1]Truerevealed[r2][c2]Truepairs_found1else:print(❌ 不匹配再想想)# 全部配对print_board(board,revealed)print(f\n 恭喜通关共翻牌{flips}次)nameinput(请输入你的昵称).strip()or匿名玩家save_rank(name,flips,theme)show_rank()# 【Scratch积木】游戏总入口defmain():print(*40)print( 记忆翻牌游戏 · AI 主题包版)print(*40)whileTrue:play_one_round()againinput(\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(keylambda x: x[1])是字符串排序“10” 会排在 “2” 前面必须keylambda 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 课程欢迎订阅下方专栏持续追更。
编程启蒙|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开始数。模块 2AI 图案主题包——字典分类管理# 【Scratch积木】新建字典 [themes]键是主题名值是图案列表themes{动物:[,,,,,,,],水果:[,,,,,,,],交通:[,,,,,,,✈️],emoji:[,,,,,,,⭐],}# 【Scratch积木】询问 选择主题 并等待从字典中取出对应列表theme_nameinput(选择主题动物/水果/交通/emoji)iconsthemes.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 11importcsv,os RANK_FILEmemory_rank.csv# 【Scratch积木】读取排行榜文件到列表defload_rank():ifnotos.path.exists(RANK_FILE):return[]withopen(RANK_FILE,r,encodingutf-8)asf:readercsv.reader(f)next(reader,None)returnlist(reader)# 【Scratch积木】追加一条成绩defsave_rank(name,flips,theme):existsos.path.exists(RANK_FILE)withopen(RANK_FILE,a,encodingutf-8,newline)asf:writercsv.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_FILEmemory_rank.csv# 【Scratch积木】定义积木 build_board(theme) → 返回 4×4 洗牌后的二维列表defbuild_board(theme):iconsTHEMES[theme][:]cardsiconsicons# 每个图案配一对random.shuffle(cards)return[cards[i*4:(i1)*4]foriinrange(4)]# 【Scratch积木】定义积木 print_board(board, revealed)defprint_board(board,revealed):print(\n 0 1 2 3)forrinrange(4):row_strf{r}forcinrange(4):row_strf[{board[r][c]ifrevealed[r][c]else❓}] print(row_str)# 【Scratch积木】定义积木 ask_coord(prompt) → 返回 (row, col)defask_coord(prompt):whileTrue:rawinput(prompt).strip().split()iflen(raw)2andall(x.isdigit()forxinraw):r,cint(raw[0]),int(raw[1])if0r4and0c4:returnr,cprint(⚠️ 请输入两个 0-3 的数字用空格分隔例如1 2)# 【Scratch积木】定义积木 save_rank(name, flips, theme)defsave_rank(name,flips,theme):existsos.path.exists(RANK_FILE)withopen(RANK_FILE,a,encodingutf-8,newline)asf:writercsv.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,encodingutf-8)asf:readercsv.reader(f)next(reader,None)rows[rowforrowinreader]# 【Scratch积木】按翻牌次数升序排序次数越少越靠前rows.sort(keylambdax: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()))themeinput(选择图案主题).strip()ifthemenotinTHEMES:theme动物print(默认使用「动物」主题)boardbuild_board(theme)revealed[[False]*4for_inrange(4)]flips0pairs_found0whilepairs_found8:print_board(board,revealed)print(f 已配对{pairs_found}/8 | 翻牌{flips}次)r1,c1ask_coord(翻开第 1 张行 列)ifrevealed[r1][c1]:print(⚠️ 这张卡已经配对啦换一张)continuer2,c2ask_coord(翻开第 2 张行 列)if(r2,c2)(r1,c1)orrevealed[r2][c2]:print(⚠️ 两张卡不能相同或已配对)continue# 【Scratch积木】临时翻开两张卡展示给玩家看print(f翻开[{board[r1][c1]}] 和 [{board[r2][c2]}])flips1ifboard[r1][c1]board[r2][c2]:print( 配对成功)revealed[r1][c1]Truerevealed[r2][c2]Truepairs_found1else:print(❌ 不匹配再想想)# 全部配对print_board(board,revealed)print(f\n 恭喜通关共翻牌{flips}次)nameinput(请输入你的昵称).strip()or匿名玩家save_rank(name,flips,theme)show_rank()# 【Scratch积木】游戏总入口defmain():print(*40)print( 记忆翻牌游戏 · AI 主题包版)print(*40)whileTrue:play_one_round()againinput(\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(keylambda x: x[1])是字符串排序“10” 会排在 “2” 前面必须keylambda 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 课程欢迎订阅下方专栏持续追更。