博客
关于我
俄罗斯方块(C/C++)
阅读量:540 次
发布时间:2019-03-09

本文共 7947 字,大约阅读时间需要 26 分钟。

俄罗斯方块(C/C++)

1.设计内容

(1)设计需要生成游戏界面,包括墙壁和底
(2)然后设计生成俄罗斯方块中七个基础方块,设计旋转程序,将其进行旋转,生成21种方块模型
(3)设计程序随机生成21中模型的方块,并自动下移,设计移动方块,left,right,down移动
(4)设计判断程序,当方块碰到墙壁和底停止移动;当方块堆满一行,消除方块;当方块碰到顶,游戏结束
(5)设计隐藏光标程序,让方块在移动过程中不显示光标
2.需求分析
在本代码中,需要规定一个游戏界卖弄,包括墙壁和底部,构建出大概类似于房子的结构,需要函数来实现方块的产生,通过键盘输入来控制方块的移动(right/left/down),旋转(空格键),需要设定判断条件,当方块触碰到墙壁或者底部,便不再继续向着墙壁或者底部的方向移动,当触碰到顶部时便结束游戏,在此时,还需在设定一个判断,看用户是否要继续游戏(y/n),如果是,便继续游戏,如果否,便按任意键结束游戏,还有就是得设定一个判断,当小方块堆积满一行便进行消除。为了美观,还需要写一个子函数来对方块进行上色和隐藏光标,当然,计分又是游戏的重要一部分,我们还需要设计子函数来对玩家的分数进行记录。

3.系统设计

共设计了10个子函数来实现俄罗斯方块的生成,旋转,自由下落,实现隐藏光标,移动光标,给方块上色,制作出游戏界面,实行判断,看方块有无碰到墙壁,看方块是否堆积成一行,进行消除。记录分数,当方块碰到顶部就退出游戏,再看用户是否要继续游戏(y/n),如果是,便继续游戏,如果否,便按任意键结束游戏。
3.1 模块划分
模块分为方块的产生与清除,方块的移动与颜色,消行于计分,隐藏光标于判断方块是否到底四部分。
功能模块图
在这里插入图片描述
4编码及调试
4.1 功能一编码及调试:开始游戏
实现情况:该函数成功编译通过,实现了输出游戏界面,控制旋转次数,随即生成方块,完成了游戏规则的判断,是否还可以移动,游戏是否还继续

