十六、 WinHRD的设计
基本组件的编写工作完成后,我们设计一个程序测试一下。在提供的源代码中提供了两个例子。一个是ConsoleHRD(DOS环境下的求解程序),比较简单。另外一个是Windows界面的WinHRD。
我们这里来看看WinHRD的设计:首先主窗口要实现IResultHandler接口以处理华容道组件提供的信息。例如当前搜索到了多少层级,以及求解的结果是什么。用户可以自己单独设计一个实现IResultHandler接口的类来处理这些事情。只要将该类的实例提供给Mediator对象就行了。
![](https://www2.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www2.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www2.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www2.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www2.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](https://www2.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www2.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www2.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www2.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](https://www2.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www2.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www2.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](https://www2.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www2.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www2.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www2.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](https://www2.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
在窗体的初始化代码中初始化各个组件:
![](https://www2.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www2.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www2.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www2.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www2.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www2.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www2.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www2.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www2.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www2.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
为了确保程序的运行效率,我们在单独的线程中运行主处理程序。因此,我们将主要的处理程序封装到一个Process方法中,并将其运行在单独的线程中,线程的优先性设置为BelowNormal,IsBackground设置为true。代码如下(部分简化):
![](https://www2.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www2.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www2.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www2.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www2.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www2.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www2.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www2.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www2.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www2.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www2.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www2.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www2.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
![](https://www2.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www2.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www2.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www2.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www2.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www2.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www2.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www2.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
![](https://www2.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www2.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www2.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www2.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www2.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
至此,我们就完成了客户端的设计。主运算运行在单独的线程中,并可以随时被终止。不会给用户带来任何停滞的感觉。
十七、 性能大比拼
完成了程序的主体工作后,就需要对效率进行一下评价了。我将自己的程序与河北石家庄李智广的"华容道全能版 V1.1"进行了效率对比。在我的机器上(P4 2.0G、512M DDR400内存)得到如下测试结果:
从表中可以看出,在一些比较简单的布局中,"华容道全能版"拥有比较高的运算效率。但当搜索的节点数超过40000时,"华容道全能版"的搜索效率急剧下降。运算时间均在10秒甚至15秒以上。本程序在运算上效率较高,尤其是在复杂布局的求解上也拥有令人满意的效率。究其原因,本人认为有以下几点:
1、本程序将布局转换为4字节整数消耗了过多的CPU时间(需要排序操作),因此为了节省内存而损失了效率。
2、AVLTree带来了良好搜索性能。即使搜索节点超过40000节点,AVLTree也能确保最多在16次比较后就能判断出是否有重复布局(2^16=65532)。
3、种种迹象表明,"华容道全能版"在判断下一步可行走法时,仅仅判断了四种情况:上、下、左、右。而本程序判断了九种情况,除上下左右外还包括上移两步、下移两步、左移两步、右移两步以及转弯(专门针对卒)。因此"华容道全能版"在一步的判断上速度要快很多,但增加了搜索深度(从表中的数据也可以看出来),并且不能正确求得华容道求解的最小步数。
"智能算法爱好者"的结论是:走一格尽管深度增加,但一个递归层的节点宽度比走两格的节点宽度窄了很多,比较的有效节点差不多,但比较的总节点数少了很多,所以走一格比走两格要少很多时间,大约为走两格的70%(用我的同一程序测试),并且只有走两格才能找到最少步数(最优解)。
如果对内存的使用可以放宽松一些的化,我们可以考虑采用其它的方式存储棋盘布局(不再使用4字节表示),这样虽会使AVLTree的构建过程有所减慢,但华容道求解速度会有所提升(不再需要执行排序操作了)。总体来说,对布局搜索速度会有提升(这只是我的猜测,未经验证)。
关于《华容道与数据结构》的内容到此就全部完成。本文中的最终程序代码可以从http://www2.cnblogs.com/Files/zhenyulu/HRD.rar下载。如果时间允许,我会继续完成《华容道与设计模式》,给这个程序添加一个更丰富的客户端界面,允许更好的人机交互,实践并应用一些设计模式在里面。
(全文完)