更多 C# 控制台游戏
2020 年 1 月 28 日,我写了一篇文章,《通过控制台游戏学习 C#》。
简而言之:我一直在维护一个GitHub仓库,里面包含开源的C#主机游戏示例,旨在帮助人们以有趣的方式学习C#。:)
当我写第一篇文章的时候,代码库里只有 8 个主机游戏示例。到现在为止,我已经编写了 27 个主机游戏,其中 19 个是在过去两年里新增的。我想写这篇后续文章,重点介绍其中的一些游戏,并分享一些我在编写它们时的想法。:)
请记住,我只是利用业余时间出于兴趣开发这个项目。仓库里的大部分游戏开发时间都不到 10 个小时,不过也有一些例外,我会在下面提到。
注意!本网站的移动版代码块未使用等宽字体,因此本文中的示例图片在移动设备上无法正确显示。在桌面浏览器上则可以正常显示。
驾驶
2021年11月新增
.............. ........................
............... .......................
................ ......................
................. .....................
.................. ....................
................... ...................
.................... ..................
.................... ..................
.................... ..................
.................... ..................
.................... ..................
.................... ..................
.................... ..................
................... ...................
.................. ....................
................. .....................
.................. ....................
................... ...................
.................... ..................
..................... .................
...................... ................
....................... ^ ...............
...................... ................
在这个游戏中,背景向下滚动,你需要^用方向键控制汽车保持在道路上行驶↑, ←, →。
我在制作这款游戏时遇到的一个难题是,游戏本身没有内置方法来检测某个按键是否被按下;没有现成的Console.IsKeyDown(ConsoleKey.LeftArrow)方法。要实现这个功能,就必须深入研究原生库,而我希望在这些游戏示例中避免这样做。因此,我不能简单地让玩家按住←左箭头键时汽车向左移动。我不得不做出妥协,让方向键来↑, ←, →控制汽车的速度,而不是需要一直按住。只需按一下左箭头键←,汽车就会向左转弯。这样就无需不断检测左箭头键是否被按下,因为速度会保持不变,直到按下其他按键为止。
道路是随机生成的。每次背景向下滚动时,顶部都会随机生成一行。道路共有三种类型:
1. 直路
2. 左转
3. 右转。
最初,我尝试将道路随机生成方式平均分配,每种类型出现到下一行的概率为 1/3。然而,这样做通常会导致道路大部分是直的,但边缘参差不齐,玩起来不太有趣。 :D
.................... ..................
................... ...................
.................... ..................
..................... .................
.................... ..................
.................... ..................
..................... .................
.................... ..................
..................... .................
..................... .................
...................... ................
..................... .................
...................... ................
....................... ^ ...............
...................... ................
我是如何解决这个问题的呢?我添加了一个偏差,使得新生成的行有 4/5 的概率与前一行相同。例如,这意味着一旦开始左转,它很可能会在接下来的几行中继续左转。这样就生成了类似驾驶游戏中那样的道路,既有较长的弯道,也有笔直的路段。
Drive在我看来,这款游戏制作起来最简单,玩起来也最有趣。与《X战警》不同Snake,《X战警》的难度始终如一,Drive直到你犯错死亡为止,而《X战警》的难度是逐渐递增的。
角色扮演游戏
2021年10月新增
╔═══════════════════════════════════════════════════════════════════════════════════════════════════╗
║ ║
║ ║
║ /---\ /---\ ║
║ /---\/-Inn-\ _._ /Store\ /---\ ║
║ /-\/-\| | |___| | | /-\/-\ ║
║ \ /\ /| █ | | █ | \ /\ / ║
║ O ║
║ L|( ║
║ | ║
║ ( \ ║
║--\ /---\ /---\ /---\ /---\ /---\ /---\ /--║
║---\ /-----\/-----\ /-----\ /-----\/-----\ /-----\ /---║
║ |#######| || |#######| | | || |#######| |#######| ║
║█ |#######| █ || █ |#######| █ | | █ || █ |#######| █ |#######| █║
║═══╗╔═════╗╔═════╗╔═════╗╔═════╗╔═════╗ |-| |-| |-| ╔═════╗╔═════╗╔═════╗╔═════╗╔═════╗╔═══║
║███║║█████║║█████║║█████║║█████║║█████║ _| |_ _| |_ _| |_ ║█████║║█████║║█████║║█████║║█████║║███║
║███║║█████║║█████║║█████║║█████║║█████║ \ / \ / \ / ║█████║║█████║║█████║║█████║║█████║║███║
║═══╝╚═════╝╚═════╝╚═════╝╚═════╝╚═════╝ \ / \ / \ / ╚═════╝╚═════╝╚═════╝╚═════╝╚═════╝╚═══║
║ ║
╚═══════════════════════════════════════════════════════════════════════════════════════════════════╝
Move: arrow keys or (w, a, s, d)
Check Status: [enter]
Quit: [escape]
这款游戏其实很容易理解……它是一款角色扮演游戏。大多数人想到“文字角色扮演游戏”时,可能会想到那种纯粹的文字问答游戏,比如Where would you like to move (n, s, e, w)?……虽然Role Playing Game严格来说它是一款“文字角色扮演游戏”,但它通过WASD键移动和角色动画(尽管角色动画比较简单)来呈现游戏世界。
Role Playing Game目前这是我添加到代码库中最复杂的游戏。大多数游戏只需 5-10 小时就能Role Playing Game完成编码,而这款游戏却耗时 25-30 小时。幸运的是,我能够复用其他游戏的一些素材,例如《跨栏》(Hurdles)中的角色跑步动画,以及《战士》(Fighter)中的出拳、摔倒、起身和待机动画。
我想在这个游戏中添加的功能之一是根据当前控制台窗口大小进行调整。你可以调整控制台窗口的大小,游戏会自动重新渲染,并将角色置于屏幕中央。当然,这没什么革命性的 :D 但动态屏幕大小在控制台/终端应用程序中使用时会有点奇怪。我不确定这算不算一个 bug,但我在设置 ` or`ArgumentOutOfRangeException时总是会遇到异常,即使我的值完全有效,所以我不得不把它包裹在一个丑陋的 try-catch 语句中。此外, `&` 和 `&` (Visual Studio 调试控制台)之间也存在一些差异。当你在一行末尾写入字符时,它们的行为不同。一个会写入字符并停留在同一行,而另一个会写入字符并跳转到下一行。由于我在每行末尾都使用了 `-`,所以一个控制台会出现空行,而另一个则不会。 :D 不过,一旦我弄清楚发生了什么,这个问题就很容易解决了。Console.BufferHeightConsole.BufferWidthcmd.exeVsDebugConsole.exeConsole.WriteLine()
尽管所有图形都是用 ASCII 字符制作的,但我仍然觉得制作精灵图并用精灵图定义地图很有帮助。游戏包含 3 种不同的地图:城镇、田野和城堡。以下是田野地图目前的定义示例:
public static readonly char[][] Field = new char[][]
{
"mmmpmmmmpmmmmmpmmmmmpmmmmmpmmmpmmmpmmmpmm".ToCharArray(),
"mmpppppppmmmpppmmmpppppmmppmmmpmmmmpppmmm".ToCharArray(),
"mmpmmpmmpmppmmpmpmmpmmpmmmmmmpppmmpmpmmmp".ToCharArray(),
"TTTTTc mpmm cTT m2mcmmpp".ToCharArray(),
"TTTT mm g mmm".ToCharArray(),
"TTT TT mm mpm".ToCharArray(),
"TTT TTT mmmm TT ppm".ToCharArray(),
"www T mm TTT www".ToCharArray(),
"www TT ww T www".ToCharArray(),
"www ww TTT wwwww".ToCharArray(),
"www w0w Tww mmmmmm".ToCharArray(),
"wwww wwwwwww TT cmmmmmmmm".ToCharArray(),
"wwwwwwwwwwwwwwwwwwwwwTTTTTTTTTTTTmmmmmmmm".ToCharArray(),
"wwwwwwwwwwwwwwwwwwwwTTTTTTTTTTTTTTmmmmmmm".ToCharArray(),
"wwwwwwwwwwwwwwwwwwwTTTTTTTTTTTTTTTTmmmmmm".ToCharArray(),
};
每个字符都是一个精灵的 ID。完整列表请查看源代码,但以下是一些字符的含义:W代表水,m代表山,T代表树。
词云
2022年1月新增
╔═══╦═══╦═══╦═══╦═══╗
║ H ║ O ║ U ║ S ║ E ║
╠═══╬═══╬═══╬═══╬═══╣
║ P ║ L ║ A ║ C ║ E ║
╠═══╬═══╬═══╬═══╬═══╣
║ S ║ E ║ A ║ R ║ S ║
╠═══╬═══╬═══╬═══╬═══╣
║ ║ ║ ║ ║ ║
╠═══╬═══╬═══╬═══╬═══╣
║ ║ ║ ║ ║ ║
╠═══╬═══╬═══╬═══╬═══╣
║ ║ ║ ║ ║ ║
╚═══╩═══╩═══╩═══╩═══╝
“Wordle”最近火了,社交媒体上到处都是。我只想说,我讨厌这个游戏。:P 但我还是把它写出来了,因为不写代码太容易了。:D 不过这游戏还是很烂……
吃豆人
2020年12月新增
╔═══════════════════╦═══════════════════╗
║ · · · · · · · · · ║ · · · · · · · · · ║
║ · ╔═╗ · ╔═════╗ · ║ · ╔═════╗ · ╔═╗ · ║
║ + ╚═╝ · ╚═════╝ · ╨ · ╚═════╝ · ╚═╝ + ║
║ · · · · · · · · · · · · · · · · · · · ║
║ · ═══ · ╥ · ══════╦══════ · ╥ · ═══ · ║
║ · · · · ║ · · · · ║ · · · · ║ · · · · ║
╚═════╗ · ╠══════ ╨ ══════╣ · ╔═════╝
║ · ║ ║ · ║
══════╝ · ╨ ╔════---════╗ ╨ · ╚══════
· ║ █ █ █ █ ║ ·
══════╗ · ╥ ║ ║ ╥ · ╔══════
║ · ║ ╚═══════════╝ ║ · ║
║ · ║ READY ║ · ║
╔═════╝ · ╨ ══════╦══════ ╨ · ╚═════╗
║ · · · · · · · · · ║ · · · · · · · · · ║
║ · ══╗ · ═══════ · ╨ · ═══════ · ╔══ · ║
║ + · ║ · · · · · · █ · · · · · · ║ · + ║
╠══ · ╨ · ╥ · ══════╦══════ · ╥ · ╨ · ══╣
║ · · · · ║ · · · · ║ · · · · ║ · · · · ║
║ · ══════╩══════ · ╨ · ══════╩══════ · ║
║ · · · · · · · · · · · · · · · · · · · ║
╚═══════════════════════════════════════╝
PacMan这是一个主机上的吃豆人克隆游戏。收集豆子,躲避幽灵。不过,它并不完全还原原作。我没有研究幽灵的AI,只是自己设计了一些能正常运行的AI。以下是我设计的幽灵AI:
- 幽灵a:使用Dijkstra寻路算法跟随玩家,每6帧更新一次(速度较快)
- 幽灵b:随机移动,每6帧更新一次(速度较快)
- 幽灵c:使用Dijkstra寻路算法跟随玩家,每12帧更新一次(速度较慢)
- 幽灵d:随机移动,每12帧更新一次(速度较慢)
注:本游戏引用了我的NuGet包Towel,因为它包含了Dijkstra寻路算法的通用版本。
在所有游戏中,只有这款游戏真正需要颜色。其他游戏或许可以很容易地不用颜色,但如果没有不同的颜色,吃豆人就无法区分幽灵和吃豆人,而且当吃豆人吃掉较大的豆子时,幽灵还需要变成蓝色+。ConsoleColor枚举值只有 16 种不同的颜色,但幸运的是,到目前为止,我使用这非常有限的调色板已经能够实现所有功能。是的,控制台中有很多方法可以渲染更多颜色,但这些示例旨在为新手开发者提供相对简单的指导,所以如果能用有限的颜色就足够了,我不想把事情搞得太复杂ConsoleColor。
PacMan和大多数其他游戏一样Role Playing Game,开发这款游戏的时间要长一些。我记不清具体的编码时间了,但估计大概花了20个小时。我其实从来都不是吃豆人的粉丝,所以制作这款游戏对我来说并没有那么有趣。:D 但是……我喜欢挑战,所以还是完成了。
曼卡拉
2022年2月新增
╔══════════════════════════════════╗
║ | |[ 8][ 0][ 1][ 0][ 6][ 7]| | ║
║ | | | | ║
║ | 3| | 4| ║
║ | | \/ | | ║
║ | |[ 7][ 1][ 0][ 7][ 2][ 2]| | ║
╚══════════════════════════════════╝
Mancala这是目前代码库中最新的游戏。它是由一位C# Discord 服务器上的用户推荐的。在编写这个游戏之前,我从未玩过 Mancala,所以如果有 Mancala 专家发现我的代码中有任何 bug,请务必告诉我。:D
Mancala编写这个游戏的代码很有趣,因为游戏本身非常简单,但我发现要在控制台中直观地呈现它比想象中要难得多。每次移动,你都会拾取种子,然后逆时针移动,沿途在每个坑里放置一颗种子。如何在控制台中表示这个过程呢?我一开始尝试制作一个简单的逆时针动画,但很快就意识到:“这个动画对学习玩播棋没有任何帮助。” :D 所以,我没有尝试制作花哨的动画,而是直接显示每个坑的图标+X,-X并在每次移动处理完毕后存储起来:
╔══════════════════════════════════╗
║ | |[ 4][ 4][ 4][ 4][ 4][ 4]| | ║
║ | | | | ║
║ | 0| +1| 1| ║
║ | | -4 +1 +1 +1 | | ║
║ | |[ 4][ 4][ 0][ 5][ 5][ 5]| | ║
╚══════════════════════════════════╝
我原以为这是向用户传达游戏体验的最佳方式。但它仍然不够完美,而且我估计,Mancala除非你已经熟悉播棋,否则这可能是整个代码库中最令人困惑的游戏。
战斗机
2020年2月新增
HP █████ ███████████ HP
EN ███████ ███ EN
o
O___. _>)
L( \|
| |
/ >
=================================
我以前从没在主机上见过2D格斗游戏,所以我决定自己做一款,看看能不能做到。它好玩吗?不好玩。:D 但是……嘿……它能玩。所以,你能在主机上制作2D格斗游戏吗?当然可以!
截至撰写本文时,Fighter这绝对是所有游戏中代码质量最差的。代码混乱不堪,到处都是乱码和魔法数字。:P 不用谢。也许有一天我会清理代码,稍微改进一下游戏。但我的目标不是制作3A大作,毕竟这只是个主机/终端。
数独
2020年8月新增
╔═══════╦═══════╦═══════╗
║ 7 6 2 ║ 9 1 5 ║ 8 4 3 ║
║ 5 4 3 ║ 7 8 6 ║ 2 1 9 ║
║ 9 1 8 ║ 2 3 4 ║ 5 7 6 ║
╠═══════╬═══════╬═══════╣
║ 4 3 1 ║ 5 9 8 ║ 7 6 2 ║
║ 6 2 5 ║ 4 7 3 ║ 1 9 8 ║
║ 8 7 9 ║ 1 6 2 ║ 3 5 4 ║
╠═══════╬═══════╬═══════╣
║ 3 9 6 ║ 8 5 1 ║ 4 2 7 ║
║ 1 8 4 ║ 6 2 7 ║ 9 3 5 ║
║ 2 5 7 ║ 3 4 9 ║ 6 8 1 ║
╚═══════╩═══════╩═══════╝
基本符合预期……主机版数独……
结论
如果您对这里的内容感兴趣,或者您认识正在寻找有趣的 C# 入门项目的人,我建议您查看一下这个所有游戏都是开源的仓库:https://github.com/ZacharyPatten/dotnet-console-games。我通常建议初学者先玩玩这些游戏,找到自己喜欢的,然后尝试从头开始编写代码;如果遇到问题,您可以参考现有的示例。
如果您自己制作了主机游戏,并愿意将其添加到代码库中,我将非常欢迎您的贡献。或者,如果您有任何想在主机上看到的游戏创意,欢迎在下方留言或在 GitHub 代码库中发起讨论。:)
我还会制作多少款主机游戏?不知道。:P 不过我有一些想法,所以未来你们应该会看到更多。
感谢阅读。祝您度过美好的一天!
文章来源:https://dev.to/zacharypatten/more-c-console-games-27bg