华容道算法设计

Author:L.T.Dreamy
2007-10-5
 
1引言
华容道游戏是古老的中国传统益智游戏,以其变化多端百玩不厌的特点,与魔方独立钻石棋一起被国外智力专家并称为智力游戏界的三个不可思议。日本藤村幸三朗曾在《数理科学》杂志上发表华容道基本布局的最少步法为85步。后来清水达雄找出更少的步法为83步。美国著名数学家马丁·加德纳又进一步把它减少为81步。此后,至今还未曾见到打破这一记录的报道。而对解题效率的提升,则有数学家指出,此问题单靠数学方法很难求解。
华容道游戏的棋盘是由20个小正方形组成的长方形宽4 格长5 格,共有10 个棋子。其中五个棋子为张飞,赵云,马超,黄忠和关羽等。五虎将每个棋子占两格,可以是横的,也可以是竖的。四个棋子为刘备兵,各占一格。另一个棋子为曹操,占四格形状为正方形。棋盘的下部有两个空置的小格,作为华容道的出口。棋盘上仅有两个小方格,空着玩法就是通过棋子在这个长方形的棋盘内滑动,用最少的步数把曹操移出华容道.
 
2分析
对于像华容道、七巧板之类的滑块游戏来说,一般都是利用搜索解空间的方式获得可行的走步,象棋和围棋已然如此,只不过可以在可以在比较复杂的游戏中添加开局图和残局图也就是以前已有的走步历史,那么可以在搜索的过程中利用这些已有的结果,可以大大缩短解空间的个数和解题时间,对于华容道来说,广度优先的解空间搜索已经满足要求了,不需要添加历史棋局。
广度优先搜索大家都会,而且有一定的套路,下面是其伪代码:
 
Procedure 广度搜索(){
展开首节点得所有儿子节点,加入到处理队列中
While(队列不空){
  取出队列头节点;
  For(取出的节点的所有可能情况){
    将新产生节点加入到队列中;
  }
}
}
但是就华容道来说,需要解决一些问题。
1 搜索的解空间比较巨大,如何存储和编码棋盘棋局
2 如何快速在已存的棋盘格局中搜索探测是否新产生的棋局在以前已经产生
以最常见的布局:“立马横刀”为例,讲解华容道算法的设计和实现。见下图。
因为对于除关羽以外的其它四位五虎将都是竖立的,我们去掉其身份信息,只是表明其为V兵(竖着),而关羽因为是横着的,所以命名H兵,曹操直接C兵,其他普通兵则为S兵,空格为B(blank),而且都以每个兵在棋盘中的左上角的坐标来标识,而这个兵所占的其余部分设置为‘0’。这样,上图中的格局可以表示为
因为在虚走步的过程中会产生很多的重复步骤,即以前出现过的棋盘格局,所以每次产生新的棋盘格局之后需要对向前查找,看是否有跟当前棋盘格局一样的格局,如果有,则这个新产生的格局不加入到将要处理的队列中。
前人已有利用AVL平衡树和哈希表结构来处理重复节点搜索的,我们这里也是利用hash链表,只不过做了细微的变化。
下图是整个华容道算法的核心数据结构-用于存放棋盘格局
 
需要解释一下:所有节点都根据棋盘格局数据进行哈希得出其对应的哈希表中的桶,然后探测这一桶中是否有相同的棋盘格局,如果没有则添加到这个hash链的最后,并且,将其加入到队列的链表尾,同时其parent父节点域指向生成这个新格局的棋局节点处.整个网结构中有3种主要的结构,1队列,用于广度优先搜索,2hash链表,用于快速搜索[几乎是O(1)时间复杂度]重复节点,3父节点指针,用于最后生成解节点后,回溯输出整个华容道的走步(移动).[表中有点乱,而且不能追究其对与否,只是一个示意图]
 
3 数据结构
记录棋盘格局节点的数据结构:
struct GridNode {
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值