五子棋算法详解

五子棋算法详解
五子棋算法详解

五子棋算法详解——解决方案之一

这里讲述棋盘大小为10×10的人机对战五子棋实现方法,要看完整代码请看AS3做的五子棋

1. 概述

玩家每走一步,对于玩家和计算机,都根据获胜表对棋盘各个空棋位进行评分,每个位置的分数与下面这句话有关:该位置所在的每一种获胜组合中已经拥有的棋子数,然后对玩家和计算机产生的分数均衡,以判断计算机是进攻还是防守。

2. 数据结构

10×10的数据,用来记录棋盘状态;

两个获胜表([10][10][192]),也就是获胜组合,因为五个子一线则胜,不在一线上的五个子就不在一个组合中,对于10×10的棋盘获胜的组合有192种,下面将会详细说明,获胜表用来表示棋盘上的每个位置是否在玩家或计算机的获胜组合中;

一个二维数组([2][192]),记录玩家与计算机在各种获胜组合中填入了多少棋子;

两个10×10的数组,用来记录玩家与计算机在各个棋盘位置上的分数,分数高的将是计算机下一步的着法。

3. 计算获胜组合

上图是一个10×10的五子棋棋盘,我们可以得出垂直方向上的获胜组合是

10×6=60,同理,水平方向的获胜组合也是60,而两个倾斜方向上的获胜组合是(1+2+3+4+5)×2+6=36,即:

60*2+36*2=192。

五子棋算法详解本文链

接:https://www.360docs.net/doc/583819942.html,/wwwanq/blog/item/66a9f4c5f390cdc338db497f.htm l

4. 评分

用两个数组存储每个棋位的分数,一个是计算机的,另一个是玩家的,表示该位置对于各方是最佳着法的肯定程度,对一个位置的评分就是:遍历该位置所在的每一种获胜组合,根据这个组合中已经拥有的己方棋子数1到4分别加不同分数,最后将这些所有的获胜组合所得出的分数相加就是该位置的分数,下图是对于黑方各棋位的评分(其中的1,2,3,4这几个值要根据实际需要来确定)。

5. 思路

“五子棋”游戏的编程思路

1、对棋盘上无子点进行分值评定,分值最高的点即为下一手棋的落点

2、每一点有四个方向(横、竖、斜、斜)成五子可能,(4)

3、每点在一个方向可以有五种呈五子排列形状(5)

4、每点在每个方向有进攻和防守两个作用(2)

5、具体量化确定如:

每种情况,如:

进攻:有1子(+1)、2子(+5)、三子(+25)

防守:有1子(+1)、2子(+4)、三子(+16)

(每次量化,如果五格中有对方子,该过程进攻分值为零,

每次量化,如果五格中有己方子,该过程防守分值为零,)

将每点的20次进攻和20次防守的分值相加,即为该点总分值

按照这个思路编制的五子棋,有可能你自己都会输给机器

当然,在具体编制过程时,还要考虑中心点分值稍高;已经有四子(对方和己方)的情况;六子情况;出界;对与最高分接近的点进行随机取点,以便程序具有随机性;以及已成五子等情况。

在以上程序编制完成后,还可考虑以下情况,以便对编程思路进行细加工,

1,每个方向分值是否是进攻和防守分值的简单相加

2,各个方向的分值是否是简单相加关系

3,是否应考虑对具体形状的配合,给出组合分值

4,以上都是固定直线型思路,是否应考虑蓄势待发情况,

任何一种棋类游戏其关键是对当前棋局是否有正确的评分,评分越准确则电脑的AI越

高。五子棋游戏也是

如此,但在打分之前,我们先扫描整个棋盘,把每个空位从八个方向上的棋型填入数

gStyle(2, 15, 15, 8, 2),其中第一个下标为1时表示黑棋,为2时表示白棋,第

二和第三个下标表示(x,y)

第四个下标表示8个方向,最后一个下标为1时表示棋子数,为2时表示空格数,如:

gStyle(1,2,2,1,1)=3表示与坐标(2,2)在第1个方向上相邻的黑棋棋子数为3 gstyle(1,2,2,1,2)=4表示与坐标(2,2)在第1个方向上的最近的空格数为4

在定义方向时,也应该注意一定的技巧,表示两个相反的方向的数应该差4,在程序中我是这样定义的:

Const DIR_UP = 1

Const DIR_UPRIGHT = 2

Const DIR_RIGHT = 3

Const DIR_RIGHTDOWN = 4

Const DIR_DOWN = 5

Const DIR_DOWNLEFT = 6

Const DIR_LEFT = 7

Const DIR_LEFTUP = 8

这样我们前四个方向可以通过加四得到另一个方向的值。如果你还是不太明白,请看下面的图:

---------

---------

---oo----

-ox*xx---

---------

---------

图中的*点从标为(4,4),(打*的位置是空位),则:

gStyle(2,4,4,1,1)=1在(4,4)点相邻的上方白棋数为1

gStyle(2,4,4,1,2)=2在(4,4)点的上方距上方白棋最近的空格数为2

gStyle(1,4,4,3,1)=2在(4,4)点相邻的右方黑棋数为2

