[玩耍]俄罗斯方块

和贪吃蛇在同一时期写的,私以为比我在网上找到的那些其他的控制台版的俄罗斯方块更精致

成品地址:链接: http://pan.baidu.com/s/1jIo9Ovs 密码: 7k8j

当时初学编程,废寝忘食地写着玩的,现在看看优化余地很大。

与之前的贪吃蛇一样R键刷新界面显示,空格暂停,“暂停”两字写在游戏右侧。这次没做花哨的开始界面,也是Visual studio2015写的,一样会生成一个保存分数的文件

上:翻转;下:瞬间下落;左右:就是左右  ESC:退出游戏(退出游戏时做了一个略花哨的动画)

//俄罗斯方块
#include
#include
#include
#include
using namespace std;
/**********************************/
//根据小键盘,将8、2、4、6定义为上下左右,5为默认,0为退出游戏
#define Sb 16//Screen的宽度
#define Sh 21//Screen的高度
bool Screen[Sh + 3][Sb + 2] = { 0 };
unsigned Speed_mulriple_limit = 2;
unsigned Speed_mulriple = 8;
unsigned SleepTime = 100;
unsigned Score = 0;
unsigned Max=0;
struct Tetris {
	bool shape[4][4];
	unsigned type;
	unsigned x, y;
}Tnow;
/**********************************/
void Start();
void Game();
void End();
void Interface();
void ScreenPrint();
void ScreenClear();
void NextShow(unsigned);
void Pause();
void TBuild(Tetris&, unsigned);
void TRotate(Tetris&);
void TMove(Tetris&, int);
void TDown(Tetris&);
void TCopy(Tetris&, const Tetris&);
void TShow(const Tetris&);
void TClear(const Tetris&);
int Judge_down(const Tetris&);
int Judge_key();
int Judge_eliminate(const Tetris&);
int Judge_gameover(const Tetris&);
void Pos(unsigned, unsigned);
void PosScreen(unsigned, unsigned);
void Swap(bool&, bool&);
/**********************************/
void Start() {
	system("mode con cols=80 lines=25");
	const CONSOLE_CURSOR_INFO cursor{ (DWORD)100,FALSE };
	SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor);
	srand((unsigned)time(0));
	ifstream i("tetris_data.dat", ios_base::binary);
	if (!i) i.close();
	else {
		unsigned s;
		i >> s;
		Max = s;
		i.close();
	}
	for (int i = 0;i < Sb + 2;++i)Screen[Sh + 2][i] = Screen[Sh + 1][i] = 1;
	for (int i = 0;i < Sh + 2;++i)Screen[i][0] = Screen[i][Sb + 1] = 1;
	Pos(12, 16);cout << "要开始游戏,请先关闭输入法,再";system("pause");system("cls");
	Interface();
}
void Game() {
	unsigned type_now = rand() % 7;
	unsigned type_next = rand() % 7;
	TBuild(Tnow, type_now);
	NextShow(type_next);
	Tetris Tp;//记录前面一步以方便删除轨迹
	TCopy(Tp, Tnow);
	int count = 1;
	int speed_count = 1;
	while (++count) {
		if (Judge_down(Tnow)) {
			Tp.type = 233;
			ScreenPrint();
			if (int lines=Judge_eliminate(Tnow)) {
				Score += 15*lines-5;
				if (Score > Max)Max = Score;
				++speed_count;
				speed_count %= 6;
				if (!speed_count&&Speed_mulriple>Speed_mulriple_limit)Speed_mulriple -= 1;
				Pos(14, 56);cout << Score;
				Pos(15, 56);cout << SleepTime*Speed_mulriple << 's';
				Pos(16, 58);cout << Max;
				ScreenClear();
				ScreenPrint();
				Sleep(10);
			}
			type_now = type_next;
			type_next = rand() % 7;
			TBuild(Tnow, type_now);
			Judge_gameover(Tnow);
			NextShow(type_next);
		}
		switch (Judge_key()) {
		case 8:TRotate(Tnow);break;
		case 4:TMove(Tnow, 4);break;
		case 6:TMove(Tnow, 6);break;
		case 2:TDown(Tnow);break;
		case 0:PosScreen(10, 4);cout << "Escape from Tetris!";End();
		}
		TClear(Tp);
		TShow(Tnow);
		TCopy(Tp, Tnow);
		if (!(count %= Speed_mulriple)) { count = 1;++Tnow.x; }
		Sleep(SleepTime);
	}
}
void End() {
	ofstream o("tetris_data.dat", ios_base::binary);
	if (!o) o.close();
	else {
		o << Max;
		o.close();
	}
	PosScreen(1, 1);
	int num = 0;
	int times = 0;
	int sl = 3;
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 119);
	while (num < 336) {
		int i, j;
		PosScreen(times + 1, times + 1);
		for (i = times + 1;i < Sb - times;++i) {
			cout << "■";
			++num;
			Sleep(sl);
		}
		for (j = times + 1;j < Sh - times;++j) {
			PosScreen(j, i);
			cout << "■";
			++num;
			Sleep(sl);
		}
		for (;i > times + 1;--i) {
			PosScreen(j, i);
			cout << "■";
			++num;
			Sleep(sl);
		}
		for (;j > times + 1;--j) {
			PosScreen(j, i);
			cout << "■";
			++num;
			Sleep(sl);
		}
		++times;
	}
	exit(0);
}
void Interface() {
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 8);
	Pos(2, 3);cout << "■■■■■■■■■■■■■■■■■■\n";//18x
	for (int i = 3;i < 24;++i)cout << "  ■\n";
	cout << "  ■■■■■■■■■■■■■■■■■■\n";
	for (int i = 3;i < 24;++i) {
		Pos(i, 37); cout << "■";
		if (i <= 8 || i >= 12) {
			Pos(i, 47); cout << "■";
			Pos(i, 69); cout << "■";
		}
	}
	Pos(2, 47); cout << "■■■■■■■■■■■■";//12x
	Pos(8, 47); cout << "■■■■■■■■■■■■";
	Pos(12, 47); cout << "■■■■■■■■■■■■";
	Pos(24, 47); cout << "■■■■■■■■■■■■";
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 15);
	Pos(9, 53);cout << "下一个  方块";
	Pos(14, 51);cout << "得分:" << Score;
	Pos(15, 51);cout << "速度:" << SleepTime*Speed_mulriple << 's';
	Pos(16, 51);cout << "最高分:" << Max;
	Pos(17, 51);cout << "按R键图像复位";
	Pos(18, 54);cout << "用于输入法导";
	Pos(19, 54);cout << "致的显示错误";
	Pos(20, 51);cout << "上下左右操控";
	Pos(21, 51);cout << "按空格键暂停";
	Pos(22, 51);cout << "按ESC结束游戏";
}
void ScreenPrint() {
	for (int i = 1;i <= Sh;++i) {
		for (int j = 1;j <= Sb;++j) {
			if (Screen[i][j]) {
				PosScreen(i, j);
				cout << "■";
			}
		}
	}
}
void ScreenClear() {
	for (int i = 1;i <= Sh;++i)
		for (int j = 1;j <= Sb;++j) {
			PosScreen(i, j);cout << "  ";
		}

}
void NextShow(unsigned t) {
	Pos(3, 49);cout << "                    ";
	Pos(4, 49);cout << "                    ";
	Pos(5, 49);cout << "                    ";
	Pos(6, 49);cout << "                    ";
	Pos(7, 49);cout << "                    ";
	if (t == 0) { Pos(5, 55);cout << "■■■■"; }
	else if (t == 1) { Pos(4, 57);cout << "■■";Pos(5, 57);cout << "■■"; }
	else if (t == 2) { Pos(4, 59);cout << "■";Pos(5, 55);cout << "■■■"; }
	else if (t == 3) { Pos(4, 57);cout << "■";Pos(5, 55);cout << "■■■"; }
	else if (t == 4) { Pos(4, 55);cout << "■";Pos(5, 55);cout << "■■■"; }
	else if (t == 5) { Pos(4, 57);cout << "■■";Pos(5, 55);cout << "■■"; }
	else { Pos(4, 55);cout << "■■";Pos(5, 57);cout << "■■"; }
}
void Pause() {
	Pos(11, 55);cout << "暂    停";
	do {
		Sleep(200);
	} while (!GetAsyncKeyState(VK_SPACE));
	Pos(11, 55);cout << "        ";
}