void stat_game(){   	int n, ch, t = 0, x = 0, y = FACE_Y / 2 - 2, i, j;	int space1 = 0;//旋转次数	kongge(nn, space1, 4, FACE_Y + 3);	n = nn;	nn = rand() % 7;    //随机生成下一块	color(nn);	fangkuai(nn, space1, 4, FACE_Y + 3);	while (1)	{   		color(n);		fangkuai(n, space1, x, y);//画-出图形		if (t == 0)			t = 15000;		while (--t)		{   			if (kbhit() != 0)//有输入就跳出				break;		}		if (t == 0)		{   			if (judge(n, space1, x + 1, y) == 1)			{   				kongge(n, space1, x, y);				x++;            //自动向下降落			}			else //不能下落后使图形的方为aBox			{   				for (i = 0; i < 4; i++)				{   					for (j = 0; j < 4; j++)					{   						if (dia[n][space1].space[i][j] == 1)						{   							face.data[x + i][y + j] = Box;							face.color[x + i][y + j] = n;							while (compare());						}					}				}				return;			}		}		else		{   			ch = getch();			switch (ch)     //移动			{   			case LEFT: if (judge(n, space1, x, y - 1) == 1)   //判断是否左可以移动					   {   						   kongge(n, space1, x, y);						   y--;					   }					   break;			case RIGHT: if (judge(n, space1, x, y + 1) == 1) //判断是否右可以移动						{   							kongge(n, space1, x, y);							y++;						}						break;			case DOWN: if (judge(n, space1, x + 1, y) == 1) //判断是否下可以移动					   {   						   kongge(n, space1, x, y);						   x++;					   }					   break;			case SPACE: if (judge(n, (space1 + 1) % 4, x + 1, y) == 1) //判断是否能旋转						{   							kongge(n, space1, x, y);							space1 = (space1 + 1) % 4;						}						break;			case ESC: system("cls");				gotoxy(FACE_X / 2, FACE_Y);				printf("---游戏结束!---\n\n");				gotoxy(FACE_X / 2 + 2, FACE_Y);				printf("---按任意键退出---\n");				getch();				exit(0);				break;			case  'R':			case  'r':  main();				exit(0);			case  'S':			case  's':  while (1)						{   							if (kbhit() != 0)//有输入就跳出								break;						}						break;			}		}	}}

输入:空

输出:表现在方块的移动,输出“游戏结束”“按任意键退出”等字体
效果:
在这里插入图片描述
4.2 功能二编码及调试:进行消除满行
把“功能二”换成系统中的实际功能。实现情况:该函数成功编译通过,通过循环结构来实现了方块堆满一行便进行消除

int compare(){   	int i, j, k, sum;	for (i = FACE_X - 2; i > 4; i--)	{   		sum = 0;		for (j = 1; j < FACE_Y - 1; j++)		{   			sum += face.data[i][j];		}		if (sum == 0)			break;		if (sum == FACE_Y - 2)   //满行减掉,消除		{   			grade += 100;			color(7);			gotoxy(FACE_X - 4, 2 * FACE_Y + 2);			printf("分数:%d", grade);			for (j = 1; j < FACE_Y - 1; j++)			{   				face.data[i][j] = Kong;				gotoxy(i, 2 * j);				printf(" ");			}			for (j = i; j > 1; j--)			{   				sum = 0;				for (k = 1; k < FACE_Y - 1; k++)				{   					sum += face.data[j - 1][k] + face.data[j][k];					face.data[j][k] = face.data[j - 1][k];					if (face.data[j][k] == Kong)					{   						gotoxy(j, 2 * k);						printf(" ");					}					else					{   						gotoxy(j, 2 * k);						color(face.color[j][k]);						printf("■");					}				}				if (sum == 0)					return 1;			}		}	}	for (i = 1; i < FACE_Y - 1; i++)	{   		if (face.data[1][i] == Box)		{   			char n;			Sleep(2000); //延时			system("cls");			color(7);			do			{   				gotoxy(FACE_X / 2 + 2, 2 * (FACE_Y / 3));				printf("是否重新开始游戏(y/n): ");				scanf("%c", &n);				gotoxy(FACE_X / 2 + 4, 2 * (FACE_Y / 3));				if (n != 'n' && n != 'N' && n != 'y' && n != 'Y')					printf("输入错误请重新输!");				else					break;			} while (1);			if (n == 'n' || n == 'N')			{   				gotoxy(FACE_X / 2 + 4, 2 * (FACE_Y / 3));				printf("按任意键退出游戏");				exit(0);			}			else if (n == 'y' || n == 'Y')				main();		}	}	return 0;}

输入:空

输出:表现在方块堆满一行便进行消除
效果:
在这里插入图片描述
4.3功能三编码及调试:判断方块是否到底
实现情况:该函数成功编译通过,通过循环结构来判断小方块是否到底,到底便不再向底部移动

int judge(int n, int space_c, int x, int y)   //判断是否到底{   	int i, j;	for (i = 0; i < 4; i++)	{   		for (j = 0; j < 4; j++)		{   			if (dia[n][space_c].space[i][j] == 0)				continue;			else if (face.data[x + i][y + j] == Wall || face.data[x + i][y + j] == Box)				return 0;		}	}	return 1;}

输入:空

输出:表现在方块到底便不再移动
效果:
在这里插入图片描述
4.4功能三编码及调试:输出空格
实现情况:该函数成功编译通过,成成实现了在4*4矩形中将标记为0的部位为输出为空格

void kongge(int base, int space_c, int x, int y){   	int i, j;	for (i = 0; i < 4; i++)	{   		for (j = 0; j < 4; j++)		{   			gotoxy(x + i, 2 * (y + j));			if (dia[base][space_c].space[i][j] == 1)				printf("  ");		}	}}

输入:空

输出“ “
效果:在这里插入图片描述
4.5功能三编码及调试:将方块输出
实现情况:该函数成功编译通过,成成实现了在4*4矩形中将标记为1的部位为输出为矩形

void fangkuai(int base, int space_c, int x, int y){   	int i, j;	for (i = 0; i < 4; i++)	{   		for (j = 0; j < 4; j++)		{   			gotoxy(x + i, 2 * (y + j));			if (dia[base][space_c].space[i][j] == 1)				printf("■");		}	}}

输入:空

输出;■
效果:
在这里插入图片描述
4.6功能三编码及调试:俄罗斯方块的基本形状
实现情况:该函数成功编译通过,通过来控制循环结构,在4*4的矩形下生成基本的7种俄罗斯方块,再通过循环结构来对这几种基本形状进行旋转,生成全部的21种方块

void init_dia(){   	int i, j, k, z;	int tmp[4][4];	for (i = 0; i < 3; i++)		dia[0][0].space[1][i] = 1;	dia[0][0].space[2][1] = 1;     //土形?	for (i = 1; i < 4; i++)		dia[1][0].space[i][1] = 1;	dia[1][0].space[1][2] = 1;    //L形1	for (i = 1; i < 4; i++)		dia[2][0].space[i][2] = 1;	dia[2][0].space[1][1] = 1;    //L形2	for (i = 0; i < 2; i++)	{   		dia[3][0].space[1][i] = 1;		dia[3][0].space[2][i + 1] = 1; //Z形1		dia[4][0].space[1][i + 1] = 1;		dia[4][0].space[2][i] = 1;//Z形2		dia[5][0].space[1][i + 1] = 1;		dia[5][0].space[2][i + 1] = 1;//田字形	}	for (i = 0; i < 4; i++)		dia[6][0].space[i][2] = 1;//1形?	//基础个形状	for (i = 0; i < 7; i++)	{   		for (z = 0; z < 3; z++)		{   			for (j = 0; j < 4; j++)			{   				for (k = 0; k < 4; k++)				{   					tmp[j][k] = dia[i][z].space[j][k];				}			}			for (j = 0; j < 4; j++)			{   				for (k = 0; k < 4; k++)				{   					dia[i][z + 1].space[j][k] = tmp[4 - k - 1][j];				}			}		}	}	//旋转的21个形状}

输入:旋转(空格键)

输出:生成21种俄罗斯方块
效果:
在这里插入图片描述
4.7功能三编码及调试:设计出游戏界面和俄罗斯方块的移动
实现情况:该函数成功编译通过,通过循环来控制生成游戏界面,再判断来进行俄罗斯方块的移动

void inter_face()//开始界面{   	int i, j;	for (i = 0; i < FACE_X; i++)	{   		for (j = 0; j < FACE_Y + 10; j++)		{   			if (j == 0 || j == FACE_Y - 1 || j == FACE_Y + 9)			{   				face.data[i][j] = Wall;				gotoxy(i, 2 * j);				printf("■");			}			else if (i == FACE_X - 1)			{   				face.data[i][j] = Box;				gotoxy(i, 2 * j);				printf("■");			}			else				face.data[i][j] = Kong;		}	}	gotoxy(FACE_X - 18, 2 * FACE_Y + 2);	printf("左移:←");	gotoxy(FACE_X - 16, 2 * FACE_Y + 2);	printf("右移:→");	gotoxy(FACE_X - 14, 2 * FACE_Y + 2);	printf("旋转");	gotoxy(FACE_X - 12, 2 * FACE_Y + 2);	printf("暂停ª");	gotoxy(FACE_X - 10, 2 * FACE_Y + 2);	printf("退出 ESC");	gotoxy(FACE_X - 8, 2 * FACE_Y + 2);	printf("重新开始");	gotoxy(FACE_X - 4, 2 * FACE_Y + 2);	printf("分数%d", grade);}

输入:<-/->

输出:表现生成的游戏界面和方块的移动上
效果:
在这里插入图片描述
在这里插入图片描述
4.8功能三编码及调试:移动光标
实现情况:该子函数成功编译通过,实现了通过光标移动来移动俄罗斯方块

void gotoxy(int x, int y) //移动光标{   	COORD coord;	coord.X = y;	coord.Y = x;	SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);}

输入:空

输出:表现在方块的移动上
效果:在这里插入图片描述
4.9功能三编码及调试:隐藏光标
实现情况:该函数成功编译通过,且实现了光标的隐藏

void hidden_cursor()//隐藏光标{   	HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);	CONSOLE_CURSOR_INFO cci;	GetConsoleCursorInfo(hOut, &cci);	cci.bVisible = 0;//赋1为显示,赋0为隐藏	SetConsoleCursorInfo(hOut, &cci);}

输入:空

输出:表现在在方块移动时不出现光标
效果:在这里插入图片描述
.10功能三编码及调试:给方块上色
实现情况:该子函数编译成功通过,实现了给方块上色的目标,符合预期设想,通过SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), c)来更改颜色

int color(int c){   	switch (c)	{   	case 0: c = 9; break;	case 1:	case 2: c = 12; break;	case 3:	case 4: c = 14; break;	case 5: c = 10; break;	case 6: c = 13; break;	default: c = 7; break;	}	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), c);        //更改文字颜色¦	return 0;}

输入:空

输出:表现在方块颜色上
效果:在这里插入图片描述
在这里插入图片描述

转载地址:http://nqoiz.baihongyu.com/

你可能感兴趣的文章
Mysql 分页语句 Limit原理
查看>>
MySql 创建函数 Error Code : 1418
查看>>
MySQL 创建新用户及授予权限的完整流程
查看>>
mysql 创建表,不能包含关键字values 以及 表id自增问题
查看>>
mysql 删除日志文件详解
查看>>
mysql 判断表字段是否存在,然后修改
查看>>
MySQL 到底能不能放到 Docker 里跑?
查看>>
mysql 前缀索引 命令_11 | Mysql怎么给字符串字段加索引?
查看>>
MySQL 加锁处理分析
查看>>
mysql 协议的退出命令包及解析
查看>>
mysql 参数 innodb_flush_log_at_trx_commit
查看>>
mysql 取表中分组之后最新一条数据 分组最新数据 分组取最新数据 分组数据 获取每个分类的最新数据
查看>>
MySQL 命令和内置函数
查看>>
MySQL 和 PostgreSQL,我到底选择哪个?
查看>>
mysql 四种存储引擎
查看>>
MySQL 在并发场景下的问题及解决思路
查看>>
MySQL 在控制台插入数据时,中文乱码问题的解决
查看>>
MySQL 基础架构
查看>>
MySQL 基础模块的面试题总结
查看>>
MySQL 处理插入重主键唯一键重复值办法
查看>>