用vs2019做了一个2048小游戏,鼠标操作被键盘操作阻塞无法运行

0

问题出在了while循环里面,我的猜想是因为键盘控制影响了鼠标操作,当不进行键盘操作时,就会停在keyDeal这一步,此时无法进行鼠标操作。因此我试着给keyDeal加了判定(现在的代码里面没加):if(_kbhit()),顺利解决了鼠标操作没用的问题。但是另一个问题就是当加了判定之后,就会一直进行gameDraw这一步,造成了闪屏现象。因此我想知道如何解决这一问题,使绘制既能正常运行,也能让鼠标操作生效

用的是VS2019!

#include<stdio.h>
#include<stdlib.h>
#include<graphics.h>
#include<time.h>
#include<math.h>
#include<conio.h>
#include<Windows.h>
#include<mmsystem.h>
#pragma comment(lib,"winmm.lib")

#define GPIO_NUM 4//格子数量4
#define GPIO_W 100//格子宽度
#define INTERVA 17//各自之间的距离
#define GPIO_M GPIO_NUM*GPIO_W+(GPIO_NUM+1)*INTERVA
int map[GPIO_NUM][GPIO_NUM];//使随机数显示在格子上而定义的数组
enum color
{
	zero = RGB(205, 193, 180),
		twoto1 = RGB(238, 228, 218),
		twoto2 = RGB(237, 224, 200),
		twoto3 = RGB(242, 177, 121),
		twoto4 = RGB(245, 149, 99),
		twoto5 = RGB(246, 124, 95),
		twoto6 = RGB(246, 94, 59),
		twoto7 = RGB(242, 177, 121),
		twoto8 = RGB(237, 204, 97),
		twoto9 = RGB(255, 0, 128),
		twoto10 = RGB(145, 0, 72),
		twoto11 = RGB(242, 17, 158),
		back = RGB(187, 173, 160),
};
color arr[13] = { zero,twoto1,twoto2,twoto3,twoto4,twoto5,twoto6,twoto7,twoto8,twoto9,twoto10,twoto11,back };//这个数组可以使格子的颜色随数字变化而变化

//游戏开局产生随机数

int createNum()
{
	srand((unsigned)time(NULL) + clock());
	
	if (rand() % 10 == 1)
	{
		return 4;
	}
	else
	{
		return 2;
	}
	
}

//每移动一次生成一个新的随机数

void ranNum()
{
	while (1)
	{
		int r = rand() % GPIO_NUM;
		int c = rand() % GPIO_NUM;
		if (map[r][c] == 0)
		{
			map[r][c] = createNum();
			break;
		}
	}
}

//初始化数据

void gameInit()
{
	srand((unsigned)time(NULL) + clock());
	for (int i = 0; i < 2;)
	{
		int r = rand() % GPIO_NUM;
		int c = rand() % GPIO_NUM;
		if (map[r][c] == 0)
		{
			map[r][c] = createNum();
			i++;
		}
		map[r][c] = createNum();
	}
}



//这里是自定义函数gameDraw,绘制16个格子



void gameDraw()
{
	setbkcolor(RGB(187, 173, 160));
	cleardevice();
	setfillcolor(BLACK);
	solidrectangle(174, 478, 321, 518);
	
	for (int i = 0; i < GPIO_NUM; i++)
	{
		for (int k = 0; k < GPIO_NUM; k++)
		{
			
			int x = k * GPIO_W + (k + 1) * INTERVA;
			int y = i * GPIO_W + (i + 1) * INTERVA;
			int index = (int)log2((double)map[i][k]);
			COLORREF tcolor = arr[index];
			setfillcolor(tcolor);
			solidroundrect(x, y, x + GPIO_W, y + GPIO_W, 20, 20);
			if (map[i][k] != 0)
			{
				settextstyle(50, 0, "黑体");
				setbkmode(TRANSPARENT);
				settextcolor(RGB(119, 110, 101));
				char str[10] = "";
				sprintf_s(str, "%d", map[i][k]);
				int tw = textwidth(str);
				int th = textheight(str);
				int tx = (GPIO_W - tw) / 2;
				int ty = (GPIO_W - th) / 2;
				outtextxy(x + tx, y + ty, str);
				printf("%d", map[i][k]);
			}
			printf("\n");
		}
		
	}
}



//自定义的moveUP,使随机数执行向上移动的操作

void moveUP()
{
	for (int i = 0; i < GPIO_NUM; i++)
	{
		int temp = 0;
		for (int begin = 1; begin < GPIO_NUM; begin++)
		{
			if (map[begin][i] != 0)
			{
				if (map[temp][i] == 0)
				{
					
					map[temp][i] = map[begin][i];
					map[begin][i] = 0;
				}
				
				else if (map[temp][i] == map[begin][i])
				{
					map[temp][i] += map[begin][i];
					map[begin][i] = 0;
					temp++;
				}
				else
				{
					map[temp + 1][i] = map[begin][i];
					if (temp + 1 != begin)
					{
						map[begin][i] = 0;
						
					}
					
					temp++;
				}
			}
		}
	}
}



//自定义的moveDOWN,使随机数执行向下移动的操作

void moveDOWN()
{
	for (int i = 0; i < GPIO_NUM; i++)
	{
		int temp = 3;
		for (int begin = 2; begin >= 0; begin--)
			if (map[begin][i] != 0)
			{
				if (map[temp][i] == 0)
				{
					
					map[temp][i] = map[begin][i];
					map[begin][i] = 0;
				}
				
				else if (map[temp][i] == map[begin][i])
				{
					map[temp][i] += map[begin][i];
					map[begin][i] = 0;
					temp--;
				}
				else
				{
					map[temp - 1][i] = map[begin][i];
					if (temp - 1 != begin)
					{
						map[begin][i] = 0;
					}
					temp--;
				}
			}
	}
}

//自定义的moveRIGHT,使随机数执行向右移动的操作

void moveRIGHT()
{
	for (int i = 0; i < GPIO_NUM; i++)
	{
		int temp = 3;
		for (int begin = 2; begin >= 0; begin--)
		{
			if (map[i][begin] != 0)
			{
				if (map[i][temp] == 0)
				{
					map[i][temp] = map[i][begin];
					map[i][begin] = 0;
				}
				else if (map[i][temp] == map[i][begin])
				{
					map[i][temp] += map[i][begin];
					map[i][begin] = 0;
					temp--;
				}
				else
				{
					map[i][temp - 1] = map[i][begin];
					if (temp - 1 != begin)
					{
						map[i][begin] = 0;
					}
					temp--;
				}
			}
		}
	}
}

//自定义的moveLEFT,使随机数执行向左移动的操作



void moveLEFT()
{
	for (int i = 0; i < GPIO_NUM; i++)
	{
		int temp = 0;
		for (int begin = 1; begin < GPIO_NUM; begin++)
		{
			if (map[i][begin] != 0)
			{
				if (map[i][temp] == 0)
				{
					
					map[i][temp] = map[i][begin];
					map[i][begin] = 0;
				}
				
				else if (map[i][temp] == map[i][begin])
				{
					map[i][temp] += map[i][begin];
					map[i][begin] = 0;
					temp++;
				}
				else
				{
					map[i][temp + 1] = map[i][begin];
					if (temp + 1 != begin)
					{
						map[i][begin] = 0;
						
					}
					
					temp++;
				}
			}
		}
	}
}

//自定义的keyDeal,与按键绑定,用键盘实现上下左右移动

void keyDeal()
{
	char key = _getch();
	switch (key)
	{
	case 'w':
	case 'W':
	case 72:
		moveUP();
		ranNum();
		break;
	case 's':
	case 'S':
	case 80:
		moveDOWN();
		ranNum();
		break;
	case 'a':
	case 'A':
	case 75:
		moveLEFT();
		ranNum();
		break;
	case 'd':
	case 'D':
	case 77:
		moveRIGHT();
		ranNum();
		break;
	}
}

//自定义mou,当按下左键时,会执行操作,这里我先把他定义为让他播放音乐
void mou()
{
	MOUSEMSG m;
	
	if (MouseHit())
	{
		m = GetMouseMsg();
		if (m.uMsg == WM_LBUTTONDOWN)
		{
			PlaySound("D:\\code\\2048\\1.wav", NULL, SND_FILENAME | SND_ASYNC | SND_LOOP);
			
		}
	}
	
}
int main()
{
	//创建一个窗口
	initgraph(GPIO_M, GPIO_M + 40/*, SHOWCONSOLE*/);
	
	//初始化数据
	
	gameInit();
	
	//开局,生成两个随机数
	
	createNum();
	
	while (1)
	{
		//绘制游戏界面
		
		gameDraw();
		
		//键盘控制数字移动
		
		keyDeal();
		
		//进行鼠标操作
		mou();
		
	}
	closegraph();
	return 0;
}
ava
意亂情迷.

2021-6-26

0

keyDeal() 整个函数阻塞了,导致 mou() 没有及时执行。

应该先用 _kbhit() 判断是否有按键,如果有,再执行 keyDeal()。这样,就能让主循环一直跑起来。同时,你需要给主循环加一个 Sleep,避免 CPU 占用率过高。

ava
慢羊羊

2021-6-26

-1

再创建一个线程专门接收鼠标消息

ava
#$@#$#$

2021-6-27

技术讨论社区