关于一个人机博弈游戏的算法

Sandycs 2011-08-16 01:03:29
最近工作比较闲空,我就自己写一些东西做研究,我写了一个棋类游戏,目前碰到了困难,想向各位请教一下。

游戏的演示地址:http://u.115.com/file/aq7zi7ig


这个游戏是这样的:
1 有一个9x9=81格子的棋盘。

2 玩家1的棋子位于棋盘从上往下数第一行的正中间,玩家2的棋子位于棋盘最底一行(即第九行)的正中间。

3 游戏规则:先走到对方的底线的玩家获得胜利(比方说,玩家1的目标就是向下走到第9行,而玩家2的目标就是向上走到第1行)

只要走到目标行即可,不管它处于目标行的哪一个单元格内。

4 每个玩家都拥有10块挡板。挡板分为2种,一种为横挡板,一种为竖挡板,每个挡板的长度(或宽度)都是两个单元格。

5 在使用挡板时,不能将对方或自己前往终点的路线堵死。

6 每一步只能选择行棋或者放置挡板中的一种,如果走了棋子就不能放置挡板,放置了挡板就不能行棋。每回合棋子移动一格,每回合最多放置一个挡板。

7 允许两方的棋子在单元格上重叠,互不干扰。

规则大体如上

附件里附上我用VB 6.0写的一个简单人机对战(即Quoridor.rar),用方向键控制棋子移动(控制下方棋子),用鼠标移动、点击来放置挡板。

以上是游戏介绍,下面是我的问题。
这个游戏的算法涉及到两个方面:

1 如何以最快的速度计算出棋子前往目标行的最短路径。与A*算法有所区别的是,该游戏并没有规定一个具体的单元格作为目标点,而是目标行的每一个单元格都有可能成为目标点,我分别用A*算法以及遍历的方法,发现二者速度差别不大(因为A*我必须把目标行上的单元格最短路径全部计算出来,然后再求一个最短值,这本身和遍历已经没有太多区别,甚至会更慢)

2 人机博弈的计算量是相当大的。以该棋子为例,每一步的选择都有很多种(一共有144块挡板的安放方法,还要加上棋子的四个方向),如果电脑需要至少思考3步,则经历的过程是 电脑--人--电脑--人--电脑一共五层递归,每一层都有100来种的可能性,其复杂度就是n的5次方。即使用了剪枝,速度也非常缓慢。

我想了好久,都没有非常有效的加快速度的办法,目前只能通过一个函数来判断哪些挡板有可能会对局势起到作用,以削减每层递归时的计算量,但是减的狠了,电脑就显得很傻,减的少了,速度慢到难以忍受。

在这个计算里,我测试寻找最短路径最多需要0.4ms,如果一个人对电脑行棋的时间忍受为20秒,这意味着电脑最多只能进行50000次循环,但是50000次循环无疑太少了,电脑根本还想不出太多有意义的步子来。


请教各位算法达人,对于这样的游戏,如何进行有效的算法分析?
...全文
358 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
never517 2011-08-31
  • 打赏
  • 举报
回复
额,玩着玩着内存错误了
fourinone 2011-08-29
  • 打赏
  • 举报
回复
等待揭晓,占个位
Sandycs 2011-08-24
  • 打赏
  • 举报
回复
顶一手
Sandycs 2011-08-18
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 lingrushikong 的回复:]

不知道棋子能不能向后走,也就是后退一步,假设不可以,那么竖放木板是没有意义的,只考虑横放,ok;
[/Quote]
棋子可以向四个方向走
福来哥 2011-08-16
  • 打赏
  • 举报
回复
玩了一下,游戏相当有难度,优化方案如下:
1,已放挡板的位置不要在计算。
2,有些挡板之间空一个格子的,应该是不能放的,也要除掉。
3,挡板优先放在对方棋子的周围。
4,挡板安放策略:在对方棋子距离终点的最短路径之间进行安放。
Sandycs 2011-08-16
  • 打赏
  • 举报
回复
不会必胜的
fire_woods 2011-08-16
  • 打赏
  • 举报
回复
先下必胜, over.
Jokul_Lee 2011-08-16
  • 打赏
  • 举报
回复
支持原创
Sandycs 2011-08-16
  • 打赏
  • 举报
回复
自己顶起来
花生壳 2011-08-16
  • 打赏
  • 举报
回复
不知道棋子能不能向后走,也就是后退一步,假设不可以,那么竖放木板是没有意义的,只考虑横放,ok;

tangxianghenggood 2011-08-16
  • 打赏
  • 举报
回复
永不止步 因你而犀利
fire_woods 2011-08-16
  • 打赏
  • 举报
回复
有道理
oo 2011-08-16
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 fire_woods 的回复:]
先下的往对方正前方走一步, 也就是到第二行的中间位置.
然后把棋盘变成8*9的样子, 以中心点对称原则和对方下棋即可, 等对方到你的第二行的位置的时候, 你就到对方的底线了.
如果对方没办法到达你的第二行, 那么肯定到不了你的底线.

所以从这个角度讲, 先下的永远也不会输.
剩下的, 只要抓住一个保证能赢的机会即可, 比如大家都把挡板用光了.
[/Quote]


用对称的方法可能不是一定奏效,因为有一条规定:不能把所有的路堵死
后手方可以设计在放下某个挡板后,使先手放的路径比后手方长很多,同时先手方在对称位置放挡板时会堵住后手方所有的路,这样先手方可能会输掉。

这种博弈肯定是先手必胜或后手必胜的,关键是如果够复杂目前无法找到必胜方法而已。
超级大笨狼 2011-08-16
  • 打赏
  • 举报
回复
数据结构采用位运算试试。
试试大整数。
fire_woods 2011-08-16
  • 打赏
  • 举报
回复
先下的往对方正前方走一步, 也就是到第二行的中间位置.
然后把棋盘变成8*9的样子, 以中心点对称原则和对方下棋即可, 等对方到你的第二行的位置的时候, 你就到对方的底线了.
如果对方没办法到达你的第二行, 那么肯定到不了你的底线.

所以从这个角度讲, 先下的永远也不会输.
剩下的, 只要抓住一个保证能赢的机会即可, 比如大家都把挡板用光了.
Sandycs 2011-08-16
  • 打赏
  • 举报
回复
楼上的,你说的这四点我都考虑在内了
并且还延展出去了

如果仅仅考虑这四点几乎是无法获胜的
因为有很多步子就必须在很想象不到的地方走出来(比如离现有棋子较远,不在对方的最短路径上等)

33,008

社区成员

发帖
与我相关
我的任务
社区描述
数据结构与算法相关内容讨论专区
社区管理员
  • 数据结构与算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