- 示例工程
【免费下载链接】basic-computer-games
An updated version of the classic "Basic Computer Games" book, with well-written examples in a variety of common MEMORY SAFE, SCRIPTING programming languages. See https://coding-horror.github.io/basic-computer-games/
导读
本文以00_Alternate_Languages目录中 Bombardment 的 MiniScript 移植版为讲解主体,带你掌握如何用命令行版 MiniScript与Mini Micro 图形化环境两种方式运行这个来自 1978 年《Basic Computer Games》的经典海战游戏,并从源码结构出发剖析bombardment.ms的实现思路、随机布阵、输入解析与胜负判定逻辑,最后对比原始 BASIC 与 Python、JavaScript 等主流移植版,指出其中仍保留的经典缺陷。读完本文,你将能独立下载、安装并运行该 MiniScript 程序,也能理解这份移植代码与仓库中其他语言版本之间的关系。
一、Bombardment 是什么:一场 5×5 网格上的导弹对决
Bombardment 是《Basic Computer Games》(1978) 中的经典文字游戏,在仓库 11_Bombardment/README.md 中有完整规则说明:
- 双方各持有一张编号 1~25 的 5×5 阵地网格(outpost,共 25 个据点);
- 你和电脑各自拥有4 个排(platoon),秘密地放在自己网格的任意 4 个不同据点上;
- 游戏开始后双方轮流发射导弹轰炸对方网格,猜中对方排所在的据点即为命中;
- 先摧毁对方全部 4 个排的一方获胜。
原始程序由新泽西州帕林(Parlin)的 Martin Burdash 编写,本仓库版本在其基础上略有修改(见 11_Bombardment/README.md)。由于游戏逻辑简单、输入输出纯粹基于文本,它非常适合被移植到各种语言;MiniScript 正是其中位于00_Alternate_Languages下的一个"附加语言"移植版。
二、MiniScript 移植版概况
MiniScript 移植版的全部内容位于00_Alternate_Languages/11_Bombardment/MiniScript/目录,仅包含两个文件:
| 文件 | 作用 |
|---|---|
bombardment.ms | MiniScript 语言实现的完整游戏程序 |
README.md | 运行说明(即本文依据的原始文档) |
按照 00_Alternate_Languages/README.md 的说明,00_Alternate_Languages下的子目录存放的是 10 种约定语言(热门、内存安全、脚本型)之外的"附加移植版",仅用于教学目的。MiniScript 版本正是这样一个教育性移植:它完整保留了原始 BASIC 的游戏流程,同时利用了 MiniScript 语言简洁的语法(如列表indexOf、字符串.val/.split方法、rnd随机函数)重写了全部逻辑,全文仅 101 行。
三、两种运行方式(原文档核心内容)
MiniScript 程序可以在两类运行环境中执行,对应00_Alternate_Languages/11_Bombardment/MiniScript/README.md中给出的两种方案。
方式一:命令行版 MiniScript
- 从 MiniScript 官方命令行版下载页获取适配你操作系统的安装包,安装后
miniscript命令即可用; - 在本仓库的
00_Alternate_Languages/11_Bombardment/MiniScript/目录下执行:
miniscript bombardment.ms程序随即在终端中逐行输出规则介绍、5×5 编号矩阵,并通过input交互式接收玩家输入,回合制对局完全在终端完成。
方式二:Mini Micro 图形环境
- 下载并启动 Mini Micro(MiniScript 官方的迷你复古计算环境);
- 点击顶部的磁盘槽(disk slot),选择"Mount Folder...",选中包含
bombardment.ms和本 README 文件的那个文件夹(即00_Alternate_Languages/11_Bombardment/MiniScript/); - 在 Mini Micro 的命令提示符中依次输入:
load "bombardment" runMini Micro 会加载并运行该程序,交互方式与命令行版一致,但运行在模拟的复古终端界面中。
说明:两种方式都需要先取得 MiniScript 运行时环境(命令行解释器或 Mini Micro 模拟器),仓库本身只提供
.ms源码,不附带可执行运行时。
四、源码级解析:bombardment.ms 是如何实现的
下面按 bombardment.ms 的执行顺序拆解其实现。
4.1 规则输出与 5×5 编号矩阵
程序首先用print输出标题和完整规则(4 个排、25 个据点、先摧毁对方全部排者胜),随后用input "(Press Return.)"暂停等待玩家按键,避免规则文字滚出屏幕——这正是 11_Bombardment/README.md 的"Porting Notes"中建议的改进点,MiniScript 版已经落实。
接着打印 5 行 5 列共 25 个编号的"可撕下矩阵",供玩家对照勾选:
for row in range(1,5) for i in range(row*5-4, row*5) print (" " + i)[-6:], "" end for print end for这里用(" " + i)[-6:]把每个数字右对齐到 6 个字符宽度再同行打印(末尾空字符串参数避免换行),实现与原始 BASICPRINT I,I+1,...(见 bombardment.bas)等价的表格效果。
4.2 随机布阵:pickOutpost 辅助函数
电脑的 4 个排需要分布在 1~25 中且互不重复。MiniScript 版用一个通用辅助函数实现"从 1~25 中挑一个不在给定列表里的数":
pickOutpost = function(excludingThese) while true pick = floor(rnd * 25) + 1 if excludingThese.indexOf(pick) == null then return pick end while end functionrnd返回[0,1)的随机浮点数,floor(rnd*25)+1映射到整数 1~25;- 列表的
indexOf方法在元素不存在时返回null,因此excludingThese.indexOf(pick) == null即"该位置尚未被占用"。
随后:
computerOutposts = [] for i in range(1,4) computerOutposts.push pickOutpost(computerOutposts) end for连续调用 4 次即得到 4 个互不重复的电脑据点。对比原始 BASIC 中C/D/E/F四个变量加 6 次IF ... THEN去重(bombardment.bas),MiniScript 的写法在可读性上明显更优。
4.3 玩家布阵:容忍逗号与空格混合的输入解析
玩家同样需要输入 4 个位置。MiniScript 版对原始 BASIC 的INPUT G,H,K,L做了输入容错处理:
inp = input("What are your four positions? ") inp = inp.replace(", ", " ").replace(",", " ") inp = inp.split for pos in inp pos = pos.val playerOutposts.push pos if pos < 1 or pos > 25 then playerOutposts=[] end for- 先把逗号(含"逗号+空格")统一替换成空格,再用
split拆成词条; - 每个词条用
.val转成数值; - 一旦发现任一位置超出 1~25,立即清空
playerOutposts重新询问,从而比原始 BASIC 更严格地拦截了非法输入(原始版甚至允许输入 0 或 26 这类"打不中的"位置,见 javascript/bombardment.js 的注释)。
不过需要留意:此处的校验只检查了范围,没有显式检查 4 个位置是否彼此重复,玩家仍可能输入重复据点——这一"漏洞"从原始 BASIC 一直延续了下来(详见第六节)。
4.4 主循环:轮流攻击与胜负判定
游戏主体是一个while true死循环,每轮依次处理"玩家攻击"与"电脑攻击"。
玩家攻击:
pos = input("Where do you wish to fire your missile? ").val if computerOutposts.indexOf(pos) == null then print "Ha, ha you missed. My turn now:" else print "You got one of my outposts!" computerOutposts.remove computerOutposts.indexOf(pos) left = computerOutposts.len ... end if命中时用remove从电脑据点列表中删掉该位置,然后依据剩余数量left(3、2、1)输出 "One down, three to go." 等进度提示;当left == 0时输出经典的胜利台词 "You got me, I'm going fast. But I'll get you when My transisto&s recup%ra*e!"(沿袭自 BASIC 第 890~900 行的彩蛋式乱码,bombardment.bas),并break结束游戏。
电脑攻击:
pos = pickOutpost(memory) memory.push pos if playerOutposts.indexOf(pos) == null then print "I missed you, you dirty rat. I picked " + pos + ". Your turn:" else playerOutposts.remove playerOutposts.indexOf(pos) left = playerOutposts.len ... end ifmemory列表记录电脑此前猜过的所有位置,pickOutpost(memory)保证电脑不会重复轰炸同一据点(对应 BASIC 中第 1160~1220 行的M/M(T)去重数组);- 命中玩家据点后同样按剩余数量输出 "You have only three/two/one outpost(s) left.",当
left == 0时输出失败台词 "You're dead. Your last outpost was at ... Ha, ha, ha." 并退出。
五、与主流移植版的对照(仓库内证据)
MiniScript 版并非孤例,同一游戏在仓库中有十多个语言的实现,可用于交叉印证:
- Python 版python/bombardment.py 用
random.shuffle打乱 1~25 后取前 4 个作为电脑据点(generate_enemy_positions),并用Set天然去重;其attack函数把"命中/未命中/进度提示"抽象成参数化函数,再通过functools.partial复用于玩家与电脑双方(见 bombardment.py),设计上比 MiniScript 版更模块化,但两者对胜负的判断逻辑完全一致。 - JavaScript 版javascript/bombardment.js 保留了最贴近 BASIC 的结构(
c/d/e/f四个变量 +do...while去重),并额外修复了"重复轰炸同一据点"的原始缺陷(命中后把对应变量置 0,见 bombardment.js);其代码注释明确记录了多处对原始游戏 bug 的修复与说明。 - 相较之下,MiniScript 版在"电脑不重复选位"(
pickOutpost+memory)上与 JavaScript 版的修复目标一致,但在"玩家不许重复布阵"上仍然保留原始缺陷。
六、已知缺陷与移植注意事项
综合 11_Bombardment/README.md 的 Known Bugs 及对 MiniScript 源码的逐行核对,MiniScript 版仍继承了两个值得注意的问题:
- 玩家可重复布阵(原始已知缺陷):规则宣称"每个据点只能放一个排",但
bombardment.ms的玩家布阵分支只校验1~25的范围、不校验重复。玩家若在同一据点重复放置多个排,将导致电脑永远无法"全歼"4 个排(因为列表里同一数字出现多次),从而事实上保证玩家不败。 - 进度提示分支错误(MiniScript 版特有):玩家命中电脑后,源码中出现了两个
else if left == 3(bombardment.ms),第二个本应为left == 1,因此"剩 1 个据点"时不会输出 "Three down, one to go." 而会静默跳过。对照 bombardment.bas 的IF Q=1/2/3三分支可见这是一个笔误级转换错误。
此外,原文档还提示:为了让规则文字不滚出屏幕,移植时应像 MiniScript 版一样加入(Press Return.)暂停提示(详见 11_Bombardment/README.md 的 Porting Notes)。
七、小结与扩展阅读
通过本文,你已经掌握:
- MiniScript 版的两种运行方式:终端下
miniscript bombardment.ms,或在 Mini Micro 中挂载文件夹后load "bombardment"+run; bombardment.ms的完整实现脉络:右对齐矩阵打印、pickOutpost无重复随机选点、容忍逗号/空格的输入解析、基于indexOf/remove的命中判定与逐轮进度播报;- 与 Python、JavaScript 移植版在随机策略、去重修复和模块化设计上的异同,以及继承自原始 BASIC 的两处已知缺陷。
若想进一步研究,可继续阅读同一游戏的其他实现:
- 原始 BASIC 程序:11_Bombardment/bombardment.bas;
- 游戏完整规则与移植笔记:11_Bombardment/README.md;
- Python 模块化实现:11_Bombardment/python/bombardment.py;
- JavaScript 修复版:11_Bombardment/javascript/bombardment.js;
- 其他 10 种约定语言实现:11_Bombardment 下的
csharp/、java/、ruby/、rust/等目录。
- 示例工程
【免费下载链接】basic-computer-games
An updated version of the classic "Basic Computer Games" book, with well-written examples in a variety of common MEMORY SAFE, SCRIPTING programming languages. See https://coding-horror.github.io/basic-computer-games/
相关推荐
Nuclei 漏洞扫描模板使用指南:13000+ 模板如何快速上手
Nuclei 漏洞扫描模板使用指南:13000+ 模板如何快速上手 Nuclei Templates 是为 Nuclei 扫描引擎提供检测规则(模板)的开源仓库
示例工程15个文件读透GPU并行架构:tiny-gpu矩阵乘法仿真实操指南
15个文件读透GPU并行架构:tiny gpu矩阵乘法仿真实操指南 tiny gpu 用 15 个以内的 Verilog 源文件,把 GPU 并行执行、指令译码
示例工程gVisor Sentry VFS 深度解析:引用计数与 Inheritance 模式的设计内幕
gVisor Sentry VFS 深度解析:引用计数与 Inheritance 模式的设计内幕 本文基于 gVisor 仓库中的 pkg/sentry/vfs
示例工程
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考