#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();
}