人工智能实习报告Word文档下载推荐.docx
《人工智能实习报告Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《人工智能实习报告Word文档下载推荐.docx(52页珍藏版)》请在冰豆网上搜索。
![人工智能实习报告Word文档下载推荐.docx](https://file1.bdocx.com/fileroot1/2022-12/30/e40c8cdd-bb4e-47ee-becf-a0a2f6d7ac67/e40c8cdd-bb4e-47ee-becf-a0a2f6d7ac671.gif)
我一定会继续完善、改进算法,重新设计评估函数,争取让机器达到理想的“智能”。
一、课题选则
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()创建窗口函数总添加以下代码
cs.style&
=~WS_MAXIMIZEBOX;
//禁止对文档最大化操作
=~WS_THICKFRAME;
cs.cx=700;
//自定义文档大小
cs.cy=500;
cs.y=180;
cs.x=300;
=~FWS_ADDTOTITLE;
//将FWS_ADDTOTITLE去掉
cs.lpszName="
我的四子棋"
;
//改变文档标题
将OnCreate(LPCREATESTRUCTlpCreateStruct)函数中以下代码屏蔽即可去掉工具栏
/*if(!
m_wndToolBar.CreateEx(this,TBSTYLE_FLAT,WS_CHILD|WS_VISIBLE|CBRS_TOP
|CBRS_GRIPPER|CBRS_TOOLTIPS|CBRS_FLYBY|CBRS_SIZE_DYNAMIC)||
!
m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
{
TRACE0("
Failedtocreatetoolbar\n"
);
return-1;
//failtocreate
}*/
1.2棋盘绘制
棋盘绘制在view类里面的ondraw函数里实现,创建画笔蓝色画笔通过MoveTo、LineTo函数画出棋格,创建天蓝色画刷绘制棋格背景色。
创建红色、黄色画刷用于绘制双方棋手棋子。
具体代码如下:
CRectrect;
CBrush*brush,*brush1,*brush2,*brush3;
brush=newCBrush;
brush1=newCBrush;
brush2=newCBrush;
brush3=newCBrush;
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);
CClientDCdc(this);
CPenm_pen(PS_SOLID,1,RGB(0,0,255));
//将画笔选入设备列表
CPen*pOldPen=dc.SelectObject(&
m_pen);
inti;
for(i=0;
i<
8;
i++)
dc.MoveTo(bx,by+width*i);
dc.LineTo(bx+width*7,by+width*i);
}
dc.MoveTo(bx+width*i,by);
dc.LineTo(bx+width*i,by+width*7);
for(i=0;
7;
for(intj=0;
j<
j++)
{
switch(grid[i][j])
{
case1:
pDC->
SelectObject(brush1);
pDC->
Ellipse(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;
case2:
//pDC->
SelectStockObject(WHITE_PEN);
pDC->
SelectObject(brush2);
Ellipse(bx+width*(i+0.5)-r,by+width*(j+0.5)-r,bx+width*(i+0.5)+r,by+width*(j+0.5)+r);
SelectStockObject(BLACK_PEN);
case3:
SelectObject(brush3);
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));
default:
}
}
2.模式选择设计
2.1更改菜单按钮
在菜单栏中添加模式按钮“二人对战”和“人机对战”
2.2响应选择按钮消息
通过MFC类向导在View类中响应“二人对战”和“人机对战”的按钮消息,实现方式如下:
voidCMYSIZIQIView:
:
OnPvsp()
{
//TODO:
Addyourcommandhandlercodehere
reset();
pvsp=true;
Invalidate();
//是当前窗口无效,需要重绘
}
OnPvsc()
pvsc=true;
RorY=true;
pvsp=false;
3.Onleftbuttondown()函数设计
3.1根据鼠标坐标转换出在存储数组中对应的下标
intpx=(point.x-bx)/width;
intpy=(point.y-by)/width;
3.2限定落子只可以在该列最下面一个空格
for(intj=6;
j>
=0;
j--)
if(grid[px][j]==0)
py=j;
break;
3.3二人对战、人机对战程序响应
if(0<
=px&
&
px<
7&
0<
=py&
py<
grid[px][py]==0)
if(!
pvsp&
!
pvsc)MessageBox("
请选择对战模式"
elseif(pvsp)//二人对战
{
grid[px][py]=c;
//根据该点颜色选择对应的画笔
color=!
color;
//换位另一颜色
r.SetRect(point.x-8*width,point.y-8*width,point.x+8*width,point.y+8*width);
InvalidateRect(&
r);
judge(c,px,py);
//判断有没有取胜
elseif(pvsc)//人机对战模式
if(!
judge(c,px,py))//ifplayerdoesn'
twin
{alphabeta(LONG_MIN,LONG_MAX,depth,false);
//computerputsthe
color=!
InvalidateRect(&
judge(c,bestmove[0],bestmove[1]);
4.judge()函数设计
4.0每一个方向定义一个变量用以记录当前棋子个数:
HWIN——横方向
SWIN——竖方向
LRWIN——左上右下方向
RLWIN——右上左下方向
4.1横向判断是否四子连线
intHWIN=1;
for(i=x-1;
i>
i--)//&
棋子左边
//MessageBox("
红赢"
if(grid[i][y]==color)HWIN++;
if(grid[i][y]!
=color)break;
if(HWIN>
=4&
color==1)//左边可能已经三个棋子
for(i=x-1;
i--)//一方赢了则改变其颜色
if(grid[i][y]==color)
grid[i][y]=3;
grid[x][y]=3;
MessageBox("
reset();
Invalidate();
returntrue;
elseif(HWIN>
color==2)
if(grid[i][y]==color)
{
grid[i][y]=3;
}
黄赢"
t0=HWIN;
for(i=x+1;
=6;
i++)//&
棋子右边
color==1)
for(i=x+1;
i++)//一方赢了则改变其颜色
if(HWIN-t0==2)grid[x-1][y]=3;
if(HWIN-t0==1){grid[x-1][y]=3;
grid[x-2][y]=3;
具体判断细节见注释
4.2竖向判断是否四子连线
//***********************竖向判断***************************//
intSWIN=1;
for(j=y+1;
j++)//&
棋子下边
//MessageBox("
if(grid[x][j]==color)SWIN++;
if(grid[x][j]!
if(SWIN>
color==1)//下边可能已经三个棋子
for(j=y+1;
j++)//一方赢了则改变其颜色
if(grid[x][j]==color&
j-y<
=3)
grid[x][j]=3;
elseif(SWIN>
4.3左上右下方向判断是否四子连线
//**********************左上右下方向*************************//
intLRWIN=1;
for(i=x-1,j=y-1;
=0&
i--,j--)//&
棋子左上方
if(grid[i][j]==color)LRWIN++;
if(grid[i][j]!
if(LRWIN>
color==1)//左上可能已经三个棋子
for(i=x-1,j=y-1;
i--,j--)//一方赢了则改变其颜色
if(grid[i][j]==color&
(y-j<
=3))
grid[i][j]=3;
elseif(LRWIN>
t0=LRWIN;
for(i=x+1,j=y+1;
=6&
i++,j++)//&
棋子右下边
for(i=x+1,j=y+1;
i++,j++)//一方赢了则改变其颜色
(j-y)<
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;
4.4右上左下方向判断是否四子连线
//***********************右上左下方向**************************//
intRLWIN=1;
for(i=x+1,j=y-1;
i++,j--)//&
棋子右上方
if(grid[i][j]==color)RLWIN++;
if(RLWIN>
color==1)//可能已经三个棋子
for(i=x+1,j=y-1;
i++,j--)//一方赢了则改变其颜色
elseif(RLWIN>
t0=RLWIN;
for(i=x-1,j=y+1;
i--,j++)//&
棋子左下边