话接上一回,Sumtec带着他写好了的那些代码,以及没有完成想法,还有那一块Frank和Sumtec都写了东西的白板,去找Jack了……
Sumtec:Hi,Jack!
Jack:Hi!找我有事吗?
Sumtec:是的,我有一些事情要请教你。(把上一回的事情说了一遍)
Jack:嗯,你的算法没有问题,很好。不过结构方面的问题,Frank说的是有道理的。他问得那几个问题,比如换一种算法等等,这些都是你的想法所无法解决的。
Sumtec:可是我觉得他的想法也有问题,按他那样写,程序能够运行起来吗?
Jack:其实是可以的。(Jack把那堆代码输入进去,然后生成了一大堆的空的类和函数,接着马上按F5)
Sumtec:这也算啊!?
Jack:对啊,Frank的职责就是负责一个项目总体方面的东西,你这么写当然没有什么结果,可是毕竟可以运行了。你如果注意的话,Frank并没有要求你能够求解,只是想知道你打算怎么去做,所以我这么写至少今天是能够让Frank满意的。
Sumtec:嗯,好吧,可是我的那个方法也可以照你这么去做啊?那Frank为什么不满意呢?
Jack:你说的没错,也可以这么来。但是这里面有很多问题,我一条条给你数。首先,Frank问你的那三个问题你是不知道怎么回答对不对?
Sumtec:这个确实不知道怎么办,不过我认为一定有办法的。
Jack:没错,确实有办法。但是,第二,你能够告诉我听,你的想法里面,各种职责,或者说是概念体现在哪里?比如说,游戏在哪里?
Sumtec:我认为我这整个的就是一个华容道的游戏。
Jack:你这么说也可以,但是至少你看,你没有封装起来。Frank要的是一个游戏,但是你给他的却是游戏里面的东西,他不关心这个。
Sumtec:哦,我懂了。
Jack:第三,这个我说之前得先问你一下,你打算怎么实现这个算法的细节,嗯,比如说如何判断这个“曹操”可以往哪里走?或者你打算在什么地方判断这盘棋赢了?
Sumtec:(这段话看看大意就好了,小心晕乎)是这样的,我这个Resolve函数将会调用MyTreeQueueCollection里面的一个xxx,然后这里面会调用它里面所包含的一个单链表里面的xxx函数,而这个函数则调用一个中间处理器,中间处理器遍历每一个棋子,然后调用每一个棋子的CanMoveUp,CanMoveDown,等函数,这样就完成了你说的“可以往哪里走的问题”,当然了,一个棋局是否已经有解得判断也在这里面,就是在曹操这个派生出来的CaocaoChess类的各个CanMove函数里面判断一下,如果胜利则改变自己的一个属性值,这样最后MyTreeQueueCollection就能够知道已经有解了。
Jack:也就是说,你打算把这些东西写在棋子里面吗?
Sumtec:正是这样。
Jack:假设你已经写好了这个程序,但是突然有一天,Frank想改一下游戏规则:斜着走是允许的;增加一个L形的棋种;另外曹操在到达底部中央的时候,周围不允许有两个以上的大子——就是占超过一个棋格的大子,才能够算是赢了。你会不会觉得很麻烦?
Sumtec:当然麻烦啦,那得改多少地方啊。
Jack:对啊,多麻烦啊!问题出在哪里呢?问题就在于一开始我问的两个问题,他不属于棋子的职责范围,你把这些职责强加到棋子的身上,就会出问题。我举一个例子:比如说中国象棋,我们平常玩中国象棋马走日象走田,那是一种玩法。但是还有一种“盲公棋”,一开始棋面向下,棋子要翻出来才能够走,而且所有棋子都一格一格的走,比大小吃子,被吃光了就算输。这种玩法听说过吗?
Sumtec:听说过,我小的时候经常玩。
Jack:你觉得对于这两种玩法来说,棋子变了吗?
Sumtec:好像没有。
Jack:也就是说这两种玩法,棋子是没有变化的,但是规则变了。或者说,规则变了棋子不一定变,两者并不是一回事。
Sumtec:哦!我明白了,也就是还应该有一个规则这样的东西对吗?
Jack:嗯,没错。这就是第三点,你只关心了最基本的数据结构,而没有更上面一层的职责。当你试图直接将最基本的数据结构组装成应用程序,就很可能将一些职责塞到不合适的地方去了。比如说某个数据结构里面,其实这并不是这个数据结构本身应该有的东西,这样做会引起很多问题的。
Sumtec:哦,那你看是不是这个意思:
HrdGame game = new HrdGame();
Layout startLayout = HrdLayoutFactory.Create("HRD1");
Player computer = HrdAlgorithmFactory.Create("Sumtec");
HrdRule rule = new HrdRule();
game.Rule = rule;
game.InitializeLayout(startLayout);
game.AddPlayer(computer);
game.Play();
PrintGameResult(game.Records);
Jack:嗯,差不多就是这个意思。不过还有一个小的概念,也许需要跟你说一下。
Sumtec:什么概念呢?
(待续)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器