【主要思路和说明】:
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 ;
}