打字母游戏:
1.项目要求:
随机产生一个字母从屏幕上方向下落,玩家输入字母,如果和显示的字母相同,就消去字母;游戏会再随机产生一个字母,继续游戏,如果字母落出屏幕,玩家失败,游戏结束;
2.项目分析:
项目由两个模块组成:1)显示模块; 2)处理模块;
2.1
显示模块由二维数组构成,把随机产生的字母赋值到二维数组中.
2.2
处理模块功能有:随机产出字母, 输入字母比较, 字母是否落出屏幕, 字母下降功能.
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<assert.h>
#include<conio.h> //windows提供的非阻塞性IO
#include<thread> //睡眠函数头文件
#define LETSIZE 26
#define ROWSIZE 20
#define COLSIZE 40
using namespace std;
typedef char GridType[ROWSIZE][COLSIZE]; //定义了一个数组
struct LetterNode
{
char ch; //放的是字母
int row;
int col;
};
void Init_Grid(GridType grid, int row, int col)
{
for (int i = 0; i < ROWSIZE; ++i)
{
memset(grid[i], ' ', sizeof(char) * col);
grid[i][col - 1] = '\0';
}
}
void Print_Grid(GridType grid, int row, int col, LetterNode*plet)
{
system("cls"); //清屏函数
Init_Grid(grid, ROWSIZE, COLSIZE);
grid[plet->row][plet->col] = plet->ch;
for (int i = 0; i < row;i++)
{
printf("%s\n", grid[i]);
}
printf("\n");
}
int main()
{
GridType grid; //定义了一个网格(网格就是游戏区)
LetterNode x = { 'a',0,18 };
char ch;
Print_Grid(grid, ROWSIZE, COLSIZE, &x);
while (1)
{
Print_Grid(grid, ROWSIZE, COLSIZE, &x);
std::this_thread::sleep_for(std::chrono::milliseconds(200));
//睡眠函数:每隔200毫秒以后再去运行
x.row += 1;
if (x.row >= ROWSIZE)
{
printf("over\n");
break;
}
if (_kbhit()) //_kbhit()函数可以探测看键盘有没有输入
{
ch = _getch();// _getch()函数不用回车就可以放进去,但这个函数不进行回显
//getchar(); //用getchar()函数将回车读走
if (x.ch == ch)
{
x.ch = rand() % LETSIZE + 'a';
x.row = 0;
x.col = rand() % (COLSIZE - 1);
}
}
}
return 0;
}
3.改进这个小游戏
一次性在屏幕上输出10个字母,使得我们每消去一个字母就自动再生成一个字母.
#include<stdio.h>
#include<thread>
#include<stdlib.h>
#include<conio.h>
#include<assert.h>
#define ROW 25
#define COL 35
#define LENSIZE 10
#define NODESIZE 26
struct LetNode {
char ch;
int row;
int col;
};
typedef char GridType[ROW][COL];
typedef struct LetNode Let[LENSIZE];
void Init_grid(GridType ar, int row, int col)//初始化二维数组
{
assert(ar != nullptr && row > 0 && col > 0);
for (int i = 0; i < row; i++)
{
memset(ar[i], ' ', sizeof(ar[0]));
ar[i][COL - 1] = '\0'; //使二维数组中的每一维数组行变成一个字符串,方便打印
}
}
void Init_Let_First(Let x, int size,char *Node,char *list)
{
assert(x != nullptr && size > 0);
srand(time(0));//随机种子
for (int i = 0; i < size;)
{
int low_or_up = rand() % 2;//控制大小写
int tag1 = rand() % NODESIZE; //控制字母不重复
int tag2 = rand() % (COL - 1);//控制下标不重叠
if (x[i].ch == 0)
{
if (Node[tag1] == 0 && list[tag2] == 0)
{
if (low_or_up == 0)
{
x[i].ch = tag1 + 'a';
}
else
{
x[i].ch = tag1 + 'A';
}
x[i].row = 0;
Node[tag1] = 1;
x[i].col = tag2;
list[tag2] = 1;
i++;
}
}
else
{
i++;
}
}
}
void Print_Let(GridType grid, int row, int col, Let x, int size)
{
system("cls");
Init_grid(grid, row, col);
for (int i = 0; i < size; i++)
{
grid[x[i].row][x[i].col] = x[i].ch;
}
for (int i = 0; i < row; i++)
{
printf("%s\n",grid[i]);
}
printf("\n");
}
bool DownNode(Let x, int n)
{
bool pos = false;
for (int i = 0; i < n; i++)
{
x[i].row += 1;
if (x[i].ch != ' ' && x[i].row >= ROW)
{
pos = true;
}
}
return pos;
}
void Remove(Let x, int size, char ch,char *ar,char *len)
{
for (int i = 0; i < size; i++)
{
if (x[i].ch == ch)
{
x[i].ch = 0;
x[i].row = 0;
ar[ch - 'a'] = 0;
len[x[i].col] = 0;
}
}
}
int main()
{
GridType grid; //网格
Let x = {}; //字母表
char Node[26] = {}; //防止字母重复
char list[COL] = {}; //防止列重叠
//Init_grid(grid, ROW, COL);
//Init_Let_First(x, LENSIZE,Node,len);
char ch;
while (1)
{
Init_Let_First(x, LENSIZE, Node, list);
Print_Let(grid, ROW, COL, x, LENSIZE);
//Init_Let(x, LENSIZE);
std::this_thread::sleep_for(std::chrono::milliseconds(500));
if (DownNode(x,LENSIZE))
{
printf("Game Over \n");
break;
}
if (_kbhit())
{
ch = _getch();
Remove(x, LENSIZE, ch, Node,list);
}
}
return 0;
}
3.输入字符,查询字符是否在其中,如果在,则给出一个新的字符
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<conio.h>
#include<assert.h>
#include<thread>
#include<windows.h> //睡眠函数头文件
using namespace std;
#define LETSIZE 26 //一共有26个字母
#define ROWSIZE 22 //行
#define COLSIZE 60 //列
#define LENSIZE 26
#define MAXSIZE 10 //当前最多能够同时出现10个字母
//首先定义网格和字母表
typedef char GridType[ROWSIZE][COLSIZE]; //定义了一个网格
typedef enum { NULLLET = 0, UPLET = 1, LOWLET = 2 }LetType;//枚举定义LetType,从中查找tag的查询结果
struct LetterNode //定义字母表
{
LetType tag;// 0代表无字符,1代表大写字母,2代表小写字母
int row;
int col;
};
typedef struct LetterNode LeTable[LENSIZE];
void Init_Let(LeTable plet) //此处plet是一个指针 //初始化字母表LeTable
{
assert(plet != nullptr);//断言字母表不能为空
int i = 0;
int num = 0;
int table[COLSIZE] = {}; //对列的信息进行初始化
srand(time(nullptr)); //由于要调动随机函数,此处用随机终止,time是获得系统时间,time是一个整型值
while (num < ROWSIZE)
{
int tag = rand() % 2 + 1; //随机查找出大写字母和小写字母并将其转化为1和2
int pos = rand() % LETSIZE; //求随机产生的字母的下标
plet[pos].tag = (tag == 1) ? UPLET : LOWLET; //判断是大写字母还是小写字母
plet[pos].row = 0;
while (1) //无限循环 //这个循环让列坐标可以不重复
{
int col = rand() % (COLSIZE - 1);
if (table[col] == 0) //因为每个列都初始化为0,如果这个列没被用过
{
table[col] = 1; //则先将列标记为1,变为用过的列
plet[pos].col = col; //将这个列应运于字母表中
break;
}
}
num += 1;
}
}
void Init_Grid(GridType grid) //初始化网格
{
for (int i = 0; i < ROWSIZE; ++i)
{
memset(grid[i], ' ', sizeof(char) * COLSIZE);
grid[i][COLSIZE - 1] = '\0';
}
}
void Print_Grid(GridType grid, LeTable plet)
{
assert(grid != nullptr && plet != nullptr);
Init_Grid(grid);//将空网格映射进去
system("cls"); //使用清屏命令
for (int i = 0; i < LENSIZE; i++)
{
if (plet[i].tag != NULLLET)
{
char ch = (plet[i].tag == UPLET) ? 'A' + i : 'a' + i;
grid[plet[i].row][plet[i].col] = ch;
}
}
for (int i = 0; i < ROWSIZE; i++)
{
printf("%s\n", grid[i]);
}
}
bool DownLet(LeTable plet) //检查字母在下落过程中有没有触底
{
assert(plet != nullptr);
bool res = false;
for (int i = 0; i < LENSIZE; i++) //小于字母表的长度
{
if (plet[i].tag != NULLLET)
{
plet[i].row += 1;
if (plet[i].row >= ROWSIZE) //触底了
{
res = true;
break;
}
}
}
return res;
}
void Remove_Inc(LeTable plet, char ch)
{
assert(plet != nullptr);
LetType tag = isupper(ch) ? UPLET : LOWLET; //判断字符是大写还是小写
int pos = (tag == UPLET) ? ch - 'A' : ch - 'a';
if (plet[pos].tag != tag) return; //如果没找到相同的值,则什么都不加
if (plet[pos].tag == tag)
{
plet[pos].tag = NULLLET;
plet[pos].row = plet[pos].col = 0;
}
while (1)
{
tag = ((rand() % 2 + 1) == 1) ? UPLET : LOWLET;
pos = rand() % LENSIZE;
if (plet[pos].tag == NULLLET) //不能让我,们取的值覆盖掉其它的
{
plet[pos].tag = tag;
plet[pos].row = 0;
plet[pos].col = rand() % (COLSIZE - 1);
break; //不能让其无限循环
}
}
}
int main()
{
GridType grid = {}; //定义了一个网格
LeTable xLet = {}; //定义字母表
Init_Let(xLet); //初始化字母表
while (1)
{
Print_Grid(grid, xLet); //打印网格
Sleep(500);
if (DownLet(xLet)) //检查字母在下落过程中有没有触底
{
printf("over!\n");
break;
}
if (_kbhit()) //_kbhit()函数可以探测看键盘有没有输入
{
char ch = _getch();// _getch()函数不用回车就可以放进去,但这个函数不进行回显数据到屏幕
//getchar(); //用getchar()函数将回车读走
Remove_Inc(xLet, ch); //删除字母表中的字母
}
}
return 0;
}