- 示例工程
【免费下载链接】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/
High IQ(独立钻石棋)是 1978 年经典《Basic Computer Games》合集中的一局逻辑游戏,本仓库在00_Alternate_Languages/48_High_IQ/MiniScript/目录下提供了完整的 MiniScript 移植版。本文将围绕 MiniScript 运行说明 展开,完整讲解两种官方推荐的运行方式(命令行 MiniScript 与 Mini Micro 图形环境),并深入到 highiq.ms 的源码,剖析棋盘建模、走子合法性判定、终局判定等核心实现,最后对照原始 BASIC 版本 说明移植思路。读完本文,你既能立刻跑起这局游戏,也能理解其数据结构与算法设计,可据此复刻到任意语言。
游戏背景:High IQ 是什么
根据 48_High_IQ/README.md 的项目说明,High IQ 是一款经典欧洲单人跳棋(European solitaire)的计算机化版本:游戏使用一个十字形(cross-shaped)棋盘,除中心孔外每个孔都插有钉子(peg),共 32 枚。玩家通过"跳子"将钉子跳入空孔,被跳过的钉子被移除,目标是移除全部 32 枚钉子——若无法全部移除,则尽可能多移。游戏存在多种可获胜的策略,且每种策略在棋盘上可沿八个方向施展。
该游戏由 Charles Lund 在荷兰海牙的美国学校(The American School in The Hague)期间编写,最初收录于 1978 年版《Basic Computer Games》。其 BASIC 源码由 Vintage Basic 归档收录,本仓库在 48_High_IQ/highiq.bas 保留了原始实现。
在仓库结构上,00_Alternate_Languages/目录(见 00_Alternate_Languages/README.md)存放的是不属于约定 10 种主语言、但被社区欢迎的"备选语言"移植版,MiniScript 移植即归此类,主要供教育学习用途。该目录下每个游戏子目录都遵循"游戏名/MiniScript/README.md + *.ms"的组织方式,High IQ 对应 MiniScript 目录,其中包含两个文件:
README.md:移植说明与运行指南(即本文主体文档);highiq.ms:完整可运行的 MiniScript 源码(约 160 行)。
运行方式一:命令行 MiniScript
关联文档给出的第一种运行方式是使用 MiniScript 的命令行解释器(Command-Line MiniScript)。完整步骤如下:
- 前往 MiniScript 官方命令行版本下载页,获取适配你操作系统的安装包;
- 按官方说明完成安装,确保
miniscript命令可用; - 在终端中进入本仓库的
00_Alternate_Languages/48_High_IQ/MiniScript/目录(或用绝对路径指定文件),执行:
miniscript highiq.ms程序随即启动:先打印标题与带钉子编号的初始棋盘图,提示玩家记下编号后按回车开始,之后进入"输入走子编号 → 显示更新棋盘 → 判定终局"的循环。
运行方式二:Mini Micro 图形环境
第二种方式是在 Mini Micro(MiniScript 官方内置的虚拟计算机/图形环境)中运行,适合希望在图形化文件系统与终端中操作的用户:
- 下载并启动 Mini Micro;
- 点击顶部磁盘槽位(top disk slot),选择"Mount Folder..."(挂载文件夹);
- 在弹出的对话框中选择包含
highiq.ms与README.md的 MiniScript 文件夹(即本仓库的00_Alternate_Languages/48_High_IQ/MiniScript/),完成挂载; - 在 Mini Micro 的命令行提示符下依次输入:
load "highiq" runload会从挂载的文件夹载入highiq.ms程序,run则启动它。Mini Micro 方式的好处是不需要单独安装命令行解释器,并且加载后可以方便地查看、编辑脚本源码。
源码剖析一:十字棋盘的建模
理解了两种运行方式后,再深入 highiq.ms 看棋盘是如何在内存中表达的。
setupBoard函数(highiq.ms)构建了一个 9×9 的二维数组t作为棋盘,使用三种数值标记格子状态:
5:该格有钉子(pin);0:该格是空孔(hole);-5:该格无效(棋盘外的区域,不参与游戏)。
globals.t = [[-5]*10] pinNums = [13,14,15,22,23,24,29,30,31,32,33,34,35,38,39,40,41, 42,43,44,47,48,49,50,51,52,53,58,59,60,67,68,69] for row in range(1,9) t.push [-5]*10 for col in range(1,9) if row < 2 or row > 8 or col < 2 or col > 8 or ((row < 4 or row > 6) and (col < 4 or col > 6)) then t[row][col] = -5 else t[row][col] = 5 pinToPos[pinNums.pull] = [row,col] end if end for end for t[5][5] = 0坐标系中(row < 2 or row > 8 or col < 2 or col > 8)抠出 7×7 的方形区域,而((row < 4 or row > 6) and (col < 4 or col > 6))再抠掉四角,恰好形成十字形状;随后t[5][5] = 0将正中心置为空孔——这正是"32 枚钉子 + 中心空位"的经典开局。
同时,函数用globals.pinToPos字典建立了"钉子编号 → [行, 列]"的映射,33 个有效位置按上、中、下三段的顺序依次分配编号 13~69(编号模式与原始 BASIC 版完全一致,见下节)。这套"二维数组 + 编号映射"的双重结构,是后续所有走子与判定逻辑的基础。
源码剖析二:走子合法性判定
游戏规则要求"跳过相邻钉子跳入空孔",isValidJump(highiq.ms)用非常直观的方式实现了该判定:
isValidJump = function(pinFrom, pinTo) if not pinToPos.hasIndex(pinFrom) then return false posFrom = pinToPos[pinFrom] if not isHole(pinTo) then return false posTo = pinToPos[pinTo] // check that the Manhattan distance is exactly 2 dist = abs(posFrom[0] - posTo[0]) + abs(posFrom[1] - posTo[1]) if dist != 2 then return false // and check that the intervening position contains a pin if t[(posFrom[0]+posTo[0])/2][(posFrom[1]+posTo[1])/2] != 5 then return false return true end function判定分三步:起点必须是真实存在的钉子(isPin,见 highiq.ms);终点必须是空孔(isHole,见 highiq.ms);起终点的曼哈顿距离必须恰好为 2(即水平或垂直相隔一格),且二者正中间的那格必须包含一枚钉子。三步全过才算合法跳子。
getMove(highiq.ms)把该判定封装进一个while true输入循环:先询问 "Move which piece?",若起点是钉子再询问 "To where?",只有同时通过isHole与isValidJump检查才跳出循环,否则打印Illegal move, try again...并重新输入——这保证了非法输入绝不会污染棋盘状态。
执行走子则落在doOneMove(highiq.ms):将起点格置 0(钉子离开)、终点格置 5(钉子落入)、中间格置 0(被跳过的钉子移除),三次数组写入完成一次完整的跳子。
源码剖析三:终局判定与计分
checkGameOver(highiq.ms)遍历棋盘上每一枚钉子,检查其上下左右两格远处([row-2, row+2]、[col-2, col+2])是否存在合法跳点;只要找到任意一个合法跳子就立即返回false(游戏未结束),全部遍历完仍无合法跳子才返回true。
主循环(highiq.ms)则串联起整局流程:
while true setupBoard printBoard while true doOneMove print printBoard if checkGameOver then break end while print; print "The game is over." pinsLeft = 0 ... print "You had " + pinsLeft + " pieces remaining." if pinsLeft == 1 then print "Bravo! You made a perfect score!" print "Save this paper as a record of your accomplishment!" end if yn = input("Play again (yes or no)? ").lower if yn and yn[0] == "n" then break end while print; print "So long for now."; print终局后程序统计剩余钉子数(遍历数组计数5),若恰好剩 1 枚则打印满分祝贺语;随后询问 "Play again (yes or no)?",输入以n开头(大小写不敏感,.lower统一转小写)即退出,否则重置棋盘开始新一局。棋盘渲染由printBoard(highiq.ms)完成:无效格输出两个空格、空孔输出o、钉子输出!,与原始 BASIC 版的字符风格保持一致。
与原始 BASIC 版的对应关系
对照 highiq.bas 可以看出 MiniScript 移植保留了原版的数据结构与流程骨架,只是用现代语言特性重写:
| 职责 | BASIC 原版(highiq.bas) | MiniScript 移植(highiq.ms) |
|---|---|---|
| 棋盘建模 | DIM T(9,9),5/-5/0三态标记(L4、L28-L65) | 9×9 数组t同三态标记,setupBoard |
| 钉子编号 | DATA语句声明 33 个编号 +B(M)=-7映射(L36-L41) | pinNums列表 +pinToPos字典 |
| 走子合法性 | 借助B()数组与算术判断(L100-L190) | isPin/isHole/isValidJump函数 |
| 打印棋盘 | GOSUB 500(L56-L72),TAB(Y*2)排版 | printBoard函数 |
| 更新棋盘 | GOSUB 1000(L73-L98) | doOneMove函数 |
| 终局判定 | GOSUB 1500(L99-L133) | checkGameOver函数 |
值得注意的是,BASIC 版的编号体系(13、14、15 / 22、23、24 / 29~35 / 38~44 / 47~53 / 58、59、60 / 67、68、69)被 MiniScript 版原样继承,这意味着两版的走子输入方式与玩家操作体验完全一致,也便于对照调试。此外,BASIC 版的中心编号为 41(B(41)=-3,即初始空孔),与 MiniScript 版t[5][5]=0语义等价。
运行与验证要点
- 预期输出:程序启动后依次打印标题 "H-I-Q"、Creative Computing 版权行、带编号的完整棋盘图,以及压缩版棋盘使用提示;游戏过程与结束时的提示语均可在源码
print语句中核对(如Illegal move, try again...、The game is over.、You had N pieces remaining.、Bravo! You made a perfect score!)。 - 两种运行方式的选择:仅需终端执行脚本用命令行 MiniScript;希望在可视化虚拟磁盘中浏览文件、编辑源码则用 Mini Micro 的 "Mount Folder..." 挂载方式。二者加载的都是同一个
highiq.ms,行为一致。 - 适用前提:命令行方式要求系统已安装 MiniScript 命令行解释器;Mini Micro 方式要求已安装 Mini Micro。本仓库只提供
.ms脚本与说明文档,不包含解释器本身,首次运行前需先完成对应环境的安装与挂载配置。
通过本文,你既掌握了在两种环境下运行 High IQ MiniScript 移植版的具体操作,也理解了其"9×9 三态棋盘 + 编号映射 + 曼哈顿距离判定"的实现范式——这套模式在00_Alternate_Languages目录下其他 MiniScript 移植(如 Craps、Diamond 等)中同样适用,可作为学习 MiniScript 游戏开发与经典游戏移植的参考起点。
- 示例工程
【免费下载链接】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/
相关推荐
shopspring/decimal 深入解析:Loki 依赖链中防止浮点精度丢失的任意精度十进制库
shopspring/decimal 深入解析:Loki 依赖链中防止浮点精度丢失的任意精度十进制库 导读 本文以 Loki 仓库中 vendored 的 sh
示例工程用 MiniScript 运行经典纸牌游戏 War:从安装、运行到源码解析(basic-computer-games)
用 MiniScript 运行经典纸牌游戏 War:从安装、运行到源码解析(basic computer games) 本文以 basic computer g
示例工程basic-computer-games 仓库实战:用 MiniScript 运行经典《Math Dice》骰子算术教学游戏
basic computer games 仓库实战:用 MiniScript 运行经典《Math Dice》骰子算术教学游戏 导读 本文以 basic comp
示例工程
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考