ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

basic-computer-games 的 70_Poetry 全解析:从 1978 年 BASIC 俳句生成器到六种语言移植实现

basic-computer-games 的 70_Poetry 全解析:从 1978 年 BASIC 俳句生成器到六种语言移植实现 示例工程【免费下载链接】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点击查看免费下载Poetry 是经典书籍Basic Computer Games1978中的第 70 号程序它用 20 个短语按固定组序循环组合再配合随机标点、缩进与分段规则生成可被宽松地视为日本俳句风格的随机诗句。本文以 70_Poetry/README.md 为主体结合仓库内 BASIC 原版 poetry.bas 与 Python、C#、Java、Ruby、JavaScript、Perl 六种移植实现逐层拆解其词库组织、概率排版引擎与各语言重写思路读完你将能完整理解该程序的运行机制并学会如何替换短语库生成自定义风格的诗句。程序概览一个随机的俳句风格诗句生成器Poetry 的设计目标非常纯粹不依赖任何用户输入程序启动后便持续不断地生成诗句直到被强制中断。其核心特征在 70_Poetry/README.md 中概括为四点20 个短语分为 4 组每组 5 个生成时基本按组顺序循环第 1 组 → 第 2 组 → 第 3 组 → 第 4 组 → 段落结束随机插入逗号约 19% 的概率随机插入缩进约 22% 的概率随机开始新段落约 18% 的概率但保证至少每 20 个短语出现一次段落分隔。README 还特别指出程序的短语风格略带爱伦·坡Edgar Allen Poe的意味。对照 poetry.bas 中的短语表可以确认这一点——QUOTH THE RAVEN、NEVERMORE、MIDNIGHT DREARY、FIERY EYES、BIRD OR FIEND等几乎全部取材自坡的名篇《乌鸦》The Raven。原文档的作者信息同样值得保留该程序原作者不详后由 DEC 的 Jim Bailey、Peggy Ewing 与 Dave Ahl 修改和重做1978 年收录于Basic Computer Games一书其源码随后被 Vintage Basic 站点收录成为本仓库移植工作的蓝本。词库系统4 组 × 5 个短语的完整短语表综合 poetry.bas行 90-135、python/poetry.py 的line_1_options至line_4_options以及 csharp/Phrase.cs 中的_phrases静态表可以交叉确认程序内置的完整 20 个短语组序短语 1短语 2短语 3短语 4短语 5第 1 组MIDNIGHT DREARYFIERY EYESBIRD OR FIENDTHING OF EVILPROPHET第 2 组BEGUILING METHRILLED MESTILL SITTING....NEVER FLITTINGBURNED第 3 组AND MY SOULDARKNESS THERESHALL BE LIFTEDQUOTH THE RAVENSIGN OF PARTING第 4 组NOTHING MOREYET AGAINSLOWLY CREEPING...EVERMORENEVERMORE每组内 5 个短语被等概率随机选中每个 20%。BASIC 原版通过行 215 的IINT(INT(10*X)/2)1把 0-9 的随机数折叠映射到 1-5实现均匀抽取Python 版则直接调用random.randint(0, 4)得到 0-4 的索引。值得注意的是短语表中埋藏着三条特殊控制规则它们让诗句在随机之余仍能保持基本的语法连贯强制逗号连接第 2 组的BEGUILING ME与NEVER FLITTING会将状态U置为 2见 poetry.bas 行 111、114使后续短语大概率以逗号衔接形成XX ME, XX的排比句式跳过逗号机会第 2 组的STILL SITTING....直接跳转至行 212绕过行 210 的逗号判断——因为短语以句点结尾不能再接逗号Python 版则在 maybe_comma 中做了更通用的保护只要当前行以.结尾就永不追加逗号条件打印第 3 组的SIGN OF PARTING仅在U≠0时才输出poetry.bas 行 125-126U0时直接跳过该短语避免它在换行后突兀出现。排版引擎四重随机规则的概率参数诗句的排版由三个独立概率控制它们在 BASIC 原版中对应 poetry.bas 行 210-214随机数统一由行 500 的子程序XRND(1)提供规则概率BASIC 行号触发效果插入逗号19%且要求U≠0210-211打印,并将U置为 2插入空格同行续写65%212-213打印空格U自增 1换行结束当前行35%214打印换行U清零变量U在此扮演标点衔接状态的角色它记录当前行内已经累积的短语间距U≠0表示行尚未结束、允许追加逗号。因此 19% 的逗号概率实际上是在行未结束的前提条件之下的概率这与 README 中插入逗号随机 19%的描述完全吻合。缩进逻辑位于行 230-235当U0新行起点且J为偶数时打印 5 个空格作为缩进概率约为 22%。分段逻辑位于行 240-270J从 1 递增到 4 时依次进入第 1-4 组J5时打印换行完成一个诗节stanza计数器K累计已生成短语数当K20时额外打印空行、重置K并跳到行 110 从第 2 组重新开始——这就是 README 所述至少每 20 个短语换一次段落的源码依据。BASIC 原版逐段解析poetry.bas 全文 51 行结构非常紧凑可划分为四个区段行 5-30初始化与标题行 5YRND(-1)以负数参数初始化随机数种子行 6-9 是被注释掉的调试代码原本用于打印随机数序列并GOTO 999行 10-30 居中打印POETRY与CREATIVE COMPUTING MORRISTOWN, NEW JERSEY标题。行 90-135四组短语每组以ON I GOTO ...根据当前短语序号I分派到具体PRINT语句打印后统一汇合到行 210 的排版逻辑。行 210-215随机排版与下一短语选择依次处理逗号、空格/换行随后通过GOSUB 500取新随机数并计算下一个I、递增J、K。行 240-270诗节与段落控制ON J GOTO 90,110,120,130,250按J值进入对应组J5时完成一个诗节并判断是否开启新段落行 999END为程序终点。主循环是一个典型的行号跳转状态机没有显式的FOR/WHILE全靠GOTO与ON...GOTO在四个短语组之间轮转这正是 1970 年代 BASIC 程序常见的控制流风格也为后续面向过程语言的移植带来了不小的挑战。Python 移植数据类驱动的状态机重写python/poetry.py 由 Dave LeCompte 移植是理解整个算法的最佳入口。它将 BASIC 的全局变量显式封装为一个Statedataclassdataclass class State: u: int 0 # 行内标点衔接状态 i: int 0 # 当前短语索引0-4 j: int 0 # 组内累计0-4 k: int 0 # 短语总数决定段落 phrase: int 1 # 当前所处短语组1-5 line: str # 正在拼装的行四个短语组被重写为process_phrase_1至process_phrase_4四个函数每组内部用列表存储短语特殊规则以元组副标记载入数据——例如第 2 组写作(BEGUILING ME, 2)、(STILL SITTING...., None)第 3 组的SIGN OF PARTING则用(True, SIGN OF PARTING)标记仅当U0时打印。主循环main()用一个phrase_processors字典把组号映射到处理函数并辅以maybe_comma、pick_phrase两个辅助函数maybe_comma对应 BASIC 行 210-214先做句点保护再以0.19/0.65两个阈值决定逗号、空格还是换行pick_phrase对应 BASIC 行 215-230随机选短语、递增计数并在u 0且j为奇数时追加 5 空格缩进。移植版还顺带修复了原版的两个小问题用print_centered按PAGE_WIDTH 64计算居中空格数并把State.phrase初始化为 1从而将第一句永远是 MIDNIGHT DREARY这一行为显式化详见下文移植注意事项。C# 移植表格驱动的面向对象设计C# 版本把短语表与状态彻底解耦是六种移植中抽象程度最高的实现。其工程结构位于 csharp/Program.cs三行入口Poem.Compose(new ConsoleIO(), new RandomNumberGenerator())将输入输出与随机数两个依赖注入到组合器Phrase.cs用Phrase[][]静态二维数组存放 4×5 短语表每个Phrase对象由条件谓词PredicateContext、文本与副作用ActionContext三部分组成——SIGN OF PARTING注册了ctx ctx.PhraseCount ! 0条件STILL SITTING....注册了ctx ctx.SkipNextComma()副作用BASIC 里的行号跳转在此变成了优雅的数据驱动声明Context.cs集中管理全部可变状态并原样保留了三条概率常量——MaybeWriteComma使用0.19F、WriteSpaceOrNewLine使用0.65F、MaybeCompleteStanza在_lineCount 20时结束段落此外还通过MaybeCapitalise实现了行首字母自动大写的增强弥补了 BASIC 全大写输出的生硬感Poem.csCompose用while (true)无限循环串联WritePhrase → MaybeWriteComma → WriteSpaceOrNewLine → Update → MaybeIndent → 段落判断与 BASIC 主循环一一对应。其他移植Java、Ruby、JavaScript 与 PerlJavajava/Poetry.javaDarren Cardenas 转换将三个概率提炼为常量COMMA_RATE 0.19、SPACE_RATE 0.65、PARAGRAPH_RATE 20并用Step枚举WORD_GROUP1到RANDOMIZE_COUNTERS构建了一个显式的有限状态机startGame()内的switch (nextStep)每次仅推进一个状态——这是对 BASICON...GOTO最忠实的结构化重现。Rubyruby/poetry.rb与 Python 版结构同构同样是State类 process_phrase_*函数族 maybe_comma/pick_phrase可作为对照阅读。JavaScriptjavascript/poetry.jsOscar Toledo G. 转换刻意保留了 BASIC 的行式结构if (j 1) ... else if (j 2) ...逐组展开四个短语组的 switch它也是唯一一个主动终结程序的移植——通过times 10在生成 10 个段落后退出循环并显式初始化i 1; j 1; k 0; u 0。Perlperl/poetry.pl由仓库工具 bas2perl.pl 自动转换而成文件头注释直白地写着Too much spaguetti code to be properly converted全篇保留goto Line90式的行号跳转恰好展示了 BASIC 原版控制流意面化的一面。移植注意事项Porting Notes70_Poetry/README.md 末尾记录了两条原版代码的历史遗留问题移植时必须留意未初始化变量I程序从行 90ON I GOTO 100,101,102,103,104开始而I在此之前从未被赋值。从源码行为看I0时ON...GOTO不会匹配任何目标执行会自然落入行 100即第一句必然是MIDNIGHT DREARY。移植时应当显式初始化为 0——但这样做意味着输出永远以 midnight dreary 开头随机性从第一句起就打了折扣。Python、Ruby、JavaScript 版都选择了显式初始化因此保留了这一固定开头。END语句不可达行 999 的END从未被执行——主循环在行 90-270 之间无限跳转程序会持续不断地生成诗句直到被用户强制中断CtrlC 或关闭终端。除 JavaScript 版加入了 10 段落的退出上限外其余移植版本均以while True忠实复现了这一无限生成行为。运行方式从源码形态可以确认各语言版本的运行入口Pythoncd 70_Poetry/python python3 poetry.pyRubycd 70_Poetry/ruby ruby poetry.rbJavacd 70_Poetry/java javac Poetry.java java PoetryC#cd 70_Poetry/csharp dotnet run工程含 Poetry.csproj 与 Poetry.slnJavaScript用浏览器直接打开 poetry.html输出渲染到页面output区域Perlcd 70_Poetry/perl perl poetry.plBASIC 原版需在兼容 Vintage BASIC 语法的解释器中加载 poetry.bas 运行各语言子目录下的 README.md 记录了移植来源信息仓库根目录的 HOW_TO_RUN_THE_GAMES.md 提供了整体运行指引运行后程序会立即开始打印诗句例如不同随机种子下结果不同MIDNIGHT DREARY BEGUILING ME, AND MY SOUL NOTHING MORE NEVER FLITTING DARKNESS THERE YET AGAIN自定义短语库让程序写出你的主题Poetry 最有趣的扩展点在于短语表完全可替换。原 README 特意附上了一组自然主题的短语示例供读者直接替换进程序Carpet of ferns Mighty Oaks Morning dew Grace and beauty Tang of dawn Silently singing Swaying pines Nature speaking Entrances me Untouched, unspoiled Soothing me Shades of green Rustling leaves Tranquility Radiates calm …so peacefulREADME 建议读者尝试计算机技术、爱情浪漫、四岁儿童等主题的短语并寄回程序输出。从实现上看替换方式非常直接在 Python/Ruby 版中修改process_phrase_1至process_phrase_4里的四个列表或在 C# 版中改写 Phrase.cs 的_phrases二维表。只要保持每组 5 个短语的规模并酌情保留两条语法规则——以句点结尾的短语不应再接逗号、需要排比的短语可强制逗号衔接——即可让程序输出完全不同的诗风而 19% 逗号、65% 空格、22% 缩进与每 20 短语一段的随机排版引擎无需任何改动。综上Poetry 是一个体量极小但算法层次丰富的经典程序它用一张 4×5 短语表和三个概率常数在随机与语法连贯之间取得了精妙的平衡而仓库内六种语言的移植实现则从行号跳转、数据类状态机、表格驱动对象到显式 FSM完整展示了同一算法在不同编程范式下的表达方式是阅读与学习经典游戏移植的最佳样本之一。赞分享示例工程【免费下载链接】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点击查看免费下载相关推荐从 1978 年 BASIC 到 10 种现代语言Chief 数字推理游戏移植全解析basic-computer-games从 1978 年 BASIC 到 10 种现代语言Chief 数字推理游戏移植全解析basic computer games 导读 Chief中文可译作示例工程Basic Computer Games 之 Hangman从 1978 年 BASIC 原版到 C / MiniScript 的多语言移植实战解析Basic Computer Games 之 Hangman从 1978 年 BASIC 原版到 C / MiniScript 的多语言移植实战解析 导读 H示例工程Basic Computer Games 之 Diamond 菱形图案程序从 1978 年 BASIC 到现代语言的移植解析Basic Computer Games 之 Diamond 菱形图案程序从 1978 年 BASIC 到现代语言的移植解析 本指南以经典书籍《Basic C示例工程上一篇Presto 0.247 版本解读QueryInterceptor、临时函数与分区统计优化的全面剖析下一篇9Router × Claude Code 集成指南环境变量、模型别名与云端 Endpoint 配置全解创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表