行为型AI:寻找迷宫出口

 

#include <Windows.h>
#include <stack>
using namespace std;

 

const int X=200,Y=100;                            //程序窗口左上角相对于屏幕的坐标  
const int WIDTH=420,HEIGHT=440;    //程序窗口的宽与高
const int rows=8,cols=8;                         //迷宫的行数与列数

 

HDC hdc,mdc,bufdc; 
HBITMAP dra,bg; 

 

DWORD tNow,tPre;             //tPre记录上一次绘图的时间,tNow记录此次准备绘图的时间
char *str=NULL;                   //记录目前搜索状态的字符串指针 

 

int nowPos,prePos;            //分别记录物体目前位置的编号及上一次位置的编号
bool find=false;                    //记录是否找到迷宫出口
stack<int> path;                   //堆栈path,记录移动路径

 

//0代表墙,1代表通道,2代表入口,3代表出口
int mapIndex[rows*cols]={0,2,0,0,0,0,0,0,
       0,1,0,1,1,1,1,0,
       0,1,0,1,0,1,1,0,
       0,1,0,0,0,1,1,0,
       0,1,1,1,1,1,1,0,
       0,1,0,0,0,0,1,0,
       0,0,1,1,1,1,1,0,
       0,0,0,0,0,0,3,0};

 

int record[rows*cols];           //标记迷宫中不可通过的方格(墙),及已走过的方格
void AIRun(HDC);
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);

 

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
 const string szTitle="迷宫";

 WNDCLASS winclass={CS_HREDRAW|CS_VREDRAW,WndProc,0,0,hInstance,LoadIcon(NULL,IDI_APPLICATION),
  LoadCursor(NULL,IDC_ARROW),(HBRUSH)GetStockObject(WHITE_BRUSH),NULL,szTitle.c_str()};

 if(!RegisterClass(&winclass))
  return false;

 HWND hWnd=CreateWindow(szTitle.c_str(),szTitle.c_str(),WS_OVERLAPPEDWINDOW,X,Y,WIDTH,HEIGHT,NULL,NULL,winclass.hInstance,NULL);

 if(0==hWnd)
  return 0;

 ShowWindow(hWnd,SW_SHOWDEFAULT);
 UpdateWindow(hWnd);

 MSG msg;
 ZeroMemory(&msg,sizeof(MSG));

 while(msg.message!=WM_QUIT)
 {
  if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
  {
   TranslateMessage(&msg);
   DispatchMessage(&msg);
  }


  else
  {
   tNow=GetTickCount();        //"tPre"记录前次绘图的时间
   while(tNow-tPre>=100)      //tNow-tRre:当此次循环运行与上次绘图时间相差0.1秒时再进行重绘操作
    AIRun(hdc);
  }
 }
 return msg.wParam;
}

 

LRESULT CALLBACK WndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)
{
 HBITMAP bmp;
 int rowNum,colNum,i,x,y;

 switch(message)
 {
 case WM_CREATE:
  {
   hdc=GetDC(hWnd);
   mdc=CreateCompatibleDC(hdc);
   bufdc=CreateCompatibleDC(hdc);
   bmp=CreateCompatibleBitmap(hdc,WIDTH,HEIGHT);
   SelectObject(mdc,bmp);

 

   //加载位图
   dra=(HBITMAP)LoadImage(NULL,"dra.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE);
   bg=(HBITMAP)LoadImage(NULL,"bg.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE);

 

   //迷宫拼接贴图
   for(i=0;i<rows*cols;i++)
   {
    record[i]=mapIndex[i];        //对record[]数组进行初始化
    rowNum=i/cols;                  //求列编号
    colNum=i%cols;                //求行编号
    x=colNum*50;                    //求贴图的X坐标
    y=rowNum*50;                   //求贴图的Y坐标

    SelectObject(bufdc,bg);

 

    if(!mapIndex[i])        //墙
     BitBlt(mdc,x,y,50,50,bufdc,0,0,SRCCOPY);

    else         //通道
    {
     //找到迷宫出口
     if(mapIndex[i]==2)
     {
      nowPos=i;
      path.push(i);
      record[i]=0;             //设定对应元素值为0,表示此格已走过
     }
     BitBlt(mdc,x,y,50,50,bufdc,0,0,WHITENESS);
    }
   }
   prePos=rows*cols+1;
  }
  break;

 

 case WM_KEYDOWN:
  {
   if(wParam==VK_ESCAPE)
    DestroyWindow(hWnd);
  }
  break;

 

 case WM_DESTROY:
  {
   DeleteDC(bufdc);
   DeleteDC(mdc);
   DeleteObject(dra);
   DeleteObject(bg);
   ReleaseDC(hWnd,hdc);
   PostQuitMessage(0);
  }
  break;

 

 default:
  return DefWindowProc(hWnd,message,wParam,lParam);
 }
 return 0;
}

 

void AIRun(HDC hdc)
{
 int rowNum,colNum,x,y,up,down,left,right;

 

 //按照prePos的值清除前次物体贴图
 rowNum=prePos/cols;
 colNum=prePos%cols;
 x=colNum*50;
 y=rowNum*50;
 SelectObject(bufdc,dra);
 BitBlt(mdc,x,y,50,50,bufdc,0,0,WHITENESS);

 

 //按照nowPre的值进行此次物体贴图
 rowNum=nowPos/cols;
 colNum=nowPos%cols;
 x=colNum*50;
 y=rowNum*50;
 SelectObject(bufdc,dra);
 BitBlt(mdc,x,y,50,50,bufdc,0,0,SRCCOPY);

 

 if(!find)
 {
  str="寻出口中……";

  up=nowPos-cols;
  down=nowPos+cols;
  left=nowPos-1;
  right=nowPos+1;

 

  //移动到最上面一列时,根据目前位置计算出的上方方格编号是否会超出临界编号0
  if(up>=0 && record[up])
  {
   path.push(up); //把方格编号进栈

   //往上走
   record[up]=0; //record数组中对应元素值设为0,表示已走过
   prePos=nowPos;
   nowPos=up;

   if(mapIndex[nowPos]==3)  //判断是否为出口
    find=true;
  }

 

  //移动到最下面一列时,根据目前位置计算出的下方方格编号是否会超出临界编号rows*cols-1
  else if(down<=rows*cols-1 && record[down])
  {
   path.push(down);
   record[down]=0;
   prePos=nowPos;
   nowPos=down;
   if(mapIndex[nowPos]==3)
    find=true;
  }

 

  //移动到最左边一行时,根据物体目前位置计算出左方方格编号是否会超出临界编号rowNum*cols(物体所在列的最小索引值)
  else if(left>=rowNum*cols && record[left])
  {
   path.push(left);
   record[left]=0;
   prePos=nowPos;
   nowPos=left;
   if(mapIndex[nowPos]==3)
    find=true;
  }

 

  //移动到最右边一行时,根据物体目前位置计算出右方方格编号是否会超出临界编号(rowNum+1)*cols-1(物体所在列的最大索引值)
  else if(right<=(rowNum+1)*cols-1 && record[right])
  {
   path.push(right);
   record[right]=0;
   prePos=nowPos;
   nowPos=right;
   if(mapIndex[nowPos]==3)
    find=true;
  }

 

  else
  {
   if(path.size()<=1)           //回到入口
    str="迷宫无出口";

   //退回到前一个重新判断
   else
   {
    path.pop();  //从堆栈删除此格编号
    prePos=nowPos;
    nowPos=path.top(); //往回走
   }
  }
 }


 else
 {
  str="逃脱成功!";
 }

 

 TextOut(mdc,0,0,str,strlen(str));
 BitBlt(hdc,0,0,cols*50,rows*50,mdc,0,0,SRCCOPY);
 tPre=GetTickCount();
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值