游戏人工智能实验报告四.docx
《游戏人工智能实验报告四.docx》由会员分享,可在线阅读,更多相关《游戏人工智能实验报告四.docx(37页珍藏版)》请在冰点文库上搜索。
游戏人工智能实验报告四
实验四有限状态机实验
实验报告
一、实验目的
通过蚂蚁世界实验掌握游戏中追有限状态机算法
二、实验仪器
Windows7系统
MicrosoftVisualStudio2015
三、实验原理及过程
1)制作菜单
设置参数:
点击会弹出对话框,设置一些参数,红、黑蚂蚁的家会在地图上标记出来
运行:
设置好参数后点击运行,毒药、食物、水会在地图上随机显示
下一步:
2只红蚂蚁和2只黑蚂蚁会随机出现在地图上,窗口右方还会出现红、黑蚂蚁当前数量的统计
不断按下一步,有限状态机就会不断运行,使蚁群产生变化
2)添加加速键
资源视图中
下方
选择ID和键值
3)新建头文件def.h
在AntView.cpp中加入#include"def.h"
与本实验有关的数据大都是在这里定义的
intflag=0;
#definekForage1
#definekGoHome2
#definekThirsty3
#definekDead4
#definekMaxEntities200
classai_Entity{
public:
inttype;
intstate;
introw;
intcol;
ai_Entity();
~ai_Entity(){}
voidNew(inttheType,inttheState,inttheRow,inttheCol);
voidForage();
voidGoHome();
voidThirsty();
voidDead();
};
ai_EntityentityList[kMaxEntities];
#definekRedAnt1
#definekBlackAnt2
intRedHomeRow;
intRedHomeCol;
intBlackHomeRow;
intBlackHomeCol;
intRedNum=2;
intBlackNum=2;
//地图大小,可改变
#definekMaxRows30
#definekMaxCols40
#defineLENGTH20
intterrain[kMaxRows][kMaxCols];
#definekGround1
#definekWater2
#definekBlackHome3
#definekRedHome4
#definekPoison5
#definekFood6
//ai_Entity类中函数的定义
ai_Entity:
:
ai_Entity()
{
type=0;
state=0;
row=0;
col=0;
}
intRnd(intmin,intmax)//不能产生负数
{
intresult;
do{
result=rand()%max;
}while(result<=min);
returnresult;
}
voidai_Entity:
:
New(inttheType,inttheState,inttheRow,inttheCol)
{
type=theType;
row=theRow;
col=theCol;
state=theState;
}
voidai_Entity:
:
Forage()
{
introwMove;
intcolMove;
intnewRow;
intnewCol;
intfoodRow;
intfoodCol;
intpoisonRow;
intpoisonCol;
rowMove=Rnd(-1,3)-1;
colMove=Rnd(-1,3)-1;
newRow=row+rowMove;
newCol=col+colMove;
if(newRow<0)
return;
if(newCol<0)
return;
if(newRow>=kMaxRows)
return;
if(newCol>=kMaxCols)
return;
if((terrain[newRow][newCol]==kGround)||(terrain[newRow][newCol]==kWater))
{
row=newRow;
col=newCol;
}
if(terrain[newRow][newCol]==kFood)
{
row=newRow;
col=newCol;
terrain[row][col]=kGround;
state=kGoHome;
do{
foodRow=Rnd(-1,kMaxRows);
foodCol=Rnd(-1,kMaxCols);
}while(terrain[foodRow][foodCol]!
=kGround);
terrain[foodRow][foodCol]=kFood;
}
if(terrain[newRow][newCol]==kPoison)
{
row=newRow;
col=newCol;
terrain[row][col]=kGround;
state=kDead;
do{
poisonRow=Rnd(-1,kMaxRows);
poisonCol=Rnd(-1,kMaxCols);
}while(terrain[poisonRow][poisonCol]!
=kGround);
terrain[poisonRow][poisonCol]=kPoison;
}
}
voidai_Entity:
:
GoHome()
{
introwMove;
intcolMove;
intnewRow;
intnewCol;
inthomeRow;
inthomeCol;
intpoisonRow;
intpoisonCol;
inti;
if(type==kRedAnt)
{
homeRow=RedHomeRow;
homeCol=RedHomeCol;
}
else
{
homeRow=BlackHomeRow;
homeCol=BlackHomeCol;
}
if(rowrowMove=1;
elseif(row>homeRow)
rowMove=-1;
else
rowMove=0;
if(colcolMove=1;
elseif(col>homeCol)
colMove=-1;
else
colMove=0;
newRow=row+rowMove;
newCol=col+colMove;
if(newRow<0)
return;
if(newCol<0)
return;
if(newRow>=kMaxRows)
return;
if(newCol>=kMaxCols)
return;
if(terrain[newRow][newCol]!
=kPoison)
{
row=newRow;
col=newCol;
}
else
{
row=newRow;
col=newCol;
terrain[row][col]=kGround;
state=kDead;
do{
poisonRow=Rnd(-1,kMaxRows);
poisonCol=Rnd(-1,kMaxCols);
}while(terrain[poisonRow][poisonCol]!
=kGround);
terrain[poisonRow][poisonCol]=kPoison;
}
if((newRow==homeRow)&&(newCol==homeCol))
{
row=newRow;
col=newCol;
state=kThirsty;
for(i=0;iif(entityList[i].type==0)
{
entityList[i].New(type,kForage,homeRow,homeCol);
if(type==kRedAnt)
RedNum++;
if(type==kBlackAnt)
BlackNum++;
break;
}
}
}
voidai_Entity:
:
Thirsty()
{
introwMove;
intcolMove;
intnewRow;
intnewCol;
intfoodRow;
intfoodCol;
intpoisonRow;
intpoisonCol;
rowMove=Rnd(-1,3)-1;
colMove=Rnd(-1,3)-1;
newRow=row+rowMove;
newCol=col+colMove;
if(newRow<0)
return;
if(newCol<0)
return;
if(newRow>=kMaxRows)
return;
if(newCol>=kMaxCols)
return;
if((terrain[newRow][newCol]==kGround)||(terrain[newRow][newCol]==kFood))
{
row=newRow;
col=newCol;
}
if(terrain[newRow][newCol]==kWater)
{
row=newRow;
col=newCol;
terrain[row][col]=kGround;
state=kForage;
do{
foodRow=Rnd(-1,kMaxRows);
foodCol=Rnd(-1,kMaxCols);
}while(terrain[foodRow][foodCol]!
=kGround);
terrain[foodRow][foodCol]=kWater;
}
if(terrain[newRow][newCol]==kPoison)
{
row=newRow;
col=newCol;
terrain[row][col]=kGround;
state=kDead;
do{
poisonRow=Rnd(-1,kMaxRows);
poisonCol=Rnd(-1,kMaxCols);
}while(terrain[poisonRow][poisonCol]!
=kGround);
terrain[poisonRow][poisonCol]=kPoison;
}
}
voidai_Entity:
:
Dead()
{
if(type==kRedAnt)
RedNum--;
if(type==kBlackAnt)
BlackNum--;
type=0;
}
4)制作对话框
添加资源,拖动控件
9个静态文本框,7个编辑框
右键对话框添加类InputDlg,添加成员变量
intm_RedHomeRow;
intm_RedHomeCol;
intm_BlackHomeRow;
intm_BlackHomeCol;
intm_food;
intm_water;
intm_poison;
在AntView.cpp中加入#include"InputDlg.h"
5)对菜单项添加事件
给CAntView类添加一些成员变量
没做说明都是添加到CAntView类,没做说明都是COMMAND事件。
设置参数:
点击出现对话框,输入值,确定后赋给CAntView的成员变量,刷新窗口
voidCAntView:
:
OnData()
{
//TODO:
在此添加命令处理程序代码
InputDlgdlg;
if(dlg.DoModal()==IDOK)
{
RedHomeRow=kRedHomeRow=dlg.m_RedHomeRow;
RedHomeCol=kRedHomeCol=dlg.m_RedHomeCol;
BlackHomeRow=kBlackHomeRow=dlg.m_BlackHomeRow;
BlackHomeCol=kBlackHomeCol=dlg.m_BlackHomeCol;
kMaxWater=dlg.m_water;
kMaxFood=dlg.m_food;
kMaxPoison=dlg.m_poison;
}
if(kRedHomeRow>=kMaxRows||kBlackHomeRow>=kMaxRows||kRedHomeCol>=kMaxCols||kBlackHomeCol>=kMaxCols
||kRedHomeRow<0||kBlackHomeRow<0||kRedHomeCol<0||kBlackHomeCol<0
||kRedHomeRow==kBlackHomeRow&&kRedHomeCol==kBlackHomeCol)
{
AfxMessageBox(L"输入坐标不合法,请重新输入!
");
return;
}
flag=1;
Invalidate();
}
运行:
初始化数组,随机生成毒药、事物、水,刷新窗口
voidCAntView:
:
OnRun()
{
//TODO:
在此添加命令处理程序代码
if(flag==0)
{
AfxMessageBox(L"还未设置蚂蚁家的位置!
");
return;
}
if(flag!
=1)
return;
inti,j;
for(i=0;ifor(j=0;j{
terrain[i][j]=kGround;
}
terrain[kRedHomeRow][kRedHomeCol]=kRedHome;
terrain[kBlackHomeRow][kBlackHomeCol]=kBlackHome;
srand(time(NULL));//取系统时间为随机种子
intr,c;
for(i=0;i{
r=Rnd(-1,kMaxRows);
c=Rnd(-1,kMaxCols);
if(terrain[r][c]==kGround)
terrain[r][c]=kWater;
else
i--;
}
for(i=0;i{
r=Rnd(-1,kMaxRows);
c=Rnd(-1,kMaxCols);
if(terrain[r][c]==kGround)
terrain[r][c]=kPoison;
else
i--;
}
for(i=0;i{
r=Rnd(-1,kMaxRows);
c=Rnd(-1,kMaxCols);
if(terrain[r][c]==kGround)
terrain[r][c]=kFood;
else
i--;
}
flag=2;
Invalidate();
}
下一步:
有限状态机的核心代码,刷新窗口
voidCAntView:
:
OnNext()
{
//TODO:
在此添加命令处理程序代码
if(flag==2)
{
//kGround才能新建
intx,y;
for(inti=0;i<2;i++)
{
x=Rnd(-1,kMaxCols);
y=Rnd(-1,kMaxRows);
if(terrain[y][x]==kGround)
{
entityList[i].New(kRedAnt,kForage,y,x);
}
else
i--;
}
for(inti=2;i<4;i++)
{
x=Rnd(-1,kMaxCols);
y=Rnd(-1,kMaxRows);
if(terrain[y][x]==kGround)
{
entityList[i].New(kBlackAnt,kForage,y,x);
}
else
i--;
}
flag=3;
}
else
{
for(inti=0;i{
switch(entityList[i].state)
{
casekForage:
entityList[i].Forage();
break;
casekGoHome:
entityList[i].GoHome();
break;
casekThirsty:
entityList[i].Thirsty();
break;
casekDead:
entityList[i].Dead();
break;
default:
break;
}
}
}
Invalidate();
}
6)OnDraw函数
flag是标志变量,便于控制绘图
voidCAntView:
:
OnDraw(CDC*pDC)
{
CAntDoc*pDoc=GetDocument();
ASSERT_VALID(pDoc);
if(!
pDoc)
return;
//TODO:
在此处为本机数据添加绘制代码
inti,j;
//绘制网格
for(i=0;i<=LENGTH*kMaxRows;i+=LENGTH)
{
//画横线
pDC->MoveTo(0,i);
pDC->LineTo(LENGTH*kMaxCols,i);
}
for(i=0;i<=LENGTH*kMaxCols;i+=LENGTH)
{
//画竖线
pDC->MoveTo(i,0);
pDC->LineTo(i,LENGTH*kMaxRows);
}
//画出红黑房子
if(flag>=1)
{
pDC->TextOutW(kBlackHomeCol*LENGTH+1,kBlackHomeRow*LENGTH+1,L"H");
pDC->SetTextColor(RGB(255,0,0));
pDC->TextOutW(kRedHomeCol*LENGTH+1,kRedHomeRow*LENGTH+1,L"H");
pDC->SetTextColor(RGB(0,0,0));
}
if(flag>=2)//遍历数组在相应位置显示图片(水滴、骷髅、苹果)
{
CDCdcMemory;
dcMemory.CreateCompatibleDC(pDC);
CBitmapbmp1,bmp2,bmp3;
BITMAPbmpInfo1,bmpInfo2,bmpInfo3;
bmp1.LoadBitmapW(IDB_BITMAP1);
bmp1.GetBitmap(&bmpInfo1);
bmp2.LoadBitmapW(IDB_BITMAP2);
bmp2.GetBitmap(&bmpInfo2);
bmp3.LoadBitmapW(IDB_BITMAP3);
bmp3.GetBitmap(&bmpInfo3);
CBitmap*pOldBitmap=dcMemory.SelectObject(&bmp1);
for(i=0;i{
for(j=0;j{
if(terrain[i][j]==kWater)
{
dcMemory.SelectObject(&bmp1);
pDC->StretchBlt(j*LENGTH+1,i*LENGTH+1,19,19,&dcMemory,0,0,bmpInfo1.bmWidth,bmpInfo1.bmHeight,SRCCOPY);
}
elseif(terrain[i][j]==kPoison)
{
dcMemory.SelectObject(&bmp2);
pDC->StretchBlt(j*LENGTH+1,i*LENGTH+1,19,19,&dcMemory,0,0,bmpInfo2.bmWidth,bmpInfo2.bmHeight,SRCCOPY);
}
elseif(terrain[i][j]==kFood)
{
dcMemory.SelectObject(&bmp3);
pDC->StretchBlt(j*LENGTH+1,i*LENGTH+1,18,18,&dcMemory,0,0,bmpInfo3.bmWidth,bmpInfo3.bmHeight,SRCCOPY);
}
}
}
dcMemory.SelectObject(pOldBitmap);
}
if(flag>=3)//绘制蚂蚁
{
CDCdcMemory;
dcMemory.CreateCompatibleDC(pDC);
CBitmapbmp1,bmp2;
BITMAPbmpInfo1,bmpInfo2;
bmp1.LoadBitmapW(IDB_BITMAP4);
bmp1.GetBitmap(&bmpInfo1);
bmp2.LoadBitmapW(IDB_BITMAP5);
bmp2.GetBitmap(&bmpInfo2);
CBitmap*pOldBitmap=dcMemory.SelectObject(&bmp1);
for(i=0;i{
if(entityList[i].type==kRedAnt)