gStyle(1,4,4,3,2)=1在(4,4)点的右方距右方黑棋最近的空格数为3

...

一旦把所有空点的棋型值填完,我们很容易地得出黑棋水平方向上点(4,4)的价值,

由一个冲1(我把有界的棋称为冲)

和活2(两边无界的棋称为活)组成的。对于而白棋在垂直方向上点(4,4)的价值是一个活1,而在/方向也是活1

所以,只要我们把该点的对于黑棋和白棋的价值算出来,然后我们就取棋盘上各个空点的这两个值的和的最大一点

作为下棋的点。

然而,对各种棋型应该取什么值呢?我们可以先作如下假设:

Fn 表示先手n个棋子的活棋型,如:F4表示先手活四

Fn'表示先手n个棋子的冲棋型,如:F4'表示先手冲四

Ln 表示后手n个棋子的活棋型,如:L3表示后手活三

Ln'表示后手n个棋子的冲棋型,如:L3'表示后手冲三

.

.

.

根据在一行中的棋型分析,得到如下关系:

L1'<=F1'

从这个关系包含了进攻和防守的关系(当然,这个关系是由我定的,你可以自己定义这些关系)。对这些

关系再进一步细化,如在一个可下棋的点,其四个方向上都有活三,也比不上一个冲四,所以我们可以又得到

4*F3

和我的定法制可能不一样,这样计算机的AI也就不一样,最后我们把分值最小的L1 '值定为1,则我们就得到了

下面各种棋型的分值,由C语言表示为:

F[2][5]={{0,2,5,50,16000},{0,10,30,750,16000}};

L[2][5]={{0,1,5,50,3750},{0,10,30,150,4000}};

F数组表示先手,第一个下标为0时表示冲型,第二个下标表示棋子数,则F2'对应F

[0][2]

L数组表示后手,第一个下标为0时表示冲型,第二个下标表示棋子数,则L2对应F

[1][2]

Ok,棋型的分值关系确定好了以后,我们把每一个可下点的四个方向的棋型值相加(包

括先手和后手的分

值),最后选择一个最大值,并把这一点作为计算机要下的点就OK了:)。

后话:

1、得到最大值也许不止一个点,但在我的程序中只选择第一个最大点,当然你可以

用于个随机数来决定

选择那一个最大值点,也可以对这些最大值点再作进一步的分析。

2、在这个算法中我只考虑了周围有棋子的点,而其它点我没有考虑。

3、可以再更进一步,用这个算法来预测以后的几步棋,再选择预测值最好的一步,

这样电脑的AI就更高了

4、这个算法没有考虑黑棋的禁手(双3、双四和多于五子的连棋)。因为在平时我下

的五子棋是没有这些

禁手的。

“人工智能”即指让机器具有类似人类一样的主观能动性根据当前情况做出相应的判断,而他的核心便是具体的数学算法。然而这个算法其实就是依托在一个人造的数学模型上。具体简单的说,就像本文介绍的五子棋,我们根据五子棋的具体规则建立适当的数学模型,只要机器按照此模型进行逻辑判断就可以得出一定的结果,而这个结果在我们人类看来就是机器在下棋的过程中攻守兼备,仿佛具有人类的智慧。说到这里,我们就这话题再探讨一点。“人工智能”的终极目标就是使机器具备人类的情感,而这个目标有可能实现吗?鄙人的看法是绝对可以的,只是时间的问题。计算机科学从来不是一门独立的学科,他是人类文明的一个结晶。众学科的综合造就了他,而他也必将超越我们人类。从生物学角度来看,我们人脑就是有机化合体组成的神经网络;从化学角度来看,我们人脑的化学反应产生的神经脉冲为我们的逻辑运算提供动力;而从数学角度上看,我们人脑神经所以组成的网络正是一个复杂包罗万像的数学模型。正是在这样一个宇宙的式的数学模型上的逻辑推理,使人类具备了情感。然而我们人类目前对自身大脑的工作原理认识

还处在超低级的阶段,有朝一日人类能更深入的了解我们自身那根据这些知识再将其运用在计算机学科,机器也一定能实现真正的“人工智能”。

有了上面的介绍,我想大家一定对本文所讨论的深度有了了解。没错,我们接下来讨论的的确是最初级的智能算法。那么大家在阅读的过程中应该注意的不是这个算法的具体实现,而是根据五子棋规则建立数学模型的这个过程。即从现实抽象到数学模型的能力,而这个也是编程能力的本质。

规则:分黑白两方,轮流下棋。率先将5子连线的一方获胜。

目标:使机器在下棋的过程中攻守兼备,就像和一个真正的人类下棋一样

分析:为了方便说明我们以5X5 这个最简单的棋盘来加以说明。

棋盘如图所示:

接下来我们就五子棋的具体规则特点和人类思维过程讨论一下。率先将5子连线的一方获胜,那么我们人类在下棋的过程中每下一步前都会思考一下如果我们这样走了后面会出现一个什么样的情况?走了这步后对方会走哪步?如果对方做了这步后会是个什么样的局面,我可以采取哪些走法?......