void TBuild(Tetris& t, unsigned sh) {
	t.x = 0;
	t.type = sh;
	switch (sh)
	{
	case 0: {
		t.shape[0][0] = 0;t.shape[0][1] = 0;t.shape[0][2] = 0;t.shape[0][3] = 0;//
		t.shape[1][0] = 1;t.shape[1][1] = 1;t.shape[1][2] = 1;t.shape[1][3] = 1;//■■■■
		t.shape[2][0] = 0;t.shape[2][1] = 0;t.shape[2][2] = 0;t.shape[2][3] = 0;//
		t.shape[3][0] = 0;t.shape[3][1] = 0;t.shape[3][2] = 0;t.shape[3][3] = 0;//青色
		t.y = 7;
		break;
	}
	case 1: {
		t.shape[0][0] = 1;t.shape[0][1] = 1;t.shape[0][2] = 0;t.shape[0][3] = 0;//■■
		t.shape[1][0] = 1;t.shape[1][1] = 1;t.shape[1][2] = 0;t.shape[1][3] = 0;//■■
		t.shape[2][0] = 0;t.shape[2][1] = 0;t.shape[2][2] = 0;t.shape[2][3] = 0;//
		t.shape[3][0] = 0;t.shape[3][1] = 0;t.shape[3][2] = 0;t.shape[3][3] = 0;//蓝
		t.y = 8;
		break;
	}
	case 2: {
		t.shape[0][0] = 0;t.shape[0][1] = 0;t.shape[0][2] = 1;t.shape[0][3] = 0;//  ■
		t.shape[1][0] = 1;t.shape[1][1] = 1;t.shape[1][2] = 1;t.shape[1][3] = 0;//■■■
		t.shape[2][0] = 0;t.shape[2][1] = 0;t.shape[2][2] = 0;t.shape[2][3] = 0;//
		t.shape[3][0] = 0;t.shape[3][1] = 0;t.shape[3][2] = 0;t.shape[3][3] = 0;//紫
		t.y = 7;
		break;
	}
	case 3: {
		t.shape[0][0] = 0;t.shape[0][1] = 1;t.shape[0][2] = 0;t.shape[0][3] = 0;// ■
		t.shape[1][0] = 1;t.shape[1][1] = 1;t.shape[1][2] = 1;t.shape[1][3] = 0;//■■■
		t.shape[2][0] = 0;t.shape[2][1] = 0;t.shape[2][2] = 0;t.shape[2][3] = 0;//
		t.shape[3][0] = 0;t.shape[3][1] = 0;t.shape[3][2] = 0;t.shape[3][3] = 0;//绿
		t.y = 7;
		break;
	}
	case 4: {
		t.shape[0][0] = 1;t.shape[0][1] = 0;t.shape[0][2] = 0;t.shape[0][3] = 0;//■
		t.shape[1][0] = 1;t.shape[1][1] = 1;t.shape[1][2] = 1;t.shape[1][3] = 0;//■■■
		t.shape[2][0] = 0;t.shape[2][1] = 0;t.shape[2][2] = 0;t.shape[2][3] = 0;//
		t.shape[3][0] = 0;t.shape[3][1] = 0;t.shape[3][2] = 0;t.shape[3][3] = 0;//红
		t.y = 7;
		break;
	}
	case 5: {
		t.shape[0][0] = 0;t.shape[0][1] = 1;t.shape[0][2] = 1;t.shape[0][3] = 0;// ■■
		t.shape[1][0] = 1;t.shape[1][1] = 1;t.shape[1][2] = 0;t.shape[1][3] = 0;//■■
		t.shape[2][0] = 0;t.shape[2][1] = 0;t.shape[2][2] = 0;t.shape[2][3] = 0;//
		t.shape[3][0] = 0;t.shape[3][1] = 0;t.shape[3][2] = 0;t.shape[3][3] = 0;//橙色
		t.y = 7;
		break;
	}
	case 6: {
		t.shape[0][0] = 1;t.shape[0][1] = 1;t.shape[0][2] = 0;t.shape[0][3] = 0;//■■
		t.shape[1][0] = 0;t.shape[1][1] = 1;t.shape[1][2] = 1;t.shape[1][3] = 0;// ■■
		t.shape[2][0] = 0;t.shape[2][1] = 0;t.shape[2][2] = 0;t.shape[2][3] = 0;//
		t.shape[3][0] = 0;t.shape[3][1] = 0;t.shape[3][2] = 0;t.shape[3][3] = 0;//黄色
		t.y = 7;
		break;
	}
	default: {Pos(1, 1);cerr << "Error 2:方块种类出错!";exit(1);}
	}
}
void TRotate(Tetris& t) {
	if (t.type == 0) {
		Swap(t.shape[0][1], t.shape[1][0]);
		Swap(t.shape[2][1], t.shape[1][2]);
		Swap(t.shape[3][1], t.shape[1][3]);
		for (int i = 0;i < 4;++i)
			for (int j = 0;j < 4;++j)
				if (t.shape[i][j])
					if (i + t.x > Sh || j + t.y>Sb || Screen[t.x + i][t.y + j]) {
						Swap(t.shape[0][1], t.shape[1][0]);
						Swap(t.shape[2][1], t.shape[1][2]);
						Swap(t.shape[3][1], t.shape[1][3]);
					}
	}
	else if (t.type == 1);
	else {
		bool tmp[3][3];
		for (int i = 0;i < 3;++i)
			for (int j = 0;j < 3;++j)
				tmp[i][j] = t.shape[i][j];
		t.shape[0][0] = tmp[2][0];
		t.shape[0][1] = tmp[1][0];
		t.shape[0][2] = tmp[0][0];
		t.shape[1][0] = tmp[2][1];
		t.shape[1][2] = tmp[0][1];
		t.shape[2][0] = tmp[2][2];
		t.shape[2][1] = tmp[1][2];
		t.shape[2][2] = tmp[0][2];
		for (int i = 0;i < 3;++i)
			for (int j = 0;j < 3;++j)
				if (t.shape[i][j])
					if (i + t.x > Sh || j + t.y>Sb || Screen[t.x + i][t.y + j]) {
						for (int i = 0;i < 3;++i)
							for (int j = 0;j < 3;++j)
								t.shape[i][j] = tmp[i][j];
					}
		TShow(t);
	}
}
void TMove(Tetris& t, int d) {
	d -= 5;
	for (int i = 0;i < 4;++i)
		for (int j = 0;j < 4;++j)
			if (t.shape[i][j] && Screen[t.x + i][t.y + j + d])
				return;
	t.y += d;
}
void TDown(Tetris& t) {
	TClear(t);
	int l = 0, i = 0, j = 0;
	while (1) {
		for (i = 0;i < 4;++i)
			for (j = 0;j < 4;++j)
				if (t.shape[i][j] && Screen[t.x + i + 1][t.y + j]) {
					TShow(t);
					return;
				}
		++t.x;
	}
	Sleep(20);
}
void TCopy(Tetris& tt, const Tetris& t) {
	tt.type = t.type;
	tt.x = t.x, tt.y = t.y;
	for (int i = 0;i < 4;++i)
		for (int j = 0;j < 4;++j)
			tt.shape[i][j] = t.shape[i][j];
}
void TShow(const Tetris& t) {
	for (int i = 0;i < 4;++i)
		for (int j = 0;j < 4;++j)
			if (t.shape[i][j] && (t.x + i != 0)) {
				PosScreen(t.x + i, t.y + j);
				cout << "■";
			}
}
void TClear(const Tetris& t) {
	if (t.type == 233)return;
	for (int i = 0;i < 4;++i)
		for (int j = 0;j < 4;++j)
			if (t.shape[i][j] && (t.x + i != 0)) {
				PosScreen(t.x + i, t.y + j);
				cout << "  ";
			}
}

int Judge_down(const Tetris& t) {
	for (int i = 0;i < 4;++i)
		for (int j = 0;j < 4;++j)
			if (t.shape[i][j] && Screen[t.x + i][t.y + j]) {
				for (int i = 0;i < 4;++i)
					for (int j = 0;j < 4;++j)
						if (t.shape[i][j])
							Screen[t.x + i - 1][t.y + j] = 1;
				return 1;
			}
	return 0;
}
int Judge_key() {
	unsigned d = 5;
	if (GetAsyncKeyState(VK_UP)) d = 8;
	else if (GetAsyncKeyState(VK_DOWN)) d = 2;
	else if (GetAsyncKeyState(VK_LEFT)) d = 4;
	else if (GetAsyncKeyState(VK_RIGHT)) d = 6;
	else if (GetAsyncKeyState(VK_SPACE)) Pause();
	else if (GetAsyncKeyState(VK_ESCAPE)) d = 0;
	else if (GetAsyncKeyState(0x52)) {
		system("cls");
		Interface();
		ScreenPrint();
		Pos(4, 49);cout << "R键图像复位导致下一";
		Pos(5, 49);cout << "个方块的显示失效BUG";
		Pos(6, 49);cout << "不高兴修复了";
	}
	return d;
}
int Judge_eliminate(const Tetris& t) {
	int judge = 0;
	for (int i = 0;i < 4;++i) {
		for (int j = 0;j < 4;++j)
			if (t.shape[i][j]) {
				int k;
				unsigned xx = t.x - 1;
				for (k = 1;k <= Sb&&Screen[xx + i][k];++k);
				if (k > Sb) {
					++judge;
					int blank = 0;
					if (xx == 1) {
						for (int l = 1;l <= Sb;++l)
							Screen[1][l] = 0;
						break;
					}
					while (blank != Sb) {
						blank = 0;
						for (int l = 1;l <= Sb;++l) {
							Screen[xx + i][l] = Screen[xx + i - 1][l];
							if (!Screen[xx + i - 1][l])++blank;
						}
						--xx;
					}
				}
				break;
			}
	}
	return judge;
}
int Judge_gameover(const Tetris& t) {
	for (int i = 0;i < 4;++i)
		if (t.shape[1][i] && Screen[1][t.y + i]) {
			PosScreen(10, 6);cout << "Game Over!";
			End();
		}
	return 0;
}

void Pos(unsigned x, unsigned y) {
	COORD p;
	try { if (x < 1 || y < 1) throw 1; }//测试代码,记得删除
	catch (int) { Pos(1, 1);cerr << "Error 1:坐标出错!";exit(1); }//测试代码,记得删除
	p.X = y - 1;p.Y = x - 1;
	SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), p);
}
void PosScreen(unsigned x, unsigned y)
{
	Pos(x + 2, 2 * y + 3);
}
void Swap(bool& a, bool& b) {
	bool t = a;
	a = b;b = t;
}


int main()
{
	Start();
	Game();
	Pos(11, 50);
	return 0;
}

截图:

[玩耍]俄罗斯方块_第1张图片


你可能感兴趣的:(玩耍)