Bootstrap

C++之俄罗斯方块

C++之俄罗斯方块

使用VS2017编译

思路:

1.打印出游戏地图,也就是设计游戏地图类game_interdace,包括设计游戏开始界面的函数,游戏地图界面的函数,游戏结束界面的函数,以及设计一些辅助函数如(设置光标为目标点,改变颜色,隐藏光标)来完成上述设计。

2.设计方块图形类,包括生成图形,清理图形,图形移动,图形停止的处理,图形的消失(实质是得分)等。

#include <iostream>
#include<conio.h>
#include<windows.h>
#include<time.h>
#include<string>


class game_interdace
{

public:
	friend class Graphic;
	game_interdace();
	
	void start_interface();//游戏开始界面

	void HideCursor(); //隐藏光标

	int color(int c);//改变颜色

	void gotoxy(int x, int y);//设置光标为目标点

	void gotoprintf(int x, int y);//在目标点打印■

	void gotoclear(int x, int y);//消除目标点■

	void map(); //游戏地图界面

	bool end_map(); //游戏结束界面

private:
	int grade;
	static int game_lv;

};
int game_interdace::game_lv{};
game_interdace::game_interdace() :grade{  }
{

}//注意这里的花括号

class Graphic
{
public:
	class game_interdace interdace;
	Graphic();
	int location_x;//用于判断和控制图形位置(x坐标)
	int location_y;//用于判断和控制图形位置(y坐标)
	int graph_id;   //图形id
	int next_graph_id{};//下一图形id
	int random(); //生成随机数
	void produce_graph(int location_x, int location_y,int id );//生成图形
	void clear_graph(int location_x, int location_y,int id);//清理图形
	void graph_moving();//图形移动
	bool graph_no_moving(int location_x, int  location_y,int id);//图形不能超界和不能变形处理
	int graph_change(int id); //按‘w'键时,图形的改变
	void graph_stop(); //图形停止的处理
	void graph_disppear(int location_x, int  location_y);  //图形的消失(实质是得分)
	bool game_end(); //游戏结束的判定
private:
	const int graph[15][8];//记录每个每个图形的各点坐标
	int graph_active_pos[32][26]{};//方块活动地图的各坐标点的状态
	const int graph_with[15];//记录每个每个图形的宽度
	int stop_tgraph_top;// 记录所有已经下落的方块中的最高点
	
};
Graphic::Graphic():

	graph
{
	//两个值一组分别代表x,y 坐标就比如方形图形数据可以这么来看(0,0),(2,0),(0,2),(2,2)
	//由于每个方块由"■"的宽度为两个字符,所以x坐标成双增长

	{0,0,2,0,0,1,2,1 },  //方形
	{2,0,4,0,0,1,2,1},{0,0,0,1,2,1,2,2},// |_
									   //    |形
	{0,0,2,0,2,1,4,1},{2,0,0,1,2,1,0,2},//

	{0,0,2,0,4,0,6,0},{0,0,0,1,0,2,0,3},//条形

	{2,0,0,1,2,1,4,1},{0,0,0,1,2,1,0,2},{0,0,2,0,4,0,2,1},{2,0,0,1,2,1,2,2} ,//T形

	{0,0,2,0,0,1,0,2},{0,0,0,1,2,1,4,1},{0,0,2,0,2,1,2,2} ,{0,0,2,0,4,0,0,1},
}, //L形
graph_with{ 2,3,2,3,2,4,1,3,2,3,2,2,3,2,3 },
location_x{ 14 },
location_y{ 1 },
graph_id{ 5 },
stop_tgraph_top{ 26 }
{

}


int main()
{
	bool aganst{ false };
	do
	{
		game_interdace interdace;
		interdace.HideCursor();
		interdace.start_interface();
		interdace.map();
		Graphic graph;
		graph.graph_moving();
	
		if (interdace.end_map())
		{
			aganst = true;
			system("cls");
			
		}
	} while (aganst);
	
	
}


void game_interdace::start_interface()//游戏开始界面
{
	color(2);
	gotoxy(30, 2);
	std::cout<<"                       游戏说明                      ";
	color(3);
	gotoxy(30, 5);
	std::cout << "        请在英文输入法中输入wsad控制方块      ";
	color(4);
	gotoxy(30, 9);
	std::cout << "                     'w'为变形           \n";
	gotoxy(30, 10);
	
	std::cout << "                    's'为快速下落             \n";
	gotoxy(30, 11);
	std::cout << "			   'a'为左移              ";
	gotoxy(30, 12);
	std::cout << " 			   'd'为右移                ";
	gotoxy(30, 14);
	
	color(5);
	std::cout << "                       游戏等级                       ";
	gotoxy(30, 16);
	color(5);
	std::cout << "=====================================================";
	color(3);
	gotoxy(30, 18);
	std::cout << "          游戏等级:(1)简单--(2)(困难)--(3)地狱";
	gotoxy(30, 20);
	color(5);
	std::cout << "=====================================================";
	gotoxy(30, 22);
	color(7);
	std::cout << "           等级越高,方块下落的速度越快,加油吧!           ";
	gotoxy(30, 24);
	color(9);
	std::cout << "                 请输入游戏等级(1-3):          ";
	gotoxy(70, 24);
	std::cin >> game_lv;

	system("cls");
	color(7);
}


void game_interdace::HideCursor()
{
	CONSOLE_CURSOR_INFO cursor;
	cursor.bVisible = FALSE;   
	cursor.dwSize = sizeof(4);   

	HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
	SetConsoleCursorInfo(handle, &cursor);

}

int game_interdace::color(int c)
{
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), c);
	return 0;
}
void game_interdace::gotoxy(int x, int y)
{
	COORD pos;	
	pos.X = x;
	pos.Y = y;	
	SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);
}

void game_interdace::gotoprintf(int x, int y)
{
	gotoxy(x, y);
	printf("■");
}

void game_interdace::gotoclear(int x, int y)
{
	gotoxy(x, y);
	printf("  ");//"■"为两个字符,所以要覆盖两个字符 
}

void game_interdace::map()
{
	int x, y;//边框打印 
	for (x = 0; x < 47; x +=2)//从第0列开始到第52列,两个字符一个"■",一共27个”■“
	{
		gotoprintf(x, 0);
		gotoprintf(x, 26);
	}
	for (y = 0; y < 27; y++)//从第0行开始到第26行
	{
		gotoprintf(0, y);
		gotoprintf(32, y);
		gotoprintf(46, y);
	}//x两格为一个前进坐标单位,y一格为一个前进单位 
}
bool game_interdace::end_map()
{
	char isno{};
		system("cls");
		gotoprintf(14, 6);
		std::cout << "游戏结束\n";
		std::cout << "         输入【y】键继续游戏\n";
		std::cout << "         输入【n】键结束游戏\n";
		gotoxy(17, 10);
		std::cin >> isno;
		if (isno =='y')
		{
			return true;
		}
		else
		{
			return false;
		}		
}

int Graphic::random()
{
	
	srand((int)time(NULL));
	int  number = rand()%15;
	return number;

}
void Graphic::produce_graph(int location_x, int location_y,int id)
{
	int X, Y;
	for (int i = 0; i < 4; i++)
	{
		X = location_x + graph[id][i * 2];
		Y = location_y + graph[id][i * 2 + 1];
		interdace.gotoprintf(X, Y);
	}
}
void Graphic::clear_graph(int location_x, int location_y,int id)
{
	int X, Y;
	interdace.color(random()%15+1);  //使下落过程中颜色随机变化(有黑色的)
	for (int i = 0; i < 4; i++)
	{
		X = location_x + graph[id][i * 2];
		Y = location_y + graph[id][i * 2 + 1];
		interdace.gotoclear(X, Y );
	}
}

void Graphic::graph_moving()//按键后,如果符号要求就消除旧图形,打印新图形
{
	int sign{}, sleep{ 400 };
	
	graph_id = random();
	next_graph_id = random();

	produce_graph(36, 3, next_graph_id);
	
	while (true)
	{
		sign = 0;
		interdace.gotoxy(35, 9);
		std::cout << "游戏分数:";
		interdace.gotoxy(39, 11);
		std::cout << interdace.grade * 10;
		if (_kbhit())
		{
			sign = _getch();
		}
		clear_graph(location_x, location_y, graph_id);
		switch (sign)
		{
		case 119:           //如果按下’w'键,			
			location_y += 1;
			if (graph_no_moving(location_x, location_y, graph_change(graph_id)))
			{
				location_y -= 1;			
				break;
			}
			graph_id = graph_change(graph_id);
			break;
		case 115:           //如果按下s'键	
			sleep = 50; 
			location_y += 1;			
			break;
		case 97:           //如果按下a'键	

			location_x -= 2;
			location_y += 1;
			if (graph_no_moving(location_x, location_y, graph_id)  )
			{
				location_x += 2;
				location_y -= 1;
			}
			break;
		case 100:           //如果按下’d'键	
			
			location_x += 2;
			location_y += 1;
			if (graph_no_moving(location_x, location_y, graph_id) )
			{
				location_x -= 2;
				location_y -= 1;
			}
			break;
		default:
			location_y += 1;
			break;
		}
		produce_graph(location_x, location_y, graph_id); //按键结束后,打印新图形	
		Sleep(sleep);		
		sleep = (4- interdace.game_lv)*100;
		
	
		graph_stop();//如果符合停止要求就停止

		if (game_end())
		{		
			break;
		}	
	}
  }

bool Graphic::graph_no_moving(int location_x, int  location_y,int id)
{
	
	for (int i = 0; i < 4; i++)
	{
		int X, Y;
		X = location_x + graph[id][i * 2];
		Y = location_y + graph[id][i * 2 + 1];			
		if (location_x < 2 || graph_active_pos[X][Y] == 1 || location_x+ (graph_with[id]-1)*2 >30)
		{
			return  true;
		}	
		else return false;
		
	}
	return 0;//防止出现该路径没有返回值
}

int Graphic::graph_change(int id)
{
	switch (id)
	{
	case 0: id = 0; break; //方形

	case 1: id = 2; break;//|_
	case 2: id = 1; break;//  |

	case 3: id = 4; break;//
	case 4: id = 3; break;

	case 5: id = 6; break;//条形
	case 6: id = 5; break;

	case 7: id = 8; break;//T形
	case 8: id = 9; break;
	case 9: id = 10; break;
	case 10: id = 7; break;

	case 11: id = 12; break;//L形
	case 12: id = 13; break;
	case 13: id = 14; break;
	case 14: id = 11; break;

	default:
		break;
	}
	return id;
}
void Graphic::graph_stop()
{
	int X{}, Y{};
	for (int i = 0; i < 4; i++)
	{
		
		X = location_x + graph[graph_id][i * 2];
		Y = location_y + graph[graph_id][i * 2 + 1];			
		if (graph_active_pos[X][Y+1] == 1||Y>=25)
		{			
			for (int i = 0; i < 4; i++)
			{
				X = location_x + graph[graph_id][i * 2];
				Y = location_y + graph[graph_id][i * 2 + 1];
				graph_active_pos[X][Y] = 1;
			
			}
			
			if (stop_tgraph_top >location_y)
			{
				stop_tgraph_top = location_y;
			}
					
			graph_disppear(location_y, Y);

			location_x = 14;//初始化初始坐标
			location_y = 1;

			clear_graph(36, 3, next_graph_id);//清除图形预览
			graph_id = next_graph_id;

			next_graph_id = random();	

			produce_graph(36, 3, next_graph_id);//生成新的图形预览		
			produce_graph(location_x, location_y, graph_id);//打印新的初始图形
			
		}
		
	}
	
}
void Graphic::graph_disppear(int  location_y,int Y)
{
	int count{ 0 };
	bool isno{ false };

		for (int  line = location_y + graph[graph_id][7]  ; line > location_y; line--)
		{
			count = 0;
			isno = false;
			for (int column = 2; column < 32; column +=2)
			{				
				if (graph_active_pos[column][line]==1)
				{
					count++;										
					if (count==15)
					{						
						count = 0;
						interdace.grade++;
						isno = true;						
					}
				}
				if (isno)
				{					
					for (int ls = 2; ls < 32; ls+=2)
					{				
						for (int i = line; i >= stop_tgraph_top; i--)
						{
							if (graph_active_pos[ls][i])
							{
								interdace.gotoclear(ls, i);
							}						
							graph_active_pos[ls][i] = graph_active_pos[ls][i - 1];
							if (graph_active_pos[ls][i])
							{
								interdace.gotoprintf(ls, i);
							}						
						}
					
					}									
				}			
			}		
			
		}	
}

bool Graphic::game_end()
{
	if (stop_tgraph_top <=1)return true;	
	else return false;

}
;