
Basic Computer Games 仓库中 GUESS 猜数字游戏的备选语言移植从 BASIC 到 Go 与 MiniScript 的完整解析【免费下载链接】basic-computer-gamesAn 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/项目地址: https://gitcode.com/gh_mirrors/ba/basic-computer-games本指南以 00_Alternate_Languages/41_Guess/README.md 为主体围绕「备选语言Alternate Languages」目录的准入策略深入剖析经典猜数字游戏 GUESS 在 BASIC 原始实现之外的 Go 与 MiniScript 移植版。读完本文你将掌握该仓库备选语言目录的组织规则、GUESS 游戏的核心算法二进制搜索提示与标准杆数公式以及如何在本仓库中运行、对比并继续扩展这些移植实现。一、备选语言目录定位与准入标准00_Alternate_Languages/41_Guess/README.md 开篇即指明请参见父目录的 readme并说明该目录下的每个子文件夹代表本程序GUESS向某种语言的移植而该语言不在约定的 10 种语言之内。这 10 种约定语言需要同时满足三条标准流行度Popular以 TIOBE 指数为参考内存安全Memory safe通常被视为「脚本」语言Generally considered a scripting language。而父目录 00_Alternate_Languages/README.md 进一步补充了关键细则备选语言目录中的实现不受上述三条标准约束——例如这里允许出现 C 或 PASCAL移植时仍需忠实于原始程序的界面观感控制台应用并尽量保持代码可移植若做不到则必须在 README 与文件夹命名中明确说明这一限制。仓库欢迎任意语言的额外移植但这些移植仅用于教育目的不计入项目末尾的捐赠总数。这一策略保证了主目录41_Guess下十种约定语言的实现风格统一、质量可控同时为教学场景留下了开放空间学习者可以在 Go、MiniScript 这类非约定语言中观察同一游戏逻辑的不同表达方式。二、GUESS 游戏本身规则与二进制搜索提示游戏的正式说明见 41_Guess/README.md在程序 GUESS 中计算机在 0 到你设定的任意上限之间选择一个随机整数玩家必须依据计算机给出的线索猜出该数字。文档特别给出了一个数学提示你应该能在「该数字的二进制表示所需位数减一」的次数内猜中它——即在二进制base 2中的位数减一。这应当能给你关于最优搜索技巧的线索。这其实就是二分搜索的提示例如上限为 100 时二进制位数为 7因为 2⁶64 ≤ 100 2⁷128那么理想情况下 6 次左右即可猜中。该游戏由 Walt Koetke美国马萨诸塞州列克星敦高中为「Computers in the Classroom」一书编写原程序为 FOCAL 语言后收录于 1978 年出版的Basic Computer Games一书。需要留意的一个细节文档描述的是「0 到任意上限」但实际实现是「1 到上限」。这一点在 41_Guess/python/guess.py 的注释中做了明确说明——由于计算上限二进制位数时必须使用对数程序实际选择 1 到上限之间的数。三、原始 BASIC 实现逐行解读仓库在 00_Alternate_Languages/41_Guess/guess.bas 中保存了完整的 BASIC 原始程序40 行它是所有移植版本的基准。核心逻辑如下8 PRINT WHAT LIMIT DO YOU WANT; 9 INPUT L 10 PRINT 11 L1INT(LOG(L)/LOG(2))1 12 PRINT IM THINKING OF A NUMBER BETWEEN 1 AND;L 13 G1 15 MINT(L*RND(1)1) 20 INPUT N 21 IF N0 THEN 25 22 GOSUB 70 23 GOTO 1 25 IF NM THEN 50 30 GG1 31 IF NM THEN 40 32 PRINT TOO LOW. TRY A BIGGER ANSWER. 40 PRINT TOO HIGH. TRY A SMALLER ANSWER. 50 PRINT THATS IT! YOU GOT IT IN;G;TRIES. 52 IF GL1 THEN 58 54 IF GL1 THEN 60 56 PRINT YOU SHOULD HAVE BEEN ABLE TO GET IT IN ONLY;L1 58 PRINT VERY ; 60 PRINT GOOD. 70 FOR H1 TO 5 71 PRINT 72 NEXT H 73 RETURN三个值得注意的实现要点标准杆数公式第 11 行L1 INT(LOG(L)/LOG(2)) 1即上限L的二进制位数。BASIC 只提供自然对数LOG因此用换底公式LOG(L)/LOG(2)得到以 2 为底的对数取整后加一。这个L1就是游戏判定「Very good / Good / 应该能更少」的分界值。随机数生成第 15 行M INT(L*RND(1)1)利用RND(1)产生 [0,1) 区间随机数乘以上限再加一并取整得到 1 到 L 之间的目标数。输入非正数的处理第 21-23 行若玩家输入N0则先调用子程序 70 打印 5 个空行FOR H1 TO 5: PRINT: NEXT H然后GOTO 1从头重新开始整个程序——这是原版游戏中「放弃当前回合、重新设定上限」的机制。四、Go 移植现代语言的严格输入校验Go 移植版位于 00_Alternate_Languages/41_Guess/go/main.go是一个不依赖第三方包的独立main.gopackage main可直接运行。与 BASIC 原版相比它做了三处典型的「现代语言加固」1. 输入校验循环。getLimit函数使用bufio.Scanner读取输入并用strconv.Atoi转换当解析失败或limit 0时会输出Please enter a number greater or equal to 1并重新提示而不是像 BASIC 那样直接接受任意输入limit, err : strconv.Atoi(scanner.Text()) if err ! nil || limit 0 { fmt.Println(Please enter a number greater or equal to 1) continue } limitGoal : int((math.Log(float64(limit)) / math.Log(2)) 1) return limit, limitGoal2. 随机源显式播种。rand.Seed(time.Now().UnixNano())确保每次运行生成不同的目标数目标数计算为int(float64(limit)*rand.Float64() 1)与 BASIC 的INT(L*RND(1)1)语义一致。3. 非正输入的语义变化。猜数字循环中输入n 0时直接break退出整个循环与 BASIC 的「重启程序」不同Go 版是静默结束这也是移植中值得注意的行为差异之一。得分判定逻辑则忠实保留了原版三段式guessCount limitGoal输出Very good.相等输出Good.否则输出You should have been able to get it in only %d guesses.。在仓库根目录下直接运行go run 00_Alternate_Languages/41_Guess/go/main.go五、MiniScript 移植三种运行方式与函数化结构MiniScript 移植版位于 00_Alternate_Languages/41_Guess/MiniScript/guess.ms其运行说明见 00_Alternate_Languages/41_Guess/MiniScript/README.md。它把原版程序组织为三个清晰函数setup打印标题与规则介绍循环读取limit要求大于 1否则提示重新输入并计算par floor(log(limit, 2)) 1作为标准杆数——注意 MiniScript 的log(x, 2)原生支持指定底数无需换底公式printGap对应 BASIC 子程序 70打印 5 个空行分隔界面doOneGame完整的一局游戏目标数为ceil(rnd * limit)用ceil而非floor1语义等价输入num 0时打印空行并重新setup对应原版的GOTO 1重启机制。猜中后的判定沿用了原版逻辑guess par输出Very good.相等输出Good.否则提示You should have been able to get it in only par.然后回到setup让玩家设定新的上限形成无限循环。MiniScript 移植版提供了三种运行方式命令行版从 miniscript.org 的 Command-Line 页面下载对应系统的命令行 MiniScript 并安装然后在仓库根目录执行miniscript 00_Alternate_Languages/41_Guess/MiniScript/guess.msMini Micro下载并启动 Mini Micro 后点击顶部磁盘槽选择 Mount Folder...挂载包含guess.ms的文件夹然后在 Mini Micro 命令提示符中输入load guess与run网页 Try-It 页面打开 miniscript.org 的 Try-It 页面清空编辑器默认代码粘贴guess.ms的内容点击 Run Script 按钮。六、移植要点对比行为差异一览综合原始 BASIC 与各移植版可以总结出几个关键移植决策点关注点BASIC 原版guess.basGo 版main.goMiniScript 版guess.msPython 版guess.py目标数范围INT(L*RND(1)1)→ 1..Lint(limit*rand.Float64()1)→ 1..Lceil(rnd*limit)→ 1..Lint(limit*random()1)→ 1..L标准杆数公式INT(LOG(L)/LOG(2))1int((math.Log(L)/math.Log(2))1)floor(log(limit, 2))1int((log(limit)/log(2))1)非正输入处理打印空行后GOTO 1重启程序n0时 break 静默退出打印空行后重新setupn0时 break随后重新limit_set()上限输入校验无解析失败或0时循环重试要求1要求0时循环重试从上表可以看出游戏算法在各语言间保持高度一致目标数范围、标准杆数公式、三段式评分差异主要集中在对异常输入的处理策略上——这正体现了「忠实原版界面与逻辑、同时按语言惯例做输入加固」的移植原则。Python 版在 41_Guess/python/guess.py 中还以注释形式记录了「文档说 0 到上限、实际实现是 1 到上限」的历史原因是理解本游戏细节的第一手材料。此外主目录 41_Guess 下的十种约定语言实现如 csharp/Game.cs、java/GuessGame.java、rust/src/main.rs、javascript/guess.js 等可作为对照样本其中 JavaScript 版41_Guess/javascript/guess.js通过tab(33)与tab(15)精确复刻了原版的标题缩进且将评分逻辑压缩为gl1/gl1/gl1三分支逻辑完全一致、写法更紧凑。七、总结从一处游戏看多语言移植方法论GUESS 虽是一个仅 40 行的简单游戏却浓缩了 Basic Computer Games 仓库移植方法论的全部要点以 00_Alternate_Languages/README.md 确立的备选语言政策为边界以 00_Alternate_Languages/41_Guess/guess.bas 为逻辑基准在 Go 与 MiniScript 两个备选语言中实现了同一游戏的不同表达。对于想要自己动手增加新语言移植的读者建议的实践路径是先通读guess.bas确认核心逻辑目标数生成、L1公式、评分分支、空行分隔再对照本目录已有的 Go 或 MiniScript 移植观察输入校验等加固手法最后参照 41_Guess/README.md 的 Porting Notes 记录移植中遇到的难点保持控制台观感与可移植性即可提交自己的版本。【免费下载链接】basic-computer-gamesAn 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/项目地址: https://gitcode.com/gh_mirrors/ba/basic-computer-games创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考