人工智能实习报告(--)

温柔似野鬼°
646次浏览
2021年01月18日 14:55
最佳经验
本文由作者推荐

dhcp服务器配置-放假通知怎么写

2021年1月18日发(作者:洪民生)





































姓名:






























班级:



191092







学号:



2009100



















指导老师:


















2011

10




人工智能课程设计







经过近一周的奋战,我终于初步实现了我的“四子棋”游戏。起初,我选
择这个游戏是因为它很独特、
少有人做,
而且我想当然的认为四子比五子少一子,
实现起来应该相对简单,
但是面对一个个头疼的错误,
遭受一次又一次失败的打
击,我才发现自己想错了,四子棋人机对 战比五子棋更让人纠结。


暑期我和班上两名同学
xxx,xx
一 起完成过五子棋和黑白棋的编程。当时,
五子棋我们是参照别人的模板完成的,
黑白棋是在透彻 研究过五子棋的基础上不
断讨论、优化算法最终完成的。现在,他们一个继续做五子棋一个做黑白棋,将
其完善作为人工智能的课程设计课题。我只得另陌新路,关注起了四子棋。


界面的搭建以及二人对战的实现只用了我两个晚上的时间,当然我的界面
构建的相对简单。二人对战实 现关键一步就是输赢判断函数
judge
()的编写。
人机对战整整折腾了自己四五天 的时间,我本来对于博弈过程中
alpha

beta

枝算法很理 解的,
但是具体要自己编程实现时我觉得自己只了解到其皮毛。
所以,
我不断看五子棋 程序、
单步跟踪、
寻问同学,
终于算是把其递归和剪枝过程搞得
明明白白。< br>

花了两天完成了
alpha

beta
剪枝算法 我本以为核心都解决了,却不知更让
人头疼的是评估函数的确定还有统计当前棋局状况的函数
C alculate
()的编写。
难题终究是可以被客服的,我花了整整一天写完了我的
Calculate
()函数。


直至
10

2 7
日上午我依然没有让机器足够智能,或者说它目前很呆板。
我一直在找原因,
自己的 模块设计算法思路都是对的,
请教过同学她也觉得设计
思路没有错。
现在,
我 整体的想了一下,
觉得应该是我的静态评估函数设计的不
够合理,
或者说目前的设计方 法对于五子棋很合理但是对于规则不同的四子棋就
可能存在缺陷。
既然目前时间不允许没能实现 足够智能,
那就只能把这粗略的程
序提交。我一定会继续完善、改进算法,重新设计评估函数, 争取让机器达到理
想的“智能”






2
191092
班—
xx
人工智能课程设计

一、课题选则

1.
题目概述

利用
VC++实现四子棋游戏,
要求提供可视化界面以及二人对战、
人机对战的功能。
四子棋游 戏规则如下:

四子棋的棋盘共有
7

7
列,
棋盘 是垂直摆放,
每名玩者只能左右控制落子的位置。
两名玩者轮流每次把一只棋子放进棋盘任何未 全满的一行中,
棋子会佔据一行中最底未
被佔据的位置。
两名玩者任何一方先以四只棋 子在横,
竖或斜方向联成一条直线,
便可
获胜,
游戏亦结束。
假如棋 盘已完全被棋子填满,
但仍未有任何一方成功把四只棋子成
一直线,则成为和局。

2.
选题缘由

四子棋游戏规则独特,所以其规则的设计将有别于五子棋等通常的棋类游戏。

四子棋人机对战功能的实现需要用到博弈树搜索中的核心算法:


与五子棋 不同,
因为四子棋的独特性网络中根本没有某某
“热心”
网友的游戏源码,
我 找了很久也只找到一个二人对战的四子棋,他还是用
C
语言在
dos
下实现的 ,一点
也不人性化。

综合以上种种我决定挑战一下自己,用
VC
实现“我的四子棋”游戏。

二、需求分析

1.
功能需求

1.1
提供合理的人机交互界面

1.2
提供二人对战功能

1.3
提供人机对战功能

2.
数据结构

2.1
棋盘数据采用一二维数组
grid[7][7]
存储