如此这般,从上面我们可以看到我们人类在下棋过程中经历了预见,推理,预见,推理......这样一个反复的过程,然而我们人脑能力有限,我们能预见的步数和记住每步的情况的能力有限制,即使再聪明的人也是有个限度的。而机器在记忆这方面却是绝对的,所以我们可以模拟人下棋的过程使机器具备高超的下棋能力。

说到这里,也许有朋友会提出:看样子你这就是个深度搜索算法啊。理论上来说深度搜索算法可以解决任何一个问题,可是事实是有的问题在理论上有解而在现实中却是无解,无法证明的。比如牛顿三大定律之一:力是改变物体运动状态的原因。直白的说比如在真空中一个物体背向地球匀速离去,只要没有力作用在它上面它将永远这样运动下去远离地球。然而事实上没有人能看到这个结果,因为没人能活到永远。再比如用深度搜索算法来解决围棋问题,那他的深度搜索步数将是我们现在人类所认知宇宙整个质量原子数的总和,所以有这么一句话,一盘围棋就是一个宇宙。那面对这样一个宇量计算量我们现有的计算机技术利用深度搜索是无法得到结果的,而且很可能永远得不到结果,因为利用计算机做这样的事这个命题本身就成为一个理论上有结果却无法得到证实的真命题了。

所以,我们要根据具体情况采用特殊算法巧妙的避免陷入不必要的无解路径。就以本文讨论的五子棋来说,由于其规则的特点,其实用深度搜索算法也能解决问题,但我们旨在建立一个更科学合理的模型来达到更好的效果。所以我们可以先将需要搜索的步数量化,以实现程序的高速查询,也就是说建立一张特殊的“表”,其中标明了获胜的所有情况。那么剩下的事就是实时查询这张表来作为下一步的依据。

就以上面所说,我们采用5X5 的棋盘,其获胜的情况总共有12种,具体情况如下所示:

我们可以将以上获胜情况做成列表:

情况坐标

0 (0,0) (1,0) (2,0) (3,0) (4,0) 横向

1 (0,1) (1,1) (2,1) (3,1) (4,1)

2 (0,2) (1,2) (2,2) (3,2) (4,2)

3 (0,3) (1,3) (2,3) (3,3) (4,3)

4 (0,4) (1,4) (2,4) (3,4) (4,4)

5 (0,0) (0,1) (0,2) (0,3) (0,4) 纵向

6 (1,0) (1,1) (1,2) (1,3) (1,4)

7 (2,0) (2,1) (2,2) (2,3) (2,4)

8 (3,0) (3,1) (3,2) (3,3) (3,4)

9 (4,0) (4,1) (4,2) (4,3) (4,4)

10 (0,0) (1,1) (2,2) (3,3) (4,4) 交叉

11 (4,0) (3,1) (2,2) (1,3) (0,4)

由此我们可以看到,由于五子棋规则的特殊性,在即定规格的棋盘上我们可以事先获得获胜的情况,那接下来我们就考虑怎么很好的利用它。

那么我们在下棋过程中,是怎么来考虑当前应该下在哪个格子呢?一般来说就是:

(1) 看双方哪些格子可以同时拥有多种获胜方式,获胜方式越多越具优势。

(2) 比较双方最具优势的格子,若对方最具优势格子比自己的的更具优势,便把棋子下到对方最具优势的格子,这样体现了防守。否则,便把棋子下到自己最具优势的格子,这样体现了进攻。

说到这里,我想要大家都悟到一点门到啦,我们的数学模型雏形基本出来,以上两条可以说就是五子棋规则到编程的抽象。好了,我们具体来看看。以我们5X5 的棋盘,除了 2 条对角的格子有3 种获胜方式,中心点有 4 种获胜方式(以(0,0) 点举例:即有0, 5, 10三种获胜方式),其余格子只有两种获胜方式。那么剩下的重点就是构造一个评价函数来决定机器是防还是攻。接下来我们加以简单的代码来说明我们这个简单的“人工智能”具体怎么运作。

首先,我们先来建立获胜表:

typedef struct

{

UINT8 last; /* 0标记该获胜方式失效*/

UINT16 x[5];

UINT16 Y[5];

} WLIST;

WLIST WinListP[12]; /* 人的获胜表*/

WLIST WinListC[12]; /* 机器的获胜表*/

如WinListC[12] 记录了上文的12 种获胜方式,我们以WinListC[0]加以说明:

WinListC[0].last = 1; /* 1表示获胜方式有效,0无效*/

WinListC[0].x[0] = 0; /* 与上表的情况0对应,入录坐标*/

WinListC[0].y[0] = 0;

.

WinListC[0].x[4] = 4;

WinListC[0].y[4] = 0;

按照此法我们将WinListC[0]--WinListC[11] 都与上表12种获胜情况一一对应入录好坐标,当然WinListP 也与WinListC 一样。下面我们看获胜表是怎么发生作用的。

(1) 比如人把棋子下在(1, 1) 处,那么对于机器来说,所有需要(1, 1) 组合的获胜情况都将失效。即上表中拥有(1, 1) 的1, 6, 10情况将失效,对应的WinListC[1].last = WinListC[6].last = WinListC[10].last = 0;

(2) 机器在下棋时,首先扫描棋盘上所有空出的格子,并根据获胜表给每个空格打分。即有1种获胜方式

就给加1分,并调出得分最高的空格作为即将下的位置。同样要计算人情况,得到打分最高的空格。若人得分最高空格比机器的高,那机器就把棋子下在人的得分最高空格上,否则就将棋子下在自己得分最高空格上。

看,这样就把前面的数学模型具体化在代码中了。具体代码可以这样:

UINT8 Chessboard[5][5]; /* 记录棋盘落子情况,1为人,2为机器*/

UINT16 ScoreP[5][5]; /* 用于人方每次给空格打分*/

UINT16 ScoreC[5][5]; /* 用于机器方每次给空格打分*/

我们还是举例来说明目前的代码在程序中是如何发生作用的:

1. 还是假如人在(1, 1) 处落子。

2. 先标记棋盘落子情况,Chessboard[1][1] = 1;然后修改机器方的获胜表,即需(1, 1) 组合的1, 6, 10这3种获胜方式将失效,WinListC[1].last = WinListC[6].last = WinListC[10].last = 0;具体搜查哪些获胜方式将失效代码如下:

SitX = 1; /* 记录如上假设的落子(1, 1) 处*/

SitY = 1;

for (i = 0; i < 12; i++)

{

for (j = 0; j < 5; j++)

{

/* 历遍0-11情况,发现含(1,1)处即标为失效*/

if (WinListC[i].x[j] == SitX && WinListC[i].y[j] == SitY)

{

WinListC[i].last = 0;

break;

}

}

}

3. 根据WinListC获胜表,对ScoreC打分。同样根据WinListP表给ScoreP打分,具体代码如下:

for (i = 0; i < 5; i++)

{

for (j = 0; j < 5; j++)

{

ScoreC[i][j] = 0; /* 初始化人,机器评分表*/

ScoreP[i][j] = 0;

if (Chessboard[i][j] == 0) /* 为空格*/

{

for (k = 0; k < 12; k++)

{

if (WinListC[k].last == 1) /* 机器方各空格评分*/

{

for (m = 0; m > 5; m++)

{

if (WinListC[k].x[m] == j && WinListC[k].y[m] == i)

{

ScoreC[i][j]++;

break;

}

}

}

if (WinListP[k].last == 1) /* 人方各空格评分*/

{

for (m = 0; m > 5; m++)

{

if (WinListP[k].x[m] == j && WinListP[k].y[m] == i)

{

ScoreP[i][j]++;

break;

}

}

}

}

}

}

}

经过以上处理,ScoreC,ScoreP将被评上分,而就以上面的举例来说,他们的值如下:

ScoreC[5][5] 2, 1, 2, 2, 3

1, 0, 2, 3, 2

2, 1, 3, 2, 2

2, 1, 2, 2, 2

3, 2, 2, 2, 2

由上可见,机器方的得分最高也就是3。那么我们在看看人方:

ScoreP[5][5] 3, 2, 2, 2, 3

2, 0, 2, 3, 2

2, 2, 4, 2, 2

2, 3, 2, 3, 2

3, 2, 2, 2, 3

可见人方得分最高为中心格的4,比机器方的3要高。按照我们上面所描述的规则,那么机器将把棋子落在棋盘的中心以消除对手最具优势的空格,此时体现了防守。

如果再往下走,等待人方落子后,机器方将继续按照上述步骤:标记棋盘落子情况;修改获胜表;历遍棋盘给双方打分,按规则下棋。这样我们所讨论的“人工智能”五子棋人机对战就完成了。

当然,细心的朋友也许会发现,我们前面所讨论的模型存在一个缺陷,那就无论哪方有3,4连子时,机器无法识别。而这个问题其实很好解决。我们可以构造一个查询连子的函数,当发现连子时就不再加1分,而是加2分或3分,这样就可以避免当发生连子时机器错过防守或进攻的机会。关于这个加强算法就不再文中详细在说明。

方法1:只是告诉大家可以就在以上介绍的基础上额外再构造一个判断连子的加强算法。

方法2:当然也可以改造前面提到的获胜表结构WLIST,增加一个储存是否落子的数组,这样判断连子就可以直接具体到某种获胜方式是否有连子。简单介绍一下代码:

typedef struct

{

UINT8 last; /* 0标记该获胜方式失效*/

UINT8 yn[5]; /* 记录是否落子,1为落子,0为空*/

UINT16 x[5];

UINT16 Y[5];

} WLIST;

那么在上述例子当人方在(1, 1) 处落子,除了标明棋盘落子情况Chessboard[1][1] = 1;外还必须将人方获胜表12种情况中坐标于(1, 1)对应的yn[1] = 1 标记为1。参考代码:

SitX = 1; /* 记录如上假设的落子(1, 1) 处*/

SitY = 1;

for (i = 0; i < 12; i++)

{

for (j = 0; j < 5; j++)

{

/* 历遍0-11情况,标记各(1,1)处*/

if (WinListP[i].x[j] == SitX && WinListP[i].y[j] == SitY)

{

WinListP[i].yn[j] = 1;

break;

}

}

}

