5KB内实现适用于curses的克朗代克纸牌游戏:参加IOCCC的独特尝试!
1. 竞赛背景与目标
作者Oscar Toledo G.在有空余时间且注意到第29届国际混淆C代码竞赛(IOCCC)开始后,决定为此次竞赛编写参赛作品。国际混淆C代码竞赛始于1984年,由Landon Curt Noll创办,目标是在规则规定的特定大小限制内编写混淆的C程序。今年,程序的最大大小为4993字节(略小于5千字节),可打印字符数量为2503个,有`iocccsize`工具用于检查这些限制。
2. 创意来源
作者决定用C语言编写克朗代克纸牌游戏,因其在职业生涯中编写过多个纸牌游戏,约二十年前为自己的操作系统编写过一个,最近还为Intellivision游戏机编写了克朗代克纸牌游戏。纸牌游戏和扫雷游戏曾被包含在Windows 3.1中且大获成功,当时Windows游戏场景几乎为零。克朗代克纸牌游戏是纸牌游戏的一种变体,数学家估计单张发牌的游戏只有43%能获胜,一次发三张牌时该比例急剧下降到18%。
3. 开始编码
作者于2026年2月6日开始编码,花三天用C语言编写主要逻辑,决定使用`curses`库创建纸牌显示界面、使用颜色并添加Unicode字符显示纸牌符号。但游戏第一个版本太大超出竞赛限制,需优化代码,同时要解决选择和放下纸牌的用户界面问题。为符合竞赛空间限制,用户界面大幅简化,使用Tab键选择纸牌,空格键放下纸牌。
4. 学习`curses`的难题
学习`curses`库的过程漫长,它有多个版本,每个Linux和Mac发行版包含的形式不同,且每个操作系统集成的库版本略有差异。另一个问题是纸牌花色需要UTF - 8编码,有些`curses`库不支持。不过作者找到了用于构建方框(纸牌)的字符定义,Unicode也提供了纸牌符号,还能为红色纸牌使用颜色,`curses`可通过统一界面解决相关问题。
5. 优化完善
作者成功实现一次发三张牌的选项,添加了拉斯维加斯计分模式,运行程序时可通过参数选择这些选项。还添加了和Windows中完全一样的计分系统,包括时间奖励。
6. 源代码
经过多次修改和数天开发,作者给出了为curses编写的克朗代克纸牌游戏的源代码。
7. 备注
编译该程序需要`ncurses`库和UTF - 8支持,任何较新的操作系统都可以,如在终端和macOS 12.7.6上测试过。在Fedora 21上,纸牌图形无法显示,需将`-lcurses`链接选项改为`-lcursesw`。在macOS 10.15上测试,安装Homebrew后符号能显示,但无字体包含纸牌边框和背景。在macOS 10.11上,默认的`ncurses v5`不支持UTF - 8,安装Homebrew无法与Github通信。建议将窗口调整为36或40行的终端大小,编译时会产生一些警告。不添加参数运行程序可获得带有Windows计分系统的克朗代克纸牌游戏;添加一个参数使用拉斯维加斯计分模式;添加两个参数使用Windows计分系统且一次发三张牌;添加三个参数使用拉斯维加斯计分系统且一次发三张牌。游戏中可使用Tab键移动光标,空格键选择要移动或放下的纸牌,在左上角按空格键发牌,按Enter键退出游戏。混淆技巧包括用减号运算符代替`!=`,用`>`代替`>=`,用`for`循环节省花括号,随意交换数组和索引位置,用`O`表示常量,加上三元运算符等。
8. 下载
可下载作者参加IOCCC的作品:适用于curses的克朗代克纸牌游戏(6.2kb)。
9. 赛后总结
竞赛结束后,作者发现代码还有可进一步混淆和优化的地方。虽作品未获奖,但作者享受获奖名单现场公布环节,很高兴分享参赛作品,让大家能在文本终端玩克朗代克纸牌游戏。