三、模块设计

A.
整体思路

通过对需求的分析,
我认为我的设计工作主要可以分为三大块,
第一块是主界面的
搭建和棋盘的绘制,
第 二块是落子和输赢判断的实现,
第三块就是二人对战和人机对战
的实现。

对 于第一块,
因为有图形学和图像处理的上机经验,
我将果断的选择单文档作为界
面窗口 ,用绘制的方式搭建棋盘。

对于第二块,
对于落子其实就是在响应鼠标左键按下的消 息后记录下所需放子的坐
标,然后改变内部存储数据,调用绘图函数
ondraw
() 进行绘制。输赢判断就是对于
每下一颗棋子搜索其横向竖向交叉斜向的棋子,如若有四颗连成一线的就判 为赢。

对于第三模块,
这是整个游戏的核心,
二人对战相对好实现。
人机对战需要用到博
弈树搜索需要用到
alphabeta
剪枝算法,还需要设定以 静态评估函数,这两方面是最困
难也是最重要的部分。

B.
具体设计

1.
主界面设计

1.1
单文档窗口大小的限定





我们知道通过
VC++
工程创建的单文档都有默认的大小,
那个大小太大不适合

作为游戏的界面窗口大小。
所以我希望自定义其大小,
而且在此游戏中不需要用工

具栏,所以我希望通过人为操作去掉工具栏。

具体实现:


Frame
框架类里面的
PreCreateWindow( )
创建窗口函数总添加以下代码

3
191092
班—
xx
人工智能课程设计





&=~WS_MAXIMIZEBOX;





//
禁止对文档最大化操作


&=~WS_THICKFRAME;

=700;/










/
自定义文档大小


=500;

cs.y=180;

cs.x=300;

&=~FWS_A DDTOTITLE;//

FWS_ADDTOTITLE
去掉


me=
我的四子棋





//
改变文档标题



OnCreate(LPCREATESTRUCT lpCreateStruct)
函数中以下代码屏蔽即可去掉工具栏








/*if (!m_Ex(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP


{


}*/
TRACE0(
return -1;





// fail to create
| CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
!m_olBar(IDR_MAINFRAME))
1.2
棋盘绘制
< br>棋盘绘制在
view
类里面的
ondraw
函数里实现,创建画笔蓝色 画笔通过
MoveTo

LineTo
函数画出棋格,创建天蓝色画刷绘制棋 格背景色。创建红色、黄
色画刷用于绘制双方棋手棋子。

具体代码如下:

CRect rect;

CBrush *brush,*brush1,*brush2,*brush3;

brush = new CBrush;

brush1 = new CBrush;

brush2 = new CBrush;

brush3 = new CBrush;

brush->CreateSolidBrush(RGB(150, 205 ,205));

brush1->CreateSolidBrush(RGB(255, 0 ,0));//
红色画刷


brush2->CreateSolidBrush(RGB(255, 255 ,0));//
黄色画刷


brush3->CreateSolidBrush(RGB(128, 128 ,28));//bai
色画刷


this->GetClientRect(&rect);

pDC->FillRect(&rect,brush);









CClientDC dc(this);

CPen m_pen(PS_SOLID,1,RGB(0,0,255));

//
将画笔选入设备列表


CPen *pOldPen = Object(&m_pen);

int i;

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

{


(bx,by+width*i);


(bx+width*7,by+width*i);

}

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

{


(bx+width*i,by);


(bx+width*i,by+width*7);

}


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

{


for (int j=0;j<7;j++)


{
4
191092
班—
xx
人工智能课程设计




switch(grid[i][j])



{



case 1:



pDC->SelectObject(brush1);












pDC->E llipse(bx+width*(i+0.5)-r,by+width*(j+0.5)











-r,bx+width*(i+0.5)+r,by+width*(j+0.5)+r);




break;



case 2:




//pDC->SelectStockObject(WHITE_PEN);




pDC->SelectObject(brush2);




pDC->Ellipse(bx+width*(i+0.5)-r,by+w idth*(j+0.5)-r,bx+width*(i+0.5)+r,by+widt
h*(j+ 0.5)+r);




//pDC->SelectStockObject(BLACK_PEN);




break;



case 3:




pDC->SelectObject(brush3);




pDC->Ellipse(bx+width*(i+0 .5)-(r+5),by+width*(j+0.5)-(r+5),bx+width*(i+0.5)+ (
r+5),by+width*(j+0.5)+(r+5));








break;



default:








break;



}


}

}
2.
模式选择设计