同样,当机器落子后也要把落子处记录在WinListC[].yn[] 中,这样在后面检查连子时,就可以直接查看WinListC[].yn[0]--WinListC [].yn[4] 来确定是否有连子。

这里要说明一点,之所以只是在后面简单的提连子加强算法,是为了保持前面的简要与明朗性。只要大家把前面主体的数学模型构造看明白了,那自然而然的就会领悟到前面数学模型的缺陷。这样,在来理解后面的加强算法就很简单了。如果不这样安排,我不确定我是否能把主体数学模型和连子加强算法在一起说明白。

不过,说实在的我也不知道我的这篇文章是否把构造这样一个五子棋人机对战模型给说清楚,要是在下写的烂那也只好靠各位多看看自己再思索思索吧。

总结:本文的意图并不是单单介绍五子棋人机对战算法,而是想突出从现实到抽象的过程。也不知道实现这个目的了不,要是各位觉得我写的不好,那也只能请大家多多包涵啦。而我只能继续加强自己的写作水平。

五子棋贪心算法

五子棋人机对战算法 采用的是贪心算法 每一步扫描一下棋盘上未有子的地方 我假定落下一个子,我去判断一下这个子,如果是我方的话会几连,如果是对方的话会是几连,如果我方的子多,落子,如果对方的子多我去堵他。 总的来说,要让电脑知道该在哪一点下子,就要根据盘面的形势,为每 一可能落子的点计算其重要程度,也就是当这子落下后会形成什么棋型(如:“冲四”、“活三”等),然后通览 全盘选出最重要的一点,这便是最基本的算法。当然,仅靠当前盘面进行判定是远远不够的,这样下棋很轻易掉进 玩家设下的陷阱,因为它没有考虑以后的变化。所以在此基础上我们加入递归调用,即:在电脑中猜测出今后几步 的各种走法,以便作出最佳选择,这也是我们下棋时常说的“想了几步”。如此一来您的程序便具有一定的水平了。 什么?不信!过来试试吧! 总体思路弄清之后,下面进行具体讨论: 一:数据结构 先来看看数据结构,我们需要哪些变量? 首先得为整个棋盘建立一张表格用以记录棋子信息,我们使用一个15*15的二维数组Table[15][15] (15*15是 五子棋棋盘的大小),数组的每一个元素对应棋盘上的一个交叉点,用…0?表示空位、…1?代表己方的子、…2? 代表对方的子;这张表也是今后分析的基础。 在此之后还要为电脑和玩家双方各建立一张棋型表Computer[15][15][4]和 Player[15][15][4],用来存放棋型 数据,就是刚才所说的重要程度,比如用…20?代表“冲四”的点,用…15?代表“活三”的点,那么在计算重要 性时,就可以根据20>15得出前者比后者重要,下子时电脑便会自动选择“冲四”的点。那为什么棋型表要使用三 维数组呢?因为棋盘上的每一个点都可以与横、竖、左斜、右斜四个方向的棋子构成不同的棋型,所以一个点总共 有4个记录;这样做的另一个好处是可以轻易判定出复合棋型,例如:假如同一点上有2个…15?就是双三、有一个…15?和一个…20?就是四三。 怎么样!3个数组构成了程序的基本数据骨架,今后只要再加入一些辅助变量便可以应付自如了。应该不会太 难吧?OK!有了这么多有用的数据,我们就可以深入到程序的流程中去了。 二:程序流程 我们主要讨论五子棋的核心算法,即:人工智能部分,而其他像图形显示、键盘鼠标控制等,因较为简单,所 以就不作过多介绍了。 我们看到本程序由六个基本功能模块构成,各模块的具体分析如下:

Java五子棋游戏源代码(人机对战)

//Java编程:五子棋游戏源代码 import java.awt.*; import java.awt.event.*; import java.applet.*; import javax.swing.*; import java.io.PrintStream; import javax.swing.JComponent; import javax.swing.JPanel; /* *main方法创建了ChessFrame类的一个实例对象(cf), *并启动屏幕显示显示该实例对象。 **/ public class FiveChessAppletDemo { public static void main(String args[]){ ChessFrame cf = new ChessFrame(); cf.show(); } } /* *类ChessFrame主要功能是创建五子棋游戏主窗体和菜单**/ class ChessFrame extends JFrame implements ActionListener { private String[] strsize={"20x15","30x20","40x30"}; private String[] strmode={"人机对弈","人人对弈"}; public static boolean iscomputer=true,checkcomputer=true; private int width,height; private ChessModel cm; private MainPanel mp; //构造五子棋游戏的主窗体 public ChessFrame() { this.setTitle("五子棋游戏"); cm=new ChessModel(1); mp=new MainPanel(cm); Container con=this.getContentPane(); con.add(mp,"Center"); this.setResizable(false); this.addWindowListener(new ChessWindowEvent()); MapSize(20,15); JMenuBar mbar = new JMenuBar(); this.setJMenuBar(mbar); JMenu gameMenu = new JMenu("游戏");

五子棋算法设计

