利用C++创建一个游戏(10)maze(代码+注释)

#include "stdafx.h"      
#include "MyGameFrame.h"      
#include <stdio.h>
#include <stack>    //堆栈类

using namespace std;

//定义全局变量
HWND              hWnd;
HINSTANCE         hInst;
HDC               hdc, mdc, bufdc;
HBITMAP           bmp, ball,tile;
DWORD             tPre, tNow;
const int         rows = 8, cols = 8;
int               nowPos;           //当前位置
int               prePos;           //
bool              find_w;
stack<int>        path;
int               record[rows*cols];//记录历史路径

//0表示墙。1表示路径
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 
};

// 此代码模块中包含的函数的前向声明:       
ATOM                MyRegisterClass(HINSTANCE hInstance);
BOOL                InitWindow(HINSTANCE, int);
LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
VOID                AIPaint(HDC hdc);

int APIENTRY WinMain(
	HINSTANCE hInstance,
	HINSTANCE hPrevInstance,
	LPSTR    lpCmdLine,
	int       nCmdShow)
{
	// 初始化全局字符串      
	MyRegisterClass(hInstance);

	// 执行应用程序初始化:       
	if (!InitWindow(hInstance, nCmdShow))//初始化窗口      
	{
		return FALSE;//如果不成功则返回FALSE,并退出程序      
	}

	MSG msg; //创建消息类对象      

	// TODO: 在此放置运行代码。 
	//定义局部变量
	int     rowNum, colNum, i, x, y;

	hdc = GetDC(hWnd);
	mdc = CreateCompatibleDC(hdc);
	bufdc = CreateCompatibleDC(hdc);

	bmp = CreateCompatibleBitmap(hdc, cols * 50, rows * 50);	
	SelectObject(mdc, bmp);

	tile = (HBITMAP)LoadImage(NULL, "tile.bmp", IMAGE_BITMAP, 50, 50, LR_LOADFROMFILE);
	ball = (HBITMAP)LoadImage(NULL, "ball2.bmp", IMAGE_BITMAP, 50, 50, LR_LOADFROMFILE);

	//按照mapIndex 内容拼接位图形成迷宫背景
	for (i = 0; i < rows*cols; i++) {
		record[i] = mapIndex[i];                //记录走过的路径
		rowNum = i / cols;                      //求行号
		colNum = i % cols;                      //求列号
		x = colNum * 50;                        //计算贴图X坐标
		y = rowNum * 50;                        //计算贴图Y坐标
		SelectObject(bufdc, tile);
		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;             //在记录路径中将入口标记为墙
			}
			BitBlt(mdc, x, y, 50, 50, bufdc, 0, 0, WHITENESS);
		}
	}
	prePos = cols * rows + 1;
	AIPaint(hdc);

	// 主消息循环:       
	PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);//赋初值      

	while (msg.message != WM_QUIT)         //进入游戏消息循环:      
	{
		if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
		{
			TranslateMessage(&msg); //获得游戏玩家输入的消息;      
			DispatchMessage(&msg);//分配玩家消息并响应用户消息。      
		}
		else
		{
			tNow = GetTickCount();
			if (tNow - tPre >= 100)
				AIPaint(hdc);
		}
	}

	return (int)msg.wParam;
}


//      
//  函数: MyRegisterClass()      
//      
//  注册Windows类,一款游戏有且仅有一个主窗口,与游戏程序唯一对应。创建游戏窗口前要填写窗口类结构体WNDCLASSEX      
//      
ATOM MyRegisterClass(HINSTANCE hInstance)
{
	WNDCLASSEX wcex =
	{
		wcex.cbSize = sizeof(WNDCLASSEX),


		CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW,

		WndProc,0,0,

		hInstance,

		LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MYGAMEFRAME)),

		LoadCursor(NULL, IDC_ARROW),


		(HBRUSH)(COLOR_WINDOW + 1),NULL,

		_T("GameFrame"),

		LoadIcon(NULL,MAKEINTRESOURCE(IDI_SMALL))
	};
	return RegisterClassEx(&wcex);
}



//      
//   函数: InitInstance(HINSTANCE, int)      
//      
//   目的: 保存实例句柄并创建主窗口      
//      
//   注释:       
//      
//        在此函数中,我们在全局变量中保存实例句柄并      
//        创建和显示主程序窗口。      
//      
BOOL InitWindow(HINSTANCE hInstance, int nCmdShow)
{
	hInst = hInstance; // 将实例句柄存储在全局变量中      

	hWnd = CreateWindow
	(
		_T("GameFrame"),
		_T("游戏框架"),
		WS_OVERLAPPEDWINDOW^WS_THICKFRAME^WS_MAXIMIZEBOX,//普通样式,不能改变大小,不能最大化      
		CW_USEDEFAULT, CW_USEDEFAULT, 427, 450, nullptr, nullptr, hInstance, nullptr
	);

	if (!hWnd)
	{
		return FALSE;
	}

	ShowWindow(hWnd, nCmdShow);
	UpdateWindow(hWnd);

	return TRUE;
}




//      
//  函数: WndProc(HWND, UINT, WPARAM, LPARAM)      
//      
//  目的:    处理主窗口的消息。      
//      
//  WM_COMMAND  - 处理应用程序菜单      
//  WM_PAINT    - 绘制主窗口      
//  WM_DESTROY  - 发送退出消息并返回      
//      
//      
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
	switch (msg)                        //判断消息      
	{
	//esc退出程序  
	case WM_KEYDOWN:
		if (wparam == VK_ESCAPE)
			PostQuitMessage(0);
		break;
	case WM_CREATE:
		//执行初始化代码                    
		return(0);
		break;
	case WM_DESTROY:
		//关闭程序,发送WM_QUIT消息      
		PostQuitMessage(0);
		return(0);
		break;
	default:
		break;
	}
	return (DefWindowProc(hwnd, msg, wparam, lparam));
}


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

	//清除上一次贴图
	rowNum = prePos / cols;                       
	colNum = prePos % cols;

	x = colNum * 50;
	y = rowNum * 50;

	SelectObject(bufdc, ball);

	//绘制墙
	BitBlt(mdc, x, y, 50, 50, bufdc, 0, 0, WHITENESS);       

    //计算小球位置
	rowNum = nowPos / cols;                                 
	colNum = nowPos % cols;
	x = colNum * 50;
	y = rowNum * 50;

	//绘制小球
	SelectObject(bufdc, ball);
	BitBlt(mdc, x, y, 50, 50, bufdc, 0, 0, SRCCOPY);
    
    //回溯算法
	if (!find_w) {
		up = nowPos - cols;                            //减一行
		down = nowPos + cols;                          //加一行
		left = nowPos - 1;                             //减一格
		right = nowPos + 1;                            //增一格

		//往上走
		if (up >= 0 && record[up]) {                            
			path.push(up);                             //向上的方向入栈
			record[up] = 0;                            //历史路径数组中标记为墙,向上方向已走过
			prePos = nowPos;                           //将当前位置记录为历史位置
			nowPos = up;                               //更新位置
			/*找到出口*/
			if (mapIndex[nowPos] == 3)
				find_w = true;
		}                                
		//往下走
		else if (down <= cols * rows - 1 && record[down]) {
			path.push(down);
			record[down] = 0;
			prePos = nowPos;
			nowPos = down;
			/*找到出口*/
			if (mapIndex[nowPos] == 3)
				find_w = true;
		}
		//往左走
		else if (left >= rowNum * cols&&record[left]) { 
			path.push(left);
			record[left] = 0;
			prePos = nowPos;
			nowPos = left;
			/*找到出口*/
			if (mapIndex[nowPos] == 3)
				find_w = true;
		}  
		//往右走
		else if (right <= (rowNum + 1)*cols - 1 && record[right])
		{                                                                          
			path.push(right);
			record[right] = 0;
			prePos = nowPos;
			nowPos = right;
			/*找到出口*/
			if (mapIndex[nowPos] == 3)
				find_w = true;                                 
		}
		//无可移动方格
		//返回上一步
		else {                                                       
			path.pop();              //移除栈顶元素
			prePos = nowPos;
			nowPos = path.top();     //返回栈顶元素
		}
	}
	BitBlt(hdc, 10, 10, cols * 50, rows * 50, mdc, 0, 0, SRCCOPY);
	tPre = GetTickCount();
}

结果如图所示

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值