项目:打字母游戏

打字母游戏:

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;
}

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值