求人机五子棋算法

207 2003-05-11 05:45:26
请指点,谢谢!
...全文
58 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
herrycsdn 2003-05-12
  • 打赏
  • 举报
回复
marking
shaolunyuan 2003-05-12
  • 打赏
  • 举报
回复
我也有一个源代码,可以给你

短消息,你的邮箱和你要的东西
Skt32 2003-05-11
  • 打赏
  • 举报
回复
基于人机对战的五子棋游戏


浙江大学计算机系(310027) 胡朝晖

五子棋是一种受大众广泛喜爱的游戏,其规则简单,变化多端,非常富有趣味性和消遣性。这里我们设计和实现了一个人机对下的五子棋程序,采用了博弈树的方法,应用了剪枝和最大最小树原理进行搜索发现最好的下子位置。

本文介绍了我们设计的五子棋程序的数据结构、评分规则、胜负判断方法和搜索算法过程这几个部分。

一、相关的数据结构

关于盘面情况的表示,以链表形式表示当前盘面的情况,目的是可以允许用户进行悔棋、回退等操作。

CList<Step,Step> StepList;

其中Step结构的表示为:

struct Step

{

int m; //m,n表示两个坐标值

int n;

char side; //side表示下子方

};

以数组形式保存当前盘面的情况,目的是为了在显示当前盘面情况时使用:

char FiveArea[FIVE_MAX_LINE][FIVE_MAX_LINE];其中FIVE_MAX_LINE表示盘面最大的行数。

同时由于我们需要在递归搜索的过程中考虑时间和空间有效性,我们只找出就当前情况来说相对比较好的几个盘面,而不是对所有的可下子的位置都进行搜索,这里我们用变量CountList来表示当前搜索中可以选择的所有新的盘面情况对象的集合:

CList<CBoardSituation,CBoardSituation> CountList;

其中类CBoardSituiton为:

class CBoardSituation

{

CList<Step,Step> StepList; //每一步的列表

char FiveArea[FIVE_MAX_LINE][FIVE_MAX_LINE];

struct Step machineStep;

//机器所下的那一步

double value; //该种盘面状态所得到的分数

}

二、评分规则

对于下子的重要性评分,我们需要从六个位置来考虑当前棋局的情况,分别为:图1

实际上我们需要考虑在这六个位置上某一方所形成的子的布局的情况,对于在还没有子的地方落子以后的当前局面的评分,主要是为了说明在这个地方下子的重要性程度,我们设定了一个简单的规则来表示当前棋面对机器方的分数。

基本的规则如下:

1. 判断是否能成5, 如果是机器方的话给予100000分,如果是人方的话给予-100000分;

2. 判断是否能成活4或者是双死4或者是死4活3,如果是机器方的话给予10000分,如果是人方的话给予-10000分;

3. 判断是否已成双活3,如果是机器方的话给予5000分,如果是人方的话给予-5000分

4. 判断是否成死3活3,如果是机器方的话给予1000分,如果是人方的话给予-1000分

5. 判断是否能成死4,如果是机器方的话给予500分,如果是人方的话给予-500分;

6. 判断是否能成单活3,如果是机器方的话给予200分,如果是人方的话给予-200分;

7. 判断是否已成双活2,如果是机器方的话给予100分,如果是人方的话给予-100分;

8. 判断是否能成死3,如果是机器方的话给予50分,如果是人方的话给予-50分;

9. 判断是否能成双活2,如果是机器方的话给予10分,如果是人方的话给予-10分;

10. 判断是否能成活2,如果是机器方的话给予5分,如果是人方的话给予-5分;

11. 判断是否能成死2,如果是机器方的话给予3分,如果是人方的话给予-3分。

实际上我们对当前的局面按照上面的规则的顺序进行比较,如果满足某一条规则的话,就给该局面打分并保存,然后退出规则的匹配。注意这里的规则是根据一般的下棋规律的一个总结,在实际运行的时候,用户可以添加规则和对评分机制加以修正。

三、胜负判断

实际上,我们是根据当前最后一个落子的情况来判断胜负的。实际上我们需要从四个位置判断,以该子为出发点的水平,竖直和两条分别为45度角和135度角的线,我们目的是看在这四个方向是否最后落子的一方构成连续五个的棋子,如果是的话,就表示该盘棋局已经分出胜负。具体见下面的图示:

图2

四、搜索算法实现描述