2.1
更改菜单按钮




在菜单栏中添加模式按钮“二人对战”和“人机对战”


2.2
响应选择按钮消息

通过
MFC
类向导在
V iew
类中响应“二人对战”和“人机对战”的按钮消息,
实现方式如下:

void CMYSIZIQIView::OnPvsp()

{

// TODO: Add your command handler code here

reset();

pvsp=true;

Invalidate();//
是当前窗口无效,需要重绘

}
void CMYSIZIQIView::OnPvsc()

{

// TODO: Add your command handler code here

reset();

pvsc=true;

RorY=true;

pvsp=false;

Invalidate();//
是当前窗口无效,需要重绘

}

buttondown
()函数设计

3.1
根据鼠标坐标转换出在存储数组中对应的下标

5
191092
班—
xx
人工智能课程设计

int px=(point.x-bx)/width;

int py=(point.y-by)/width;

3.2
限定落子只可以在该列最下面一个空格





for(int j=6;j>=0;j--)

{


if(grid[px][j]==0)


{



py=j;



break;


}

}
3.3
二人对战、人机对战程序响应


if(0<=px&&px<7&&0<=py&&py<7&&grid[px][py]==0)

{


if(!pvsp&&!pvsc) MessageBox(
请选择对战模式



else if(pvsp)





//
二人对战



{



grid[px][py]=c;//
根据该点颜色选择对应的画笔



color=!color;//
换位另一颜色


< br>t(point.x-8*width,point.y-8*width,point.x+8*wid th,point.y+8*width);


InvalidateRect(&r);


judge(c,px,py);//
判断有没有取胜



}


else if (pvsc)
//
人机对战模式




{



color=!color;



if (!judge(c,px,py)) // if player doesn't win



{

alphabeta(LONG_MIN,LONG_MAX,depth,false); //computer puts the





color=!color;




InvalidateRect(&r);












judge(c,bestmove[0],bestmove[1]);



}


}

}

()函数设计

4.0
每一个方向定义一个变量用以记录当前棋子个数:

HWIN
——横方向

SWIN
——竖方向

LRWIN
——左上右下方向

RLWIN
——右上左下方向

4.1
横向判断是否四子连线

int HWIN=1;

for ( i=x-1;i>=0;i--)//&&&&&&&&&
棋子左边


{


//MessageBox(
红赢



if(grid[i][y]==color) HWIN++;
6
191092
班—
xx
人工智能课程设计






if(grid[i][y]!=color) break;

}





if(HWIN>=4&&color==1)//


{
左边可能已经三个棋子





for ( i=x-1;i>=0;i--)//





if(grid[i][y]==color)
一方赢了则改变其颜色




{




grid[i][y]=3;

}
grid[x][y]=3;









MessageBox(
红赢




reset();



Invalidate();


}
return true;


else if (HWIN>=4&&color==2)


{






for ( i=x-1;i>=0;i--)//


if(grid[i][y]==color)
一方赢了则改变其颜色





{





grid[i][y]=3;




grid[x][y]=3;
}






MessageBox(
黄赢



reset();




Invalidate();




t0=HWIN;
}
return true;

for (i=x+1;i<=6;i++)//&&&&&&&&&&&&

{
棋子右边





//MessageBox(
红赢



if(grid[i][y]==color) HWIN++;

}
if(grid[i][y]!=color) break;





if(HWIN>=4&&color==1)


{






for ( i=x+1;i<=6;i++)//

if(grid[i][y]==color)
一方赢了则改变其颜色









{

grid[i][y]=3;




}



grid[x][y]=3;






if(HWIN-t0==2) grid[x-1][y]=3;



if(HWIN-t0==1) {grid[x-1][y]=3;grid[x-2][y]=3;}
MessageBox(



红赢




reset();
Invalidate();



return true;


}


else if (HWIN>=4&&color==2)


{






for ( i=x+1;i<=6;i++)//
一方赢了则改变其颜色





if(grid[i][y]==color)





{

grid[i][y]=3;




}





grid[x][y]=3;

if(HWIN-t0==2) grid[x-1][y]=3;
if(HWIN-t0==1) {grid[x-1][y]=3;grid[x-2][y]=3;}
7
班—
xx
191092
人工智能课程设计








MessageBox(
黄赢



reset();


Invalidate();


return true;

}
具体判断细节见注释

4.2
竖向判断是否四子连线

//****************** *****
竖向判断
***************************//


int SWIN=1;


for ( j=y+1;j<=6;j++)//&&&&&&&&&
棋子下边



{



//MessageBox(
红赢




if(grid[x][j]==color) SWIN++;



if(grid[x][j]!=color) break;






}


if(SWIN>=4&&color==1)//
下边可能已经三个棋子



{



for (j=y+1;j<=6;j++)//
一方赢了则改变其颜色





if(grid[x][j]==color&&j-y<=3)




{





grid[x][j]=3;




}



grid[x][y]=3;



MessageBox(
红赢




reset();



Invalidate();



return true;


}


else if (SWIN>=4&&color==2)


{



for (j=y+1;j<=6;j++)//
一方赢了则改变其颜色





if(grid[x][j]==color&&j-y<=3)




{





grid[x][j]=3;




}



grid[x][y]=3;




MessageBox(
黄赢




reset();



Invalidate();



return true;


}
具体判断细节见注释

4.3
左上右下方向判断是否四子连线


//**********************
左上右下方向
*** **********************//


int LRWIN=1;


for (i=x-1,j=y-1;i>=0&&j>=0 ;i--,j--)//&&&&&&&&&
棋子左上方



{



//MessageBox(
红赢




if(grid[i][j]==color) LRWIN++;



if(grid[i][j]!=color) break;






}


if(LRWIN>=4&&color==1)//
左上可能已经三个棋子



{



for (i=x-1,j=y-1;i>=0&&j>=0;i--,j--) //
一方赢了则改变其颜色





if(grid[i][j]==color&&(y-j<=3))




{





grid[i][j]=3;




}



grid[x][y]=3;
8
191092
班—
xx
人工智能课程设计








































































MessageBox(
红赢


reset();

Invalidate();

return true;
}
else if (LRWIN>=4&&color==2)
{

for (i=x-1,j=y-1;i>=0&&j>=0;i--,j--) //
一方赢了则改变其颜色



if(grid[i][j]==color&&(y-j<=3))


{



grid[i][j]=3;


}

grid[x][y]=3;


MessageBox(
黄赢



reset();


Invalidate();


return true;

}


t0=LRWIN;

for (i=x+1,j=y+1;i<=6&&j<=6;i++,j++)//&&&&&&&& &&&&
棋子右下边


{





if(grid[i][j]==color) LRWIN++;


if(grid[i][j]!=color) break;


}

if(LRWIN>=4&&color==1)

{


for (i=x+1,j=y+1;i<=6&&j<=6;i++,j++) //
一方赢了则改变其颜色




if(grid[i][j]==color&&(j-y)<=3)



{




grid[i][j]=3;



}


grid[x][y]=3;


if(LRWIN-t0==2) grid[x-1][y-1]=3;


if(LRWIN-t0==1) {grid[x-1][y-1]=3;grid[x-2][y-2]=3;}


MessageBox(
红赢



reset();


Invalidate();


return true;

}

else if (LRWIN>=4&&color==2)

{


for (i=x+1,j=y+1;i<=6&&j<=6;i++,j++) //
一方赢了则改变其颜色




if(grid[i][j]==color&&(j-y)<=3)



{




grid[i][j]=3;



}


grid[x][y]=3;


if(LRWIN-t0==2) grid[x-1][y-1]=3;


if(LRWIN-t0==1) {grid[x-1][y-1]=3;grid[x-2][y-2]=3;}


MessageBox(
黄赢



reset();


Invalidate();


return true;

}
具体判断细节见注释

4.4
右上左下方向判断是否四子连线


//********* **************
右上左下方向
********************** ****//


int RLWIN=1;


for (i=x+1,j=y-1;i<=6&&j>=0;i++,j--)//&&&&&&&& &
棋子右上方



{
9
191092
班—
xx
人工智能课程设计




if(grid[i][j]==color) RLWIN++;



if(grid[i][j]!=color) break;



}


if(RLWIN>=4&&color==1)//
可能已经三个棋子



{



for (i=x+1,j=y-1;i<=6&&j>=0;i++,j--) //
一方赢了则改变其颜色





if(grid[i][j]==color&&(y-j<=3))




{





grid[i][j]=3;




}



MessageBox(
红赢




reset();



Invalidate();



return true;


}


else if (RLWIN>=4&&color==2)


{



for (i=x+1,j=y-1;i<=6&&j>=0;i++,j--) //
一方赢了则改变其颜色





if(grid[i][j]==color&&(y-j<=3))




{





grid[i][j]=3;




}



grid[x][y]=3;



MessageBox(
黄赢




reset();



Invalidate();



return true;


}


t0=RLWIN;


for (i=x-1,j=y+1; i>=0&&j<=6;i--,j++)//&&&&&&&&&&&&
棋子左下边



{



if(grid[i][j]==color) RLWIN++;



if(grid[i][j]!=color) break;



}


if(RLWIN>=4&&color==1)


{



for (i=x-1,j=y+1;i>=0&&j<=6;i--,j++) //
一方赢了则改变其颜色





if(grid[i][j]==color&&(j-y<=3))




{





grid[i][j]=3;




}



grid[x][y]=3;















if(RLWIN-t0==2) grid[x+1][y-1]=3;



if(RLWIN-t0==1) {grid[x+1][y-1]=3;grid[x+2][y-2]=3;}



MessageBox(
红赢




reset();



Invalidate();



return true;


}


else if (RLWIN>=4&&color==2)


{



for (i=x-1,j=y+1;i>=0&&j<=6;i--,j++) //
一方赢了则改变其颜色





if(grid[i][j]==color&&(j-y<=3))




{





grid[i][j]=3;




}



grid[x][y]=3;



if(RLWIN-t0==2) grid[x+1][y-1]=3;



if(RLWIN-t0==1) {grid[x+1][y-1]=3;grid[x+2][y-2]=3;}



MessageBox(
黄赢




reset();



Invalidate();
10
191092
班—
xx
人工智能课程设计




return true;


}
具体判断细节见注释


()函数设计

该函数很简单,即是将数组存储空间归零化。
起作用就是让二人对战、
人机对战函
数调用,达到初 始化数据的目的:


for (int i=0;i<7;i++)


for (int j=0;j<7;j++)



grid[i][j]=0;
eta
()函数设计

6.1
极大极小值分析法

6.1.1
其基本思想或算法是:



(1)
设博弈的 双方中一方为
MAX
,另一方为
MIN
。然后为其中的一方
(
例如
MAX)


找一个最优行动方案。



(2)
为了找到当前的最优行动方案,
需要对各个可能的方案所产生的后果进行比较
,

具体地说,就是要考虑每一方案实施后对方可能采取的所有行动,并计算可能得



(3)
为计算得分,
需要根据问题的特性信息定义一个估价函数,
用来估算当前博弈

树端节点的得分。此时估算出来的得分称为静态估值。



(4)
当端节点的估值计算出来后,
再推算出父节点的得分,
推算的方法是:
“或”

节点,
选其子节点中一个最大的得分作为父节点的得分,
这是为 了使自己在可供选

择的方案中选一个对自己最有利的方案;
对“与”节点,选其子节点中一个最小的
< br>得分作为父节点的得分,
这是为了立足于最坏的情况。
这样计算出的父节点的得分

称为倒推值



(5)
如果一个行动方案能获得较大的倒推值,则它就是当前最好的行动方案。


6.2

α
-
β
剪枝技术

6.2.1
算法思想:

int AlphaBeta(int depth, int alpha, int beta)

{
if (depth == 0)//
叶子节点;

return Evaluate();//
返回当前盘面的估值;

GenerateLegalMoves();//
产生所有合理走法;

while (MovesLeft()) {//
如果还有未分析的走法;

MakeNextMove();//
试走一步;

val = -AlphaBeta(depth - 1, -beta, -alpha);//
返回当前节点



//
的估值,加负号是为了消除双方的差别,使程序简洁;

UnmakeMove();//
退回到没走前的状态;

if (val > = beta)//
剪枝;

return beta;
if (val > alpha)//
存当前值;

alpha = val;
}
return alpha;//
返回当前值;


}
6.2.2
关键点与具体设计:

alphabeta
()函数设计的关键点 包括递归调用、剪枝操作。其中递归的深度由参数
11
191092
班—
xx
人工智能课程设计

depth< br>限定,剪枝操作跟递归返回的
evalue
评估函数值息息相关。

long CMYSIZIQIView::alphabeta(long alpha,long beta,int d,bool m)
{

int i,j;

if(d==0)



//the depth of search is enough


return evalue();


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

//search for the blank

{


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



if(grid[i][j]==0)
break;


if(grid[i][j]==0)
break;

}

if(i==7&&j==7)

//no place to move


return evalue();

long a=alpha,b=beta;

long current,best;

bool first=true,choose=!m;
//choose--to decide the layer,max or min

int set_color;

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


for (j=6;j>=0;j--)//
怎么限制只找一个
?????????? ?????????????????


{



if(grid[i][j]!=0)
continue;



set_color=(RorY==true&&choose==true||RorY==fal se&&choose==false)?1:2;




grid[i][j]=set_color;



memset(sttblack,0,sizeof(sttblack));



memset(sttwhite,0,sizeof(sttwhite));

Calculate(false,sttblack[0],sttblack[1],sttbla ck[2],sttblack[3],sttblack[4],sttblack[5],sttbl
ack[6]);//
分别计算当前状态







Calculate(true,sttwhite[0],sttwhite[ 1],sttwhite[2],sttwhite[3],sttwhite[4],sttwhite[5] ,sttwhite[6
]);



current=alphabeta(a,b,d-1,choose);




grid[i][j]=0;



memset(sttblack,0,sizeof(sttblack));



memset(sttwhite,0,sizeof(sttwhite));

Calculate(false,sttblack[0],sttblack[1],sttbla ck[2],sttblack[3],sttblack[4],sttblack[5],
sttb lack[6]);//
分别计算当前状态




Cal culate(true,sttwhite[0],sttwhite[1],sttwhite[2],st twhite[3],sttwhite[4],sttwhite[5],sttw
hite[6]) ;



if(first)



{




best=current;




first=false;




if(d==depth)




{





bestmove[0]=i;





bestmove[1]=j;




}



}



if(choose)



//MAX

NODE



{




if(current>=b)
//beta cut





return current;




if(best



{





best=current;





a=current;





if(d==depth)





{






bestmove[0]=i;
12
191092
班—
xx
人工智能课程设计







bestmove[1]=j;





}




}



}else{




//MIN

NODE




if(current<=a)
//alpha cut





return current;




if(best>current)




{





best=current;





b=current;





if(d==depth)





{






bestmove[0]=i;






bestmove[1]=j;





}




}



}



break;


}

if(d==depth)

{


return 1;

}

return best;
}
ate( )
函数设计

7.1
该函数主要是统计当前棋局的状态,包括一个棋子一边被 堵
d1c
、一个棋子两
边都没被堵
a1c
、两个棋子连在一起一边被 堵
d2c
、两个棋子连在一起两边都未堵堵
d2c
„„

7.2
可以从横竖左斜右斜四个方面分析统计


例如横着方向实现如下:

//************************
横着方向
*************************//

for (y=6;y>=0;y--)

{



for(x=0;x<=6;x++)



{



if(grid[x][y]==c)



{






if(x==0)//
左边边界




for (i=x+1;i<=6;i++)



{




if(grid[i][y]==c) continue;




if(grid[i][y]==c0) break;




if(grid[i][y]==0)




{





if(i-x==1) d1c++;





if(i-x==2) d2c++;





if(i-x==3) d3c++;





if(i-x==4) d4c++;





break;




}



}
13
191092
班—
xx
人工智能课程设计





































































































































else if(x!=0&&x<6)//
左右都不是边界

{

for (i=x+1;i<=6;i++)

{


if(grid[i][y]==c) continue;


if(grid[i][y]==c0) //
右边为对手



{




if(grid[x-1][y]==0)



{




if(i-x==1) d1c++;




if(i-x==2) d2c++;




if(i-x==3) d3c++;




if(i-x==4) d4c++;




break;



}









else break;



}


if(grid[i][y]==0)//
右边为
0


{



if(grid[x-1][y]==0)//
在右边为
0
左边为
0



{




if(i-x==1) a1c++;




if(i-x==2) a2c++;




if(i-x==3) a3c++;




if(i-x==4) d4c++;




break;



}









else if(grid[x-1][y]==c0)//
在右边为
0
左边为对手




{if(i-x==1) d1c++;




if(i-x==2) d2c++;




if(i-x==3) d3c++;




if(i-x==4) d4c++;




break;



}


}

}
}
else if(x==6)
{

if (grid[x-1][y]==c0)break;

else





d1c++;break;

}
x=i;
14
191092
班—
xx
人工智能课程设计




}



}

}

()函数设计

所谓评估函 数,就是要建立一个函数,对棋盘上每一个空点进行计算,得出哪个点才
是最优的。这是一个看似简单, 其实很难的问题。

参照五子棋评估函数,我将棋局分类如下:活一、死一、活二、死二、活三 、死三、
死四。活二是指当前棋局两个子连在一起且两端都是活路的总数,死二是指当前棋局两个
子连在一起且有一端是死路的总数,以此类推。

然后给每种棋型一个权重,棋型乘以权重加 和的结果就是棋型的分数。我的权重分配
改变过很多次,目前依然没找到最合理的分配。

#define
FOUR






20000000
#define
ALIVE_3



1000000
#define
DEAD_3





10000
#define
ALIVE_2






8000
#define
DEAD_2








50
#define
ALIVE_1








30


#define
DEAD_1








10
评估函数如下:

long CMYSIZIQIView::evalue()
{

long



value=sttblack[0]*FOUR+sttblack[1]* ALIVE_3+sttblack[2]*DEAD_3





+sttblack[3]*ALIVE_2+sttblack[4]*DEAD_2+s ttblack[5]*ALIVE_1





+sttblack[6]*DEAD_1





-sttwhite[0]*FOUR- sttwhite[1]*ALIVE_3-sttwhite[2]*DEAD_3





-sttwhite[3]*ALIVE_2-sttwhite[4 ]*DEAD_2-sttwhite[5]*ALIVE_1





-sttwhite[6]*DEAD_1;


//
if(bkorwt)
value=value*(-1);


return value;


}
四、调试分析

1.
界面调试

1.1
棋盘背景和区域绘制出错

15
191092
班—
xx
人工智能课程设计


分析出错原因:

我在
opaint
函数中画线在
ondraw
函数中画背景,由于
opaint
函数会先

调用
ondraw
函数,所以画完再画棋格原来的背景被刷新了。

棋格绘制出错原因很简单,
范围限制的不正确,
再次计算做了调整棋盘显示正常如
下:


1.2
刷新函数出错


16
191092
班—
xx

dhcp服务器配置-放假通知怎么写


dhcp服务器配置-放假通知怎么写


dhcp服务器配置-放假通知怎么写


dhcp服务器配置-放假通知怎么写


dhcp服务器配置-放假通知怎么写


dhcp服务器配置-放假通知怎么写


dhcp服务器配置-放假通知怎么写


dhcp服务器配置-放假通知怎么写