十四、 CircularLinkedList的设计
CircularLinkedList类是整个程序的核心,所有搜索操作都由CircularLinkedList来触发。CircularLinkedList是一个环形链表,每个链表中的元素都含有下一元素的一个指针,元素与元素链接成封闭的环形。下面是该环型链表的节点定义:





该节点包含一个Layout类型的info,还有一指向下一节点的指针link。CircularLinkedList自身在构造时传入一个ILayoutFactory类型的工厂,用于加工生成Layout(确保环形链表一旦溢出,能够生成新节点元素)。下面是CircularLinkedList的构造函数:










在传入工厂对象的同时初始化四个指针:current、last、allocate与end,除此之外还初始化两个计数器count(用于计算环型链表总共包含多少个节点)与stepCounter(用于计算当前搜索层级,搜索到了第几步)。current、last、allocate三个指针的作用在前面的内容中已经说的很清楚了。这里的end指针是用于防止溢出,记录溢出位置的指针。
分配可用Layout的函数以及确认分配的函数定义如下:





















在这里需要注意的是当分配可用Layout时,注意防止溢出发生。溢出判断的方式是:allocate.link == current,如果相同表明将会发生溢出,这时候需要先插入新节点,然后再分配可用布局。确认分配的动作很简单,就是将allocate指针指向下一节点而已。
插入节点时,首先判断当前环形链表是否为空,如果为空,新节点的下一个节点就是自己本身,单一节点构成一封闭的环。如果环形链表不为空,则在end指针处插入新节点。具体插入操作可以参考下面的代码。
























当某一步搜索完成后,就会进入下一轮搜索,系统重置各指针位置。这是由NextStep方法来实现的:













注意这里调用了中介者的HandleInfo方法,允许外部程序得到当前系统运行状态的一个通知。

另外,如果allocate指针未能分配出任何布局,说明程序运行到此处已经没有任何可行的解了,程序就此终止。否则重置各指针位置并通过中介者通知TreeLinkedList移动current指针。
CircularLinkedList中的核心运算方法就是BeginProcess方法。该方法通过递归调用完成搜索操作。首先对当前层级的每个节点运算可行的下步走法,然后调用NextStep方法继续搜索下一步直至搜索完成或系统判断处棋局无解。期间通过stop属性判断是否终止搜索。我们可以通过CircularLinkedList中的Stop方法随时终止搜索进程。在WinHRD的例子中,通过将搜索放到单独的线程中运行确保不影响主程序,同时也可以让用户随时通过Stop方法终止程序运行。BeginProcess方法与Stop方法的定义如下:

























CircularLinkedList是程序求解的关键部件,我们从上面的递归调用中可以看出求解的思路。在下部分内容中,将介绍中介者Mediator对象。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步