使用多线程用二维数组模拟打字母游戏。

【主要思路和说明】:

1,使用俩个线程,一个线程用来更新二维数组->把之前在第0行的数据下移一行,在现在的第0行的随机列更新随机字母,清屏后,打印当前二维数组的数据。一个线程用来接受用户的输入,从最后一行往第一行遍历遇到于用户属于相同的字母消除字母(把它的位置的值置为0).

2,我定义了11行10列的二维数组,第十一行的数据主要是用来判断游戏是否结束。

3,只要游戏不结束就一直创建线程来等待用户输入。

4,使用CRITICAL_SECTION 把可能由多个线程同时修改的变量的操作放在临界区,防止出现异常。

【代码】:


#define  _CRT_SECURE_NO_WARNINGS 
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdbool.h>
#include <windows.h>
#include <conio.h>

#define MAXSIZE 10 

CRITICAL_SECTION cs;

bool gameoverflag = false;
char GameLayout[MAXSIZE + 1][MAXSIZE];
int YourScore = 0;



DWORD WINAPI removeCh(LPVOID p)
{
	char ch = 0;
	ch = getch();
	
	for (int i = MAXSIZE - 1; i >= 0; i--)
	{
		for (int j = 0; j < MAXSIZE; j++)
		{
			if (GameLayout[i][j] == ch)
			{
				EnterCriticalSection(&cs);
				GameLayout[i][j] = '\0';
				YourScore += 1;
				LeaveCriticalSection(&cs);
				break;
			}
		}
	}
	
	return 0;
}

void PrintArr()
{
	system("cls");
	printf("your score:%d\n", YourScore);
	for (int i = 0; i < MAXSIZE; i++)
	{
		for (int j = 0; j < MAXSIZE; j++)
		{
			printf("%3c", GameLayout[i][j]);
		}
		printf("\n------------------------------------------\n");
	}
}
bool isGameOver()
{
	for (int j = 0; j < MAXSIZE; j++)
	{
		if (GameLayout[MAXSIZE][j] != '\0')
			return true;
	}
	return false;
}
void RandAppearACh(int i)//i是第i行的意思
{
	int j = 0;
	//1,设置随机种子
	//srand((unsigned int)time(NULL));
	//2,生成0~MAXSIZE - 1 的随机数字---获得要放置的随机位置
	do 
	{
		j = rand() % MAXSIZE;
	} while (GameLayout[i][j] != 0);//确保选择的位置上面没有放置元素
	
	//3,获得大小或者小写字母的选项 0->小写 1->大写
	int flag = rand() % 2;
	//4,根据第三步选项判断获取的是65	~90(大写)还是97~122(小写)的值。
	int chval;

	if (flag == 0)
	{
		chval = rand() % (122 - 97 + 1) + 97;
	}
	else
	{
		chval = rand() % (90 - 65 + 1) + 65;//取任意范围的随机数的方法:[min,max] = rand % (max - min + 1) + min
	}

	//5,给相应位置赋值
	EnterCriticalSection(&cs);
	GameLayout[i][j] = chval;
	LeaveCriticalSection(&cs);
}
void UpdateArr()
{
	for (int i = MAXSIZE; i > 0; i--)
	{
		for (int j = 0; j < MAXSIZE; j++)
		{
			GameLayout[i][j] = GameLayout[i - 1][j];
			if (i == 1)
			{
				EnterCriticalSection(&cs);
				GameLayout[i - 1][j] = 0;
				LeaveCriticalSection(&cs);
			}
		}
	}
}
DWORD WINAPI MainGaming()
{
	//1,设置随机种子
	srand((unsigned int)time(NULL));
	//rand srand
	//
	int length = 1;		//每行的字母的个数  最多是5个
	int level = 0;		//一共更新了多少行当更新十行的时候,下次更新的没行的字母量加1
	while (true)
	{
		if (isGameOver())
		{
			MessageBox(NULL,"GameOver!\n","提示!\n",MB_OK);
			break;
		}
		//1,向下移动一行
		UpdateArr();
		//2,根据length的值随机移动个数
		int times = rand() % length;
		for (int i = 0; i <= times; i++)
		{
			RandAppearACh(0);
		}
		//3,打印二维数组
		PrintArr();

		Sleep(1000);

		//4,当移动的次数超过9次的话,每行的出现的个数可能加1
		level++;
		if (level == 9 && length<5)
		{
			length++;
			level = 0;
		}
	}

	return 0;
}


void main()
{
	InitializeCriticalSection(&cs);
	HANDLE myhandle;
	CreateThread(NULL, 0, MainGaming, NULL, 0, NULL);
	while (!gameoverflag)
	{
		myhandle = CreateThread(NULL, 0, removeCh, NULL, 0, NULL);
		WaitForSingleObject(myhandle, INFINITE);
	}
	DeleteCriticalSection(&cs);
	printf("hello...\n");
	system("pause");
	return ;
}

【目前存在的问题】:

1,分数的输出有问题,没有按照预期的输出。

2,消除字母并不可以"实时"有稍微的延迟。

【解决问题1】:主要是英文getch的函数的问题,导致在循环内Yourscore增加了数次,导致了Yourscore的异常


#define  _CRT_SECURE_NO_WARNINGS 
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdbool.h>
#include <windows.h>
#include <conio.h>

#define MAXSIZE 10 

CRITICAL_SECTION cs;

bool gameoverflag = false;
char GameLayout[MAXSIZE + 1][MAXSIZE];
int YourScore = 0;



DWORD WINAPI removeCh(LPVOID p)
{
	char ch = 0;
	while (!gameoverflag)
	{
		ch = getch();
		if (ch != 0)
		{
			bool matched = false;
			for (int i = MAXSIZE - 1; i >= 0 && !matched; i--)
			{
				for (int j = 0; j < MAXSIZE; j++)
				{
					if (GameLayout[i][j] == ch)
					{
						EnterCriticalSection(&cs);
						GameLayout[i][j] = '\0';
						YourScore += 1;
						matched = true;
						LeaveCriticalSection(&cs);
						break;
					}
				}
			}
		}
	}
	
	return 0;
}

void PrintArr()
{
	system("cls");
	EnterCriticalSection(&cs);
	printf("your score:%d\n", YourScore);
	LeaveCriticalSection(&cs);
	for (int i = 0; i < MAXSIZE; i++)
	{
		for (int j = 0; j < MAXSIZE; j++)
		{
			printf("%3c", GameLayout[i][j]);
		}
		printf("\n------------------------------------------\n");
	}
}
bool isGameOver()
{
	for (int j = 0; j < MAXSIZE; j++)
	{
		if (GameLayout[MAXSIZE][j] != '\0')
			return true;
	}
	return false;
}
void RandAppearACh(int i)//i是第i行的意思
{
	int j = 0;
	//1,设置随机种子
	//srand((unsigned int)time(NULL));
	//2,生成0~MAXSIZE - 1 的随机数字---获得要放置的随机位置
	do 
	{
		j = rand() % MAXSIZE;
	} while (GameLayout[i][j] != 0);//确保选择的位置上面没有放置元素
	
	//3,获得大小或者小写字母的选项 0->小写 1->大写
	int flag = rand() % 2;
	//4,根据第三步选项判断获取的是65	~90(大写)还是97~122(小写)的值。
	int chval;

	if (flag == 0)
	{
		chval = rand() % (122 - 97 + 1) + 97;
	}
	else
	{
		chval = rand() % (90 - 65 + 1) + 65;//取任意范围的随机数的方法:[min,max] = rand % (max - min + 1) + min
	}

	//5,给相应位置赋值
	EnterCriticalSection(&cs);
	GameLayout[i][j] = chval;
	LeaveCriticalSection(&cs);
}
void UpdateArr()
{
	for (int i = MAXSIZE; i > 0; i--)
	{
		for (int j = 0; j < MAXSIZE; j++)
		{
			GameLayout[i][j] = GameLayout[i - 1][j];
			if (i == 1)
			{
				EnterCriticalSection(&cs);
				GameLayout[i - 1][j] = 0;
				LeaveCriticalSection(&cs);
			}
		}
	}
}
DWORD WINAPI MainGaming()
{
	//1,设置随机种子
	srand((unsigned int)time(NULL));
	//rand srand
	//
	int length = 1;		//每行的字母的个数  最多是5个
	int level = 0;		//一共更新了多少行当更新十行的时候,下次更新的没行的字母量加1
	while (true)
	{
		if (isGameOver())
		{
			MessageBox(NULL,"GameOver!\n","提示!\n",MB_OK);
			break;
		}
		//1,向下移动一行
		UpdateArr();
		//2,根据length的值随机移动个数
		int times = rand() % length;
		for (int i = 0; i <= times; i++)
		{
			RandAppearACh(0);
		}
		//3,打印二维数组
		PrintArr();

		Sleep(1000);

		//4,当移动的次数超过9次的话,每行的出现的个数可能加1
		level++;
		if (level == 9 && length<5)
		{
			length++;
			level = 0;
		}
	}

	return 0;
}


void main()
{
	InitializeCriticalSection(&cs);
	HANDLE myhandle1, myhandle2;
	myhandle1 = CreateThread(NULL, 0, MainGaming, NULL, 0, NULL);
	
	myhandle2 = CreateThread(NULL, 0, removeCh, NULL, 0, NULL);

	WaitForSingleObject(myhandle1, INFINITE);
	DeleteCriticalSection(&cs);
	CloseHandle(myhandle1);
	CloseHandle(myhandle2);
	printf("hello...\n");
	system("pause");
	return ;
}

猜你喜欢

转载自blog.csdn.net/qq_42418668/article/details/89630930