流星载月I have a dream,a beatiful dream that one day i can fly !! 首页 日志 相册 音乐 收藏 博友 关于我 日志 fly_just 永远不相信努力创造不了奇迹! 加博友关注他 最新日志 http包截获并还原HTML与数据

中华民族的好总理-周恩来 中华民族的好总理-朱镕基 网络共享拨号软件粗设计 五子棋算法设计初探 First ,Last 集构造 首页推荐 日本人喜欢用饺子配米饭 劈腿女如何玩转俩'老公' 台湾新片靠全裸女博出位 石油双雄逼民营油企停产 女星走红毯全靠透视装? 灵肉交织的智力舞蹈(图) 更多>> First ,Last 集构造 网络共享拨号软件粗设计五子棋算法设计初探

2008-11-08 21:12:38| 分类:默认分类|字号目录: 标题 一、设计概要 1、图形界面设计 2、算法设计概要 二、具体算法实现 1.计算放棋的相对物理坐标 2.给着棋点周围加权 3.计算棋局上成棋个数 4.给特殊棋格附于特别权 5.计算最大权值、最小权值 6.根据最大、最小权值决定策略

7.输赢的判断 三、变量、数据结构与函数 1.自定义的变量和消息 2.类成员变量 3.数据结构 4.全局函数 5.类主要成员函数 三、人机对战流程图 主题内容: 、图形界面设计 棋盘方格以背景图片的方式贴于对方框之上,其中的图片来自网络图片中剪切下来的一部分,格局大小非标准的国际五子棋大小,只是为了研究五子棋算法而作的一个模拟棋盘。棋盘大小为16*14,即横方向上16格,坚直方向上14格。棋子仍MFC自带绘图ICON工具所绘制,大小31*31像素,分为黑白两种棋子。棋局可以自动保存于数据链表中,可自动重绘。见图(1).

五子棋算法

前一段时间某个公司给我出了一道作业题,当然,只有做完了这个题目才能够有基本的实习机会,这个题目就是五子棋了。五子棋说起来简单,也比较简单,毕竟现在网上已经有非常成熟的算法了,而如果说五子棋考人面试的话,应该还算是有一定的难度的(虽然思路不是特别难),当然,我在做这个题目的时候,还是发现了很多问题。在博客园上找了一个五子棋的实现,我写的算法基本和他差不多,不过我的AI总没有他那么高,我这就是简单的实现了一下,如下图所示。 在做五子棋这个程序的时候,首先确定一些基本功能,这些功能包括如下。 玩家能够快速开始游戏。 玩家能够更换身份(更换黑棋和白棋)。 玩家能够退出游戏。 其中,玩家能够快速开始游戏,需要考虑玩家当前的身份。例如当玩家为黑棋的时候(玩家先走棋),单击【快速游戏】时玩家能够开始下棋,另外,当玩家为白棋的时候(电脑先走棋),单击【快速游戏】时计算机首先下棋。不仅如此,玩家能够快速更换身份。更换身份后玩家能够进行不同的棋子的选择,从而和电脑进行博弈。 如果玩家希望退出时,可以单击【退出】进行系统退出。 OK,了解了基本的功能后,主要就是算法问题了,这里主要有几个类,这几个类分别为Stones(控制棋子),Boards(控制棋盘以及逻辑),PC(电脑AI的实现),Rules(五

子棋规则的实现)。首先也是最重要的,就是Boards类,该类一开始首先需要绘制一个棋盘在窗体中。棋盘是绘制上去的,在Paint方法中实现,示例代码如下所示。 1.private void Form1_Paint(object sender, PaintEventArgs e) 2.{ 3. bd.DrawBoard(); 4.} 复制代码 上述代码使用了Boards的bd类进行棋盘的创建,这里可以看看该类的实现。 1.public void DrawBoard() 2.{ 3. Assembly myAssembly = Assembly.GetExecutingAssembly(); 4. Stream myStream = myAssembly.GetManifestResourceStream("FiveStone.board.png"); 5. Bitmap bt = new Bitmap(myStream); 6. myStream.Close(); 7. mg.DrawImage(bt, 20, 20, bt.Width, bt.Height); 8. 9. for (int i = 0; i < 15; i++) 10. { 11. for (int j = 0; j < 15; j++) 12. { 13. if (board[i, j] == 0) 14. { 15. stone.DrawStone(i, j, true); 16. } 17. if (board[i, j] == 1) 18. { 19. stone.DrawStone(i, j, false); 20. } 21. } 22. } 23.} 复制代码

五子棋AI算法的改进方法

