1、游戏人工智能实验报告四实验四 有限状态机实验实验报告一、实验目的通过蚂蚁世界实验掌握游戏中追有限状态机算法二、实验仪器Windows7系统 Microsoft Visual Studio2015三、实验原理及过程1)制作菜单设置参数:点击会弹出对话框,设置一些参数,红、黑蚂蚁的家会在地图上标记出来运行:设置好参数后点击运行,毒药、食物、水会在地图上随机显示下一步:2只红蚂蚁和2只黑蚂蚁会随机出现在地图上,窗口右方还会出现红、黑蚂蚁当前数量的统计不断按下一步,有限状态机就会不断运行,使蚁群产生变化2)添加加速键资源视图中下方选择ID和键值3)新建头文件def.h 在AntView.cpp中加入#
2、include def.h与本实验有关的数据大都是在这里定义的int flag=0;#define kForage 1#define kGoHome 2#define kThirsty 3#define kDead 4#define kMaxEntities 200class ai_Entitypublic: int type; int state; int row; int col; ai_Entity(); ai_Entity() void New (int theType,int theState,int theRow,int theCol); void Forage(); void G
3、oHome(); void Thirsty(); void Dead();ai_Entity entityListkMaxEntities;#define kRedAnt 1#define kBlackAnt 2int RedHomeRow;int RedHomeCol;int BlackHomeRow;int BlackHomeCol;int RedNum=2;int BlackNum=2;/地图大小,可改变#define kMaxRows 30#define kMaxCols 40#define LENGTH 20int terrainkMaxRowskMaxCols;#define kG
4、round 1#define kWater 2#define kBlackHome 3#define kRedHome 4#define kPoison 5#define kFood 6/ai_Entity类中函数的定义ai_Entity:ai_Entity() type=0; state=0; row=0; col=0;int Rnd(int min, int max)/不能产生负数 int result; do result=rand()%max; while(result=min); return result;void ai_Entity:New (int theType,int th
5、eState,int theRow,int theCol) type=theType; row=theRow; col=theCol; state=theState;void ai_Entity:Forage() int rowMove; int colMove; int newRow; int newCol; int foodRow; int foodCol; int poisonRow; int poisonCol; rowMove=Rnd(-1,3)-1; colMove=Rnd(-1,3)-1; newRow=row+rowMove; newCol=col+colMove; if(ne
6、wRow0) return; if(newCol=kMaxRows) return; if(newCol=kMaxCols) return; if(terrainnewRownewCol=kGround)|(terrainnewRownewCol=kWater) row=newRow; col=newCol; if(terrainnewRownewCol=kFood) row=newRow; col=newCol; terrainrowcol=kGround; state=kGoHome; do foodRow=Rnd(-1,kMaxRows); foodCol=Rnd(-1,kMaxCols
7、); while(terrainfoodRowfoodCol!=kGround); terrainfoodRowfoodCol=kFood; if(terrainnewRownewCol=kPoison) row=newRow; col=newCol; terrainrowcol=kGround; state=kDead; do poisonRow=Rnd(-1,kMaxRows); poisonCol=Rnd(-1,kMaxCols); while(terrainpoisonRowpoisonCol!=kGround); terrainpoisonRowpoisonCol=kPoison;
8、void ai_Entity:GoHome() int rowMove; int colMove; int newRow; int newCol; int homeRow; int homeCol; int poisonRow; int poisonCol; int i; if(type=kRedAnt) homeRow=RedHomeRow; homeCol=RedHomeCol; else homeRow=BlackHomeRow; homeCol=BlackHomeCol; if(rowhomeRow) rowMove=-1; else rowMove=0; if(colhomeCol)
9、 colMove=-1; else colMove=0; newRow=row+rowMove; newCol=col+colMove; if(newRow0) return; if(newCol=kMaxRows) return; if(newCol=kMaxCols) return; if(terrainnewRownewCol!=kPoison) row=newRow; col=newCol; else row=newRow; col=newCol; terrainrowcol=kGround; state=kDead; do poisonRow=Rnd(-1,kMaxRows); po
10、isonCol=Rnd(-1,kMaxCols); while(terrainpoisonRowpoisonCol!=kGround); terrainpoisonRowpoisonCol=kPoison; if(newRow=homeRow)&(newCol=homeCol) row=newRow; col=newCol; state=kThirsty; for(i=0;ikMaxEntities;i+) if(entityListi.type=0) entityListi.New(type,kForage,homeRow,homeCol); if(type=kRedAnt) RedNum+
11、; if(type=kBlackAnt) BlackNum+; break; void ai_Entity:Thirsty() int rowMove; int colMove; int newRow; int newCol; int foodRow; int foodCol; int poisonRow; int poisonCol; rowMove=Rnd(-1,3)-1; colMove=Rnd(-1,3)-1; newRow=row+rowMove; newCol=col+colMove; if(newRow0) return; if(newCol=kMaxRows) return;
12、if(newCol=kMaxCols) return; if(terrainnewRownewCol=kGround)|(terrainnewRownewCol=kFood) row=newRow; col=newCol; if(terrainnewRownewCol=kWater) row=newRow; col=newCol; terrainrowcol=kGround; state=kForage; do foodRow=Rnd(-1,kMaxRows); foodCol=Rnd(-1,kMaxCols); while(terrainfoodRowfoodCol!=kGround); t
13、errainfoodRowfoodCol=kWater; if(terrainnewRownewCol=kPoison) row=newRow; col=newCol; terrainrowcol=kGround; state=kDead; do poisonRow=Rnd(-1,kMaxRows); poisonCol=Rnd(-1,kMaxCols); while(terrainpoisonRowpoisonCol!=kGround); terrainpoisonRowpoisonCol=kPoison; void ai_Entity:Dead() if(type=kRedAnt) Red
14、Num-; if(type=kBlackAnt) BlackNum-; type=0;4)制作对话框添加资源,拖动控件9个静态文本框,7个编辑框右键对话框添加类InputDlg,添加成员变量int m_RedHomeRow; int m_RedHomeCol; int m_BlackHomeRow; int m_BlackHomeCol; int m_food; int m_water;int m_poison;在AntView.cpp中加入#include InputDlg.h5)对菜单项添加事件给CAntView类添加一些成员变量没做说明都是添加到CAntView类,没做说明都是COMMA
15、ND事件。设置参数:点击出现对话框,输入值,确定后赋给CAntView的成员变量,刷新窗口void CAntView:OnData() / TODO: 在此添加命令处理程序代码 InputDlg dlg; if(dlg.DoModal()=IDOK) RedHomeRow=kRedHomeRow=dlg.m_RedHomeRow; RedHomeCol=kRedHomeCol=dlg.m_RedHomeCol; BlackHomeRow=kBlackHomeRow=dlg.m_BlackHomeRow; BlackHomeCol=kBlackHomeCol=dlg.m_BlackHomeCol
16、; kMaxWater=dlg.m_water; kMaxFood=dlg.m_food; kMaxPoison=dlg.m_poison; if(kRedHomeRow=kMaxRows|kBlackHomeRow=kMaxRows|kRedHomeCol=kMaxCols|kBlackHomeCol=kMaxCols |kRedHomeRow0|kBlackHomeRow0|kRedHomeCol0|kBlackHomeCol0 |kRedHomeRow=kBlackHomeRow&kRedHomeCol=kBlackHomeCol) AfxMessageBox(L输入坐标不合法,请重新输
17、入!); return; flag=1; Invalidate();运行:初始化数组,随机生成毒药、事物、水,刷新窗口void CAntView:OnRun() / TODO: 在此添加命令处理程序代码 if(flag=0) AfxMessageBox(L还未设置蚂蚁家的位置!); return ; if(flag!=1) return ; int i,j; for(i=0;ikMaxRows;i+) for(j=0;jkMaxCols;j+) terrainij=kGround; terrainkRedHomeRowkRedHomeCol=kRedHome; terrainkBlackHom
18、eRowkBlackHomeCol=kBlackHome; srand(time(NULL); /取系统时间为随机种子 int r,c; for(i=0;ikMaxWater;i+) r=Rnd(-1,kMaxRows); c=Rnd(-1,kMaxCols); if(terrainrc=kGround) terrainrc=kWater; else i-; for(i=0;ikMaxPoison;i+) r=Rnd(-1,kMaxRows); c=Rnd(-1,kMaxCols); if(terrainrc=kGround) terrainrc=kPoison; else i-; for(i
19、=0;ikMaxFood;i+) r=Rnd(-1,kMaxRows); c=Rnd(-1,kMaxCols); if(terrainrc=kGround) terrainrc=kFood; else i-; flag=2; Invalidate();下一步:有限状态机的核心代码,刷新窗口void CAntView:OnNext() / TODO: 在此添加命令处理程序代码 if(flag=2) /kGround才能新建 int x,y; for(int i=0;i2;i+) x=Rnd(-1,kMaxCols); y=Rnd(-1,kMaxRows); if(terrainyx=kGroun
20、d) entityListi.New(kRedAnt,kForage,y,x); else i-; for(int i=2;i4;i+) x=Rnd(-1,kMaxCols); y=Rnd(-1,kMaxRows); if(terrainyx=kGround) entityListi.New(kBlackAnt,kForage,y,x); else i-; flag=3; else for(int i=0;ikMaxEntities;i+) switch(entityListi.state) case kForage: entityListi.Forage(); break; case kGo
21、Home: entityListi.GoHome(); break; case kThirsty: entityListi.Thirsty(); break; case kDead: entityListi.Dead(); break; default: break; Invalidate();6)OnDraw函数flag是标志变量,便于控制绘图void CAntView:OnDraw(CDC* pDC) CAntDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); if (!pDoc) return; / TODO: 在此处为本机数据添加绘制代码 in
22、t i,j; /绘制网格 for(i=0;iMoveTo(0,i); pDC-LineTo(LENGTH*kMaxCols,i); for(i=0;iMoveTo(i,0); pDC-LineTo(i,LENGTH*kMaxRows); /画出红黑房子 if(flag=1) pDC-TextOutW(kBlackHomeCol*LENGTH+1,kBlackHomeRow*LENGTH+1,LH); pDC-SetTextColor(RGB(255,0,0); pDC-TextOutW(kRedHomeCol*LENGTH+1,kRedHomeRow*LENGTH+1,LH); pDC-Set
23、TextColor(RGB(0,0,0); if(flag=2)/遍历数组在相应位置显示图片(水滴、骷髅、苹果) CDC dcMemory; dcMemory.CreateCompatibleDC(pDC); CBitmap bmp1,bmp2,bmp3; BITMAP bmpInfo1,bmpInfo2,bmpInfo3; bmp1.LoadBitmapW(IDB_BITMAP1); bmp1.GetBitmap(&bmpInfo1); bmp2.LoadBitmapW(IDB_BITMAP2); bmp2.GetBitmap(&bmpInfo2); bmp3.LoadBitmapW(IDB
24、_BITMAP3); bmp3.GetBitmap(&bmpInfo3); CBitmap *pOldBitmap=dcMemory.SelectObject(&bmp1); for(i=0;ikMaxRows;i+) for(j=0;jStretchBlt(j*LENGTH+1,i*LENGTH+1,19,19,&dcMemory,0,0,bmpInfo1.bmWidth,bmpInfo1.bmHeight,SRCCOPY); else if(terrainij=kPoison) dcMemory.SelectObject(&bmp2); pDC-StretchBlt(j*LENGTH+1,
25、i*LENGTH+1,19,19,&dcMemory,0,0,bmpInfo2.bmWidth,bmpInfo2.bmHeight,SRCCOPY); else if(terrainij=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) /绘制蚂蚁 CDC dcMemory; dcMemory.CreateCompatibleDC(pDC); CBitmap bmp1,bmp2; BITMAP bmpInfo1,bmpInfo2; bmp1.LoadBitmapW(IDB_BITMAP4); bmp1.GetBitmap(&bmpInfo1); bmp2.LoadBitmapW(IDB_BITMAP5); bmp2.GetBitmap(&bmpInfo2); CBitmap *pOldBitmap=dcMemory.SelectObject(&bmp1); for(i=0;ikMaxEntities;i+) if(entityListi.type=kRedAnt)