注意下面的核心的算法中的变量currentBoardSituation,表示当前机器最新的盘面情况, CountList表示第一层子节点可以选择的较好的盘面的集合。核心的算法如下:

void MainDealFunction()

{

value=-MAXINT; //对初始根节点的value赋值

CalSeveralGoodPlace(currentBoardSituation,CountList);

//该函数是根据当前的盘面情况来比较得到比较好的可以考虑的几个盘面的情况,可以根据实际的得分情况选取分数比较高的几个盘面,也就是说我们在第一层节点选择的时候采用贪婪算法,直接找出相对分数比较高的几个点形成第一层节点,目的是为了提高搜索速度和防止堆栈溢出。

pos=CountList.GetHeadPosition();

CBoardSituation* pBoard;

for(i=0;i<CountList.GetCount();i++) //对这些盘面做进一步深度搜索

{

pBoard= CountList.GetNext(pos);

pBoard->value=Search(pBoard,min,value,0);

Value=Select(value,pBoard->value,max); //取value和pBoard->value中大的赋给根节点

}

for(i=0;i<CountList.GetCount();i++)

{

pBoard= CountList.GetNext(pos);

if ( value==pBoard->value) //找出那一个得到最高分的盘面

{

currentBoardSituation=pBoard;

PlayerMode=min; //当前下子方改为人

Break;

}

}

其中对于Search函数的表示如下:实际上核心的算法是一个剪枝过程,其中在这个搜索过程中相关的四个参数为:

(1)当前棋局情况;

(2)当前的下子方,可以是机器(max)或者是人(min);

(3)父节点的值oldValue;

(4)当前的搜索深度depth。

double Search(CBoardSituation& board,int mode,double oldvalue,int depth)

{

CList<Step,Step> m_DeepList;

if(depth<MAX_DEPTH && goal(board)==0)

{

if(mode=max) //实际上判断当前是谁下子,根据不同的下子方,设定初始value值

value=-MAXINT; //设置当前盘面的初始值

else

value=MAXINT; //设置当前盘面的初始值

GetSeveralGoodPlace(m_DeepList); //我们只选择比较好的几个点作为下一个搜索的目标,可以采用贪婪算法得到。

For(i=0;i<m_DeepList.GetCount();i++)

{

//根据m_DeepList中结构Step点的情况和board盘面的情况生成一个新的盘面,这里不妨设为successorBoard

//下面的if条件实际上就是我们判断是否进行剪枝的依据

if (((mode==max&&value<oldvalue)||(mode==min&&value>oldvalue))== TRUE)

{

if(mode==max)

 value=select(value,search(successorBoard,min,value,depth+1),max);

else

 value=select(value,search(successorBoard,max,value,depth+1),min);

}

return value;

}

else

{

if ( goal(board)<>0) //这里goal(board)<>0表示已经可以分出胜负

return goal(board);

else

return evlation(board);

}

}

注意这里的goal(board)函数是用来判断当前盘面是否可以分出胜负,而evlation(board)是对当前的盘面从机器的角度进行打分。

下面是Select函数的介绍,这个函数的主要目的是根据PlayerMode情况,即是机器还是用户来返回节点的应有的值。

double Select(double a,double b,int mode)

{

if(a>b && mode==max)||(a<b && mode==min)

return a;

else

return b;

}

五、小结

我们在Windows操作系统下,用VC++实现了这个人机对战的五子棋程序。和国内许多只是采用规则或者只是采用简单递归而没有剪枝的那些程序相比,在智力上和时间有效性上都要好于这些程序。同时我们所讨论的方法和设计过程为用户设计其他的游戏(如象棋和围棋等)提供了一个参考。

五子棋算法探讨:
http://weiqiang.51.net/a68.html

网络五子棋源代码:
h这是一个五子棋游戏的源代码,界面精美,带背景音乐,其中的许多算法,如搜索算法,也都值得研究! 这是一个五子棋游戏的源代码,界面精美,带背景音乐,其中的许多算法,如搜索算法,也都值得研究!大小:331K
http://www.vckbase.com/code/downcode.asp?id=332
ttp://www.aesa111.com/download/openfile.asp?id=46&filename=code/31.zip
妙手连珠五子棋人工智能源代码 详细信息 < 游戏开发 >

本代码是一个完整的小游戏,界面美观,其中的人工智能算法也很值得参考学习.

http://www.vckbase.com/code/downcode.asp?id=1620

19,468

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 图形处理/算法
社区管理员
  • 图形处理/算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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