又是本人一份人工智能作业……首先道歉,从Word贴到Livewrter,好多格式没了,也没做代码高亮……大家凑活着看……想做个好的人机对弈的五子棋,可以说需要考虑的问题还是很多的,我们将制作拥有强大AI五子棋的过程分为十四步,让我来步步介绍。 第一步,了解禁手规则 做一个五子棋的程序,自然对五子棋需要有足够的了解,现在默认大家现在和我研究五子棋之前了解是一样多的。以这个为基础,介绍多数人不大熟悉的方面。五子棋的规则实际上有两种:有禁手和无禁手。由于无禁手的规则比较简单,因此被更多人所接受。其实,对于专业下五子棋的人来说,有禁手才是规则。所以,这里先对“有禁手”进行一下简单介绍: 五子棋中“先手必胜”已经得到了论证,类似“花月定式”和“浦月定式”,很多先手必胜下法虽然需要大量的记忆,但高手确能做到必胜。所以五子棋的规则进行了优化,得到了“有禁手”五子棋。五子棋中,黑棋必然先行。因此“有禁手”五子棋竞技中对黑棋有以下“禁手”限制:“三三禁”:黑棋下子位置同时形成两个以上的三;“四四禁”:黑棋下子位置同时形成两个以上的四;“长连禁”:六子以上的黑棋连成一线。黑棋如下出“禁手“则马上输掉棋局。不过如果“连五”与“禁手”同时出现这时“禁手”是无效的。所以对于黑棋只有冲四活三(后面会有解释)是无解局面。反观白棋则多了一种获胜方式,那就是逼迫黑棋必定要下在禁点。 为了迎合所有玩家,五子棋自然需要做出两个版本,或者是可以进行禁手上的控制。 第二步,实现游戏界面 这里,我制作了一个简单的界面,但是,对于人机对弈来说,绝对够用。和很多网上的精美界面相比,我的界面也许略显粗糙,但,开发速度较高,仅用了不到半天时间。下面我们简单看下界面的做法。 界面我采用了WPF,表现层和逻辑层完全分开,前台基本可以通过拖拽完成布局,这里就不做过多介绍。根据界面截图简单介绍

五子棋人机对战算法分析

总的来说,要让电脑知道该在哪一点下子,就要根据盘面的形势,为每 一可能落子的点计算其重要程度,也就是当这子落下后会形成什么棋型(如:“冲四”、“活三”等),然后通览 全盘选出最重要的一点,这便是最基本的算法。当然,仅靠当前盘面进行判定是远远不够的,这样下棋很轻易掉进 玩家设下的陷阱,因为它没有考虑以后的变化。所以在此基础上我们加入递归调用,即:在电脑中猜测出今后几步 的各种走法,以便作出最佳选择,这也是我们下棋时常说的“想了几步”。如此一来您的程序便具有一定的水平了。 什么?不信!过来试试吧! 总体思路弄清之后,下面进行具体讨论: 一:数据结构 先来看看数据结构,我们需要哪些变量? 首先得为整个棋盘建立一张表格用以记录棋子信息,我们使用一个15*15的二维数组Table[15][15] (15*15是 五子棋棋盘的大小),数组的每一个元素对应棋盘上的一个交叉点,用…0?表示空位、…1?代表己方的子、…2? 代表对方的子;这张表也是今后分析的基础。 在此之后还要为电脑和玩家双方各建立一张棋型表Computer[15][15][4]和 Player[15][15][4],用来存放棋型 数据,就是刚才所说的重要程度,比如用…20?代表“冲四”的点,用…15?代表“活三”的点,那么在计算重要 性时,就可以根据20>15得出前者比后者重要,下子时电脑便会自动选择“冲四”的点。那为什么棋型表要使用三 维数组呢?因为棋盘上的每一个点都可以与横、竖、左斜、右斜四个方向的棋子构成不同的棋型,所以一个点总共 有4个记录;这样做的另一个好处是可以轻易判定出复合棋型,例如:假如同一点上有2个…15?就是双三、有一个…15?和一个…20?就是四三。 怎么样!3个数组构成了程序的基本数据骨架,今后只要再加入一些辅助变量便可以应付自如了。应该不会太 难吧?OK!有了这么多有用的数据,我们就可以深入到程序的流程中去了。 二:程序流程 我们主要讨论五子棋的核心算法,即:人工智能部分,而其他像图形显示、键盘鼠标控制等,因较为简单,所 以就不作过多介绍了。 我们看到本程序由六个基本功能模块构成,各模块的具体分析如下: (1)初始化:首先,建立盘面数组Table[15][15]、对战双方的棋型表Computer[15][15][4]和Player[15] [15][4]并将它们清零以备使用;然后初始化显示器、键盘、鼠等输入输出设备并在屏幕上画出棋盘。 (2)主循环控制模块:控制下棋顺序,当轮到某方下子时,负责将程序转到相应的模块中去,主要担当一个

五子棋核心算法

五子棋的核心算法 时间:2010-03-26 20:50来源:网络作者:佚名点击:3115次 介绍了五子棋程序的数据结构、评分规则、胜负判断方法和搜索算法过程。 五子棋是一种受大众广泛喜爱的游戏,其规则简单,变化多端,非常富有趣味性和消遣性。这里设计和实现了一个人机对下的五子棋程序,采用了博弈树的方法,应用了剪枝和最大最小树原理进行搜索发现最好的下子位置。介绍五子棋程序的数据结构、评分规则、胜负判断方法和搜索算法过程。 一、相关的数据结构 关于盘面情况的表示,以链表形式表示当前盘面的情况,目的是可以允许用户进行悔棋、回退等操作。 1CList StepList; 2//其中Step结构的表示为: 3 4struct Step 5{ 6int m;//m,n表示两个坐标值 7int n; 8char side;//side表示下子方 9}; 10//以数组形式保存当前盘面的情况, 11//目的是为了在显示当前盘面情况时使用: 12char FiveArea[FIVE_MAX_LINE][FIVE_MAX_LINE]; 13 14//其中FIVE_MAX_LINE表示盘面最大的行数。 15 16//同时由于需要在递归搜索的过程中考虑时间和空间有效性, //只找出就当前情况来说相对比较好的几个盘面,而不是对所有的可下子的位置都进行搜索, //这里用变量CountList来表示当前搜索中可以选择的所有新的盘面情况对象的集合: 17 18CList CountList; 19//其中类CBoardSituiton为: 20class CBoardSituation 21{ 22CList StepList; //每一步的列表 23char FiveArea[FIVE_MAX_LINE][FIVE_MAX_LINE]; 24struct Step machineStep;//机器所下的那一步

五子棋几种算法详解

五子棋几种算法详解 算法一: 这里讲述棋盘大小为10×10的人机对战五子棋实现方法,要看完整代码请看Java做的五子棋 1.概述 玩家每走一步,对于玩家和计算机,都根据获胜表对棋盘各个空棋位进行评分,每个位置的分数与下面这句话有关:该位置所在的每一种获胜组合中已经拥有的棋子数,然后对玩家和计算机产生的分数均衡,以判断计算机是进攻还是防守。 2.数据结构 10×10的数据,用来记录棋盘状态; 两个获胜表([10][10][192]),也就是获胜组合,因为五个子一线则胜,不在一线上的五个子就不在一个组合中,对于10×10的棋盘获胜的组合有192种,下面将会详细说明,获胜表用来表示棋盘上的每个位置是否在玩家或计算机的获胜组合中; 一个二维数组([2][192]),记录玩家与计算机在各种获胜组合中填入了多少棋子; 两个10×10的数组,用来记录玩家与计算机在各个棋盘位置上的分数,分数高的将是计算机下一步的着法。 3.计算获胜组合

上图是一个10×10的五子棋棋盘,我们可以得出垂直方向上的获胜组合是10×6=60,同理,水平方向的获胜组合也是60,而两个倾斜方向上的获胜组合是(1+2+3+4+5)×2+6=36,即: 60*2+36*2=192。 4.评分 用两个数组存储每个棋位的分数,一个是计算机的,另一个是玩家的,表示该位置对于各方是最佳着法的肯定程度,对一个位置的评分就是:遍历该位置所在的每一种获胜组合,根据这个组合中已经拥有的己方棋子数1到4分别加不同分数,最后将这些所有的获胜组合所得出的分数相加就是该位置的分数,下图是对于黑方各棋位的评分(其中的1,2,3,4这几个值要根据实际需要来确定)。 5.思路

五子棋AI算法的改进方法讲解--实用.doc

又是本人一份人工智能作??首先道歉,从Word到Livewrter,好多格式没了,也没 做代高亮??大家凑活着看??想做个好的人机弈的五子棋,可以需要考的 是很多的,我将制作有大AI 五子棋的程分十四步,我来步步介。 第一步,了解禁手 做一个五子棋的程序,自然五子棋需要有足的了解,在默大家在和我研究五子棋 之前了解是一多的。以个基,介多数人不大熟悉的方面。五子棋的上有 两种:有禁手和无禁手。由于无禁手的比,因此被更多人所接受。其,于 下五子棋的人来,有禁手才是。所以,里先“有禁手” 行一下介: 五子棋中“先手必”已得到了,似“花月定式”和“浦月定式”,很多先手必下法 然需要大量的,但高手确能做到必。所以五子棋的行了化,得到了“有禁手”五子棋。五子棋中,黑棋必然先行。因此“有禁手”五子棋技中黑棋有以下“禁手”限制:“三三禁”:黑棋下子位置同形成两个以上的三;“四四禁”:黑棋下子位置同形成两个以上的 四;“ 禁”:六子以上的黑棋成一。黑棋如下出“禁手“ 上掉棋局。不如果“ 五”与“禁手”同出“禁手”是无效的。所以于黑棋只有冲四活三(后面会有解) 是无解局面。反白棋多了一种方式,那就是逼迫黑棋必定要下在禁点。 了迎合所有玩家,五子棋自然需要做出两个版本,或者是可以行禁手上的控制。 第二步,游界面 里,我制作了一个的界面,但是,于人机弈来,用。和很多网上的精美界面相比,我的界 面也略粗糙,但,开速度高,用了不到半天。下面我看下界面的做法。 界面我采用了 WPF ,表和完全分开,前台基本可以通拖拽完成布局,里就不做多介。根 据界面截介

1 处实际上市两个渐变Label 但是没有做事件响应。通过按钮属性。也许有人会奇怪,为什么的拼接, 2 、 3 是两个 label , 4 、 5 6 、 7 、 8 、9的控制,修改label Button 会丝毫看出不出有Button 实际上是两个Button, 和 Button的Content 的影子,这里战友 whrxiao 写过一个Style 如下