📄 迷宫.cpp
字号:
// 迷宫.cpp : 定义应用程序的入口点。
//
#include "stdafx.h"
#include "迷宫.h"
#include"Stack.cpp"
#include"Graph.cpp"
#include<iostream>
#include<Time.h>
using namespace std;
#define MAX_LOADSTRING 100
// 全局变量:
HINSTANCE hInst; // 当前实例
TCHAR szTitle[MAX_LOADSTRING]; // 标题栏文本
TCHAR szWindowClass[MAX_LOADSTRING]; // 主窗口类名
HBITMAP ball;
clock_t ttPre; //记录之前时间
clock_t ttNow; //记录当前时间
int ttime; //计算时间差
HBITMAP backer; //背景
HBITMAP bmp;
HBITMAP outer; //出口
HDC hdc,mdc,bufdc;
bool keydown; //判断是否重新开始游戏
HBITMAP tile; //墙
wchar_t step[60]; //显示步数
wchar_t timee[60]; //显示时间
wchar_t* automo; //自动生成路径
wchar_t* info; //重新开始
wchar_t* begin; //游戏开始
HWND hWnd;
int curx = 0,cury = 0;
DWORD tPre,tNow;
int nowPos,prePos; //记录当前和上一步的位置
bool find; //是否找到出口
bool autoplay; //判断是否自动生成路径
bool begint; //判断是否开始游戏
int rowNum,colNum;
const int X=700;
const int Y=700;
int up,down;
int COUNT = 0;
int leeft,riight;
SStack<int> path;
Graph mazes;
const int rows = 35;
const int cols = 35;
int mapIndex[rows*cols];
int mapCopy[rows*cols];
int record[rows*cols];
//计算迷宫的路径
// 此代码模块中包含的函数的前向声明:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// TODO: 在此放置代码。
MSG msg;
HACCEL hAccelTable;
// 初始化全局字符串
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_MY, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// 执行应用程序初始化:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_MY));
// 主消息循环:
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int) msg.wParam;
}
//
// 函数: MyRegisterClass()
//
// 目的: 注册窗口类。
//
// 注释:
//
// 仅当希望
// 此代码与添加到 Windows 95 中的“RegisterClassEx”
// 函数之前的 Win32 系统兼容时,才需要此函数及其用法。调用此函数十分重要,
// 这样应用程序就可以获得关联的
// “格式正确的”小图标。
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MY));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCE(IDC_MY);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassEx(&wcex);
}
//生成最短路径函数
void getpath()
{
int count=0;
while(count<cols*rows&&!find)
{
if(!find)
{
rowNum = nowPos/cols;
colNum=nowPos%cols;
up = nowPos - cols;
down = nowPos + cols;
leeft = nowPos - 1;
riight = nowPos +1;
if( up>= 0 && record[up])
{
path.push(up);
record[up] = 0;
prePos = nowPos;
nowPos = up;
if(mapIndex[nowPos] == 3)
find = true;
}
else if(down <=cols*rows - 1 && record[down])
{
path.push(down);
record[down] = 0;
prePos = nowPos;
nowPos = down;
if(mapIndex[nowPos] == 3)
find = true;
}
else if(leeft >= rowNum*cols && record[leeft])
{
path.push(leeft);
record[leeft] = 0;
prePos = nowPos;
nowPos = leeft;
if(mapIndex[nowPos] == 3)
find = true;
}
else if(riight <=(rowNum+1)*cols - 1&& record[riight])
{
path.push(riight);
record[riight] = 0;
prePos = nowPos;
nowPos = riight;
if(mapIndex[nowPos] == 3)
find = true;
}
else
{
if(path.empty())
{
count++;
}
else
{
path.pop();
if(!path.empty())
{
prePos = nowPos;
nowPos = path.top();
}
}
}
}
}
}
//获取随机迷宫
void getMaze()
{
for(int a = 0;a<rows;a++)
{
int* p = mazes.get_Maze(a);
for(int b = 0;b<cols;b++)
{
mapIndex[a*cols+b]=p[b];
}
}
}
//画迷宫图 重新游戏时的初始化
void backPaint()
{
begin = L"BEGIN!";
find = false;
if(keydown )
{
getMaze();
curx = cury = 0;
}
SelectObject(mdc,bmp);
int i,x,y;
for( i = 0;i < rows*cols;i++)
{
record[i] = mapIndex[i];
mapCopy[i]=mapIndex[i];
rowNum = i/cols;
colNum = i%cols;
x = colNum*4*X/(5*rows);y = rowNum*4*X/(5*cols);
if(!mapIndex[i])
{
SelectObject(bufdc,tile);
BitBlt(mdc,x,y,4*X/(5*rows),4*X/(5*cols),bufdc,0,0,SRCCOPY);
}
else
{
if(mapIndex[i]==2)
{
nowPos = i;
path.push(i);
SelectObject(bufdc,tile);
BitBlt(mdc,x,y,4*X/(5*rows),4*X/(5*cols),bufdc,0,0,WHITENESS);
}
else if(mapIndex[i]==3)
{
SelectObject(bufdc,outer);
BitBlt(mdc,x,y,4*X/(5*rows),4*X/(5*cols),bufdc,0,0,SRCCOPY);
}
else
{
SelectObject(bufdc,tile);
BitBlt(mdc,x,y,4*X/(5*rows),4*X/(5*cols),bufdc,0,0,WHITENESS);
}
}
}
prePos = cols*rows+1;
}
void MyPaint(HDC hdc)
{
if(begint)
{
ttPre = ttNow;
ttNow = clock();
ttime+=(ttNow-ttPre)*1.0/CLOCKS_PER_SEC ;
}
else
{
ttime = 0;
}
/*if((curx!=0||cury!=0))
{
SelectObject(bufdc,tile);
if(mapIndex[curx*cols+cury]==1)
BitBlt(mdc,curx*4*X/(5*rows),cury*4*Y/(5*cols),4*X/(5*rows),4*X/(5*cols),bufdc,0,0,SRCCOPY);
else if(mapIndex[curx*cols+cury]==0)
BitBlt(mdc,curx*4*X/(5*rows),cury*4*Y/(5*cols),4*X/(5*rows),4*X/(5*cols),bufdc,0,0,WHITENESS);
}*/
SelectObject(bufdc,backer);
BitBlt(hdc,X*4/5-75,-30,X,Y,bufdc,0,0,SRCCOPY);
int x,y;
//消除上次贴图
rowNum = prePos / cols;
colNum = prePos % cols;
x = colNum*(4*X/(5*rows));
y = rowNum*(4*Y/(5*cols));
SelectObject(bufdc,ball);
BitBlt(mdc,x,y,4*X/(5*rows),4*Y/(5*cols),bufdc,0,0,WHITENESS);
//小球贴图
rowNum = nowPos / cols;
colNum = nowPos%cols;
x=colNum*4*X/(5*rows);
y=rowNum*4*Y/(5*cols);
SelectObject(bufdc,ball);
BitBlt(mdc,x,y,4*X/(5*rows),4*Y/(5*cols),bufdc,0,0,SRCCOPY);
swprintf(step,L"STEPS: %d",COUNT);
TextOut(hdc,X*4/5,200,step,wcslen(step));
swprintf(timee,L"TIME: %d S",ttime);
TextOut(hdc,4*X/5,100,timee,wcslen(timee));
TextOut(hdc,X*4/5,300,info,wcslen(info));
TextOut(hdc,X*4/5,400,automo,wcslen(automo));
TextOut(hdc,4*X/5,500,begin,wcslen(begin));
wchar_t remind[90];
swprintf(remind,L"Total Time : %d S",180-ttime);
TextOut(hdc,4*X/5,600,remind,wcslen(remind));
//重新开始游戏时重新绘制地图 地图随机产生
if(keydown||autoplay)
{
for( int i = 0;i < rows*cols;i++)
{
rowNum = i/cols;
colNum = i%cols;
x = colNum*4*X/(5*rows);y = rowNum*4*X/(5*cols);
if(!mapCopy[i])
{
SelectObject(bufdc,tile);
BitBlt(mdc,x,y,4*X/(5*rows),4*X/(5*cols),bufdc,0,0,SRCCOPY);
}
else
{
if(mapCopy[i]==2)
{
nowPos = i;
path.push(i);
record[i]=0;
SelectObject(bufdc,ball);
BitBlt(mdc,x,y,4*X/(5*rows),4*X/(5*cols),bufdc,0,0,SRCCOPY);
}
else if(mapCopy[i]==3)
{
SelectObject(bufdc,outer);
BitBlt(mdc,x,y,4*X/(5*rows),4*X/(5*cols),bufdc,0,0,SRCCOPY);
}
else if(mapCopy[i]==4)
{
SelectObject(bufdc,ball);
BitBlt(mdc,x,y,4*X/(5*rows),4*X/(5*cols),bufdc,0,0,SRCCOPY);
}
else
{
SelectObject(bufdc,tile);
BitBlt(mdc,x,y,4*X/(5*rows),4*X/(5*cols),bufdc,0,0,WHITENESS);
}
}
}
}
BitBlt(hdc,0,0,cols*4*X/(5*rows),rows*4*Y/(5*cols),mdc,0,0,SRCCOPY);
tPre = GetTickCount();
}
//获取生成的最短路径存入数组
void getRoute()
{
if(path.empty())begin=L"NO WAY!";
while(!path.empty())
{
int current = path.top();
path.pop();
int currentx = current/cols;
int currenty = current%cols;
if(!path.empty())
{
int current1 = path.top();
int current1x = current1;
int current1y = current1;
}
if((mapIndex[current]!=2)||(mapIndex[current]!=3))
mapCopy[current]=4;
}
}
//
// 函数: InitInstance(HINSTANCE, int)
//
// 目的: 保存实例句柄并创建主窗口
//
// 注释:
//
// 在此函数中,我们在全局变量中保存实例句柄并
// 创建和显示主程序窗口。
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance; // 将实例句柄存储在全局变量中
info=L"REPLAY!!";
begin = L"BEGIN!";
automo=L"PLAY AUTOMOLLY!";
for(int a = 0;a<rows;a++)
{
int* p = mazes.get_Maze(a);
for(int b = 0;b<cols;b++)
{
mapIndex[a*cols+b]=p[b];
}
}
hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
if (!hWnd)
{
return FALSE;
}
MoveWindow(hWnd,10,10,X,Y,true);
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
hdc = GetDC(hWnd);
mdc = CreateCompatibleDC(hdc);
bufdc = CreateCompatibleDC(hdc);
bmp = CreateCompatibleBitmap(hdc,cols*4*X/(5*rows),rows*4*X/(5*cols));
tile = (HBITMAP)LoadImage(NULL,L"tile.bmp",IMAGE_BITMAP,4*X/(5*rows),4*X/(5*cols),LR_LOADFROMFILE);
ball = (HBITMAP)LoadImage(NULL,L"ball.bmp",IMAGE_BITMAP,4*X/(5*rows),4*X/(5*cols),LR_LOADFROMFILE);
backer=(HBITMAP)LoadImage(NULL,L"2.bmp",IMAGE_BITMAP,X,Y,LR_LOADFROMFILE);
outer = (HBITMAP)LoadImage(NULL,L"out.bmp",IMAGE_BITMAP,4*X/(5*rows),4*X/(5*cols),LR_LOADFROMFILE);
getMaze();
backPaint();
MyPaint(hdc);
return TRUE;
}
//
// 函数: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// 目的: 处理主窗口的消息。
//
// WM_COMMAND - 处理应用程序菜单
// WM_PAINT - 绘制主窗口
// WM_DESTROY - 发送退出消息并返回
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
switch (message)
{
case WM_KEYDOWN: //键盘输入 利用方向键控制小鼠的移动
if(!find)
{
begin = L"finding..";
switch(wParam)
{
case VK_UP: //向上移动
up = nowPos - cols;
if( up>= 0 && record[up])
{
prePos = nowPos;
nowPos = up;
if(mapIndex[nowPos] == 3)
find = true;
}
else
{
begin= L"BLOCK.";
}
break;
case VK_DOWN: //向下移动
down = nowPos + cols;
if(down <=cols*rows - 1 && record[down])
{
prePos = nowPos;
nowPos = down;
if(mapIndex[nowPos] == 3)
find = true;
}
else
{
begin= L"BLOCK.";
}
break;
case VK_LEFT: //向左移
leeft = nowPos - 1;
if(leeft >= rowNum*cols && record[leeft])
{
prePos = nowPos;
nowPos = leeft;
if(mapIndex[nowPos] == 3)
find = true;
}
else
{
begin= L"BLOCK.";
}
break;
case VK_RIGHT: //向右移
riight = nowPos +1;
if(riight <=(rowNum+1)*cols - 1&& record[riight])
{
prePos = nowPos;
nowPos = riight;
if(mapIndex[nowPos] == 3)
find = true;
}
else
{
begin= L"BLOCK.";
}
break;
}
}
else if(find==true&&ttime<=180){begin=L"YOU WIN";} //找到出口
else if(ttime>180){begin = L"YOU LOSE";}
COUNT++;
keydown = false;
MyPaint(hdc);
break;
case WM_LBUTTONDOWN: //鼠标左击
curx = LOWORD(lParam); //获取当前
cury = HIWORD(lParam); //鼠标的坐标值
if(0<=curx&&curx<=4*X/5&&0<=cury&&cury<=4*Y/5) //墙变路 路变墙
{
curx = curx/(4*X/(5*rows));
cury = cury/(4*Y/(5*cols));
if(mapIndex[curx*cols+cury]==0)
mapIndex[curx*cols+cury]=1;
else if(mapIndex[curx*cols+cury]==1)
mapIndex[curx*cols+cury]=0;
autoplay = false;
keydown = false;
begint = false;
find = false;
backPaint();
MyPaint(hdc);
}
else if(curx>=X*4/5&&curx<=X&&cury>=380&&cury<=420) //自动生成路径
{
curx = cury = 0;
autoplay=true;
keydown = false;
begint = false;
backPaint();
ttime = 0;
backPaint();
getpath();
getRoute();
MyPaint(hdc);
}
else if(curx>=X*4/5&&curx<=X&&cury>=280&&cury<=320) //重新游戏
{
curx = cury = 0;
begin = L"BEGIN";
autoplay = false;
keydown = true;
begint = false;
backPaint();
MyPaint(hdc);
record[1*cols+5]=3;
}
else if(curx>=X*4/5&&curx<=X&&cury>=480&&cury<=520) //开始游戏
{
curx = cury = 0;
ttNow = clock();
begint = true;
}
break;
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// 分析菜单选择:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
MyPaint(hdc);
// TODO: 在此添加任意绘图代码...
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
// “关于”框的消息处理程序。
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
return (INT_PTR)TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
break;
}
return (INT_PTR)FALSE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -