C++ Windows编程实现贪吃蛇(可用Dev C++实现)

最近学习Windows编程,试着自己做了个简单的贪吃蛇游戏。不到300行代码,把Windows消息机制,绘制方法,多线程等知识都用上了,适合初学者入门。效果图如下:

C++ Windows编程实现贪吃蛇(可用Dev C++实现)_第1张图片

完整代码附注释:

#include 
#include 
#include 
#include
#include

#define SIZE 20    //指定游戏地图大小为20*20
#define WIDTH 15    //指定每个格子的大小
#define FPS 10    //每秒刷新多少次
#define SPEED 3    //每刷新多少次蛇移动一格

HWND m_hwnd;//窗口句柄,唯一标示游戏窗口
int g_nWidth = WIDTH*SIZE+10, g_nHeight = WIDTH*SIZE+33;//指定窗口大小
int map[SIZE][SIZE];//地图数组,值为0表示空,1表示蛇身,2表示苹果
std::vector x,y;//用于保存蛇身体每一个部位的位置
int ax,ay;//苹果的位置
int px,py;//最后一次蛇经过的位置,用于吃过苹果后加长蛇身
int dir;//表明当前方向
unsigned long long tk;//游戏ticket数,即已经过多少逻辑帧
bool lock;//操作锁,防止一次刷新操作两次

void init(){//初始化参数
	srand((unsigned)time(NULL));
	tk = 0;
	dir = 2;
	x.push_back(0);
	y.push_back(0);
	px = py = 0;
	ax = -1;
	memset(map,0,sizeof(map));
	map[0][0] = 1;
	lock = false;
}

void gameover(){//输了时调用
	MessageBox(m_hwnd,"你输了","游戏结束",MB_OK);//弹窗
	x.clear();//重新初始化
	y.clear();
	init();
}

void youwin(){//赢了时调用
	MessageBox(m_hwnd,"你赢了","游戏结束",MB_OK);
	x.clear();
	y.clear();
	init();
}

void move(int d){//调用次函数以移动
	if(d == 0&&x[0]>0){//当移动方向为上并且移动合法时,保存并去掉蛇尾,加一格蛇头
		x.insert(x.begin(),x[0]-1);
		px = x[x.size()-1];
		x.erase(x.begin()+x.size()-1);
		y.insert(y.begin(),y[0]);
		py = y[y.size()-1];
		y.erase(y.begin()+y.size()-1);
	}
	else if(d == 0&&x[0]<=0)gameover();//当移动不合法时游戏结束
	else if(d == 2&&x[0]=SIZE-1)gameover();
	else if(d == 1&&y[0]>0){
		x.insert(x.begin(),x[0]);
		px = x[x.size()-1];
		x.erase(x.begin()+x.size()-1);
		y.insert(y.begin(),y[0]-1);
		py = y[y.size()-1];
		y.erase(y.begin()+y.size()-1);
	}
	else if(d == 1&&y[0]<=0)gameover();
	else if(d == 3&&y[0]=SIZE-1)gameover();
}

void update(){//游戏更新主逻辑,每帧调用此函数
	if(tk%SPEED==0){//每隔SPEED间隔帧移动一次
		move(dir);
		lock = false;
	}
	if(x[0]==ax&&y[0]==ay){//如果吃到了苹果
		x.push_back(px);//加蛇尾
		y.push_back(py);
		ax = -1;//去掉苹果
	}
	if(x.size()>=SIZE*SIZE){//如果蛇的长度大于等于地图大小,游戏结束
		youwin();
		return;
	}
	memset(map,0,sizeof(map));//刷新地图
	for(int i = 0; i < x.size(); i++){
		if(map[x[i]][y[i]]==0)map[x[i]][y[i]] = 1;//如果没有蛇身阻挡则放置蛇身
		else{//否则游戏结束
			gameover();
			return;
		}
	}
	if(ax==-1){//苹果被吃,刷新苹果
		ax = rand()%SIZE;
		ay = rand()%SIZE;
		while(map[ax][ay]==1){
			ax = rand()%SIZE;
			ay = rand()%SIZE;
		}
	}
	map[ax][ay] = 2;
	tk++;
}

/* 此函数用于处理窗口接受的所有消息 */
LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) {
	switch(Message) {
		
		/* Upon destruction, tell the main thread to stop */
		case WM_DESTROY: {
			PostQuitMessage(0);
			break;
		}
		
		case WM_KEYDOWN:{//当收到按键消息
			if(!lock){//且操作锁没有锁上,则改变蛇的移动方向并上锁
				if(wParam == VK_UP&&(dir-0)%2!=0){
					dir = 0;
					lock = true;
				}
				else if(wParam == VK_DOWN&&(dir-2)%2!=0){
					dir = 2;
					lock = true;
				}
				else if(wParam == VK_LEFT&&(dir-1)%2!=0){
					dir = 1;
					lock = true;
				}
				else if(wParam == VK_RIGHT&&(dir-3)%2!=0){
					dir = 3;
					lock = true;
				}
			}
			if(wParam == VK_ESCAPE)PostQuitMessage(0);//如果是ESC键则退出
			break;
		}
		
		/* All other messages (a lot of them) are processed using default procedures */
		default:
			return DefWindowProc(hwnd, Message, wParam, lParam);
	}
	return 0;
}

void render()//渲染函数,用于绘制游戏图像
{  
    HDC hDC = GetDC(m_hwnd);//定义窗口句柄的DC
  
    HDC memDC = CreateCompatibleDC(0);//定义兼容DC
  
    HBITMAP bmpBack = CreateCompatibleBitmap(hDC,g_nWidth,g_nHeight);//定义位图画布
    SelectObject(memDC,bmpBack);
  
    HPEN penBack = CreatePen(PS_SOLID,1,RGB(0,0,0));//定义画笔
    SelectObject(memDC,penBack);
  
    HBRUSH brushBack = CreateSolidBrush(RGB(255,255,255));//定义背景画刷
    SelectObject(memDC,brushBack);
  
    RECT rcClient;
    GetClientRect(m_hwnd,&rcClient);
    FillRect(memDC,&rcClient,brushBack);//用背景画刷以矩形填充整个窗口
    HBRUSH brushObj = CreateSolidBrush(RGB(255,0,0));//定义蛇身画刷
    HBRUSH brushApple = CreateSolidBrush(RGB(0,0,255));//定义苹果画刷
    int dw = WIDTH;  
    int rows = SIZE;  
    int cols = SIZE;  
    for (int r=0; r 0) { /* If no error is received... */
		TranslateMessage(&msg); /* Translate key codes to chars if present */
		DispatchMessage(&msg); /* Send it to WndProc */
	}
	return msg.wParam;
}

你可能感兴趣的:(随便做的小玩意)