C++写的一个很粗糙的俄罗斯方块

#include<iostream>
#include<cstdlib>
#include<vector>
#include <chrono>
#include <future>
#include<conio.h>
#include <fstream>
#include <algorithm>


const int MAP_W = 10;
const int MAP_H = 24;

int gameend_flag = 0;
int GameScore = 0;

/*std::vector<std::vector<bool>>*/bool GAME_MAP[MAP_W] /*std::vector<bool>(*/[MAP_H];

//方块类型
enum class TetroType {
	I,
	J,
	L,
	O,
	S,
	T,
	Z
};

struct Tetromino {
	int x, y;					//中心块坐标
	int Side_Block [3][2];		//边缘方块相对坐标
};

class Block {
public:
	Block()		//随机形状,方块初始化
	{
		TetroType TypeList[7] = { TetroType::I,TetroType::J,TetroType::L,TetroType::O,TetroType::S,TetroType::T,TetroType::Z };
		int i = rand() % 7;
		MyTetroType = TypeList[i];
		switch (MyTetroType) {
		case TetroType::I:
			MyTrtro.x = 3;
			MyTrtro.y = 3;
			MyTrtro.Side_Block[0][0] = MyTrtro.x - 1;
			MyTrtro.Side_Block[0][1] = MyTrtro.y;
			MyTrtro.Side_Block[1][0] = MyTrtro.x + 1;
			MyTrtro.Side_Block[1][1] = MyTrtro.y;
			MyTrtro.Side_Block[2][0] = MyTrtro.x + 2;
			MyTrtro.Side_Block[2][1] = MyTrtro.y;
			break;
		case TetroType::J:
			MyTrtro.x = 5;
			MyTrtro.y = 2;
			MyTrtro.Side_Block[0][0] = MyTrtro.x;
			MyTrtro.Side_Block[0][1] = MyTrtro.y - 1;
			MyTrtro.Side_Block[1][0] = MyTrtro.x;
			MyTrtro.Side_Block[1][1] = MyTrtro.y + 1;
			MyTrtro.Side_Block[2][0] = MyTrtro.x - 1;
			MyTrtro.Side_Block[2][1] = MyTrtro.y + 1;
			break;
		case TetroType::L:
			MyTrtro.x = 4;
			MyTrtro.y = 2;
			MyTrtro.Side_Block[0][0] = MyTrtro.x;
			MyTrtro.Side_Block[0][1] = MyTrtro.y - 1;
			MyTrtro.Side_Block[1][0] = MyTrtro.x;
			MyTrtro.Side_Block[1][1] = MyTrtro.y + 1;
			MyTrtro.Side_Block[2][0] = MyTrtro.x + 1;
			MyTrtro.Side_Block[2][1] = MyTrtro.y + 1;
			break;
		case TetroType::O:
			MyTrtro.x = 4;
			MyTrtro.y = 3;
			MyTrtro.Side_Block[0][0] = MyTrtro.x + 1;
			MyTrtro.Side_Block[0][1] = MyTrtro.y;
			MyTrtro.Side_Block[1][0] = MyTrtro.x + 1;
			MyTrtro.Side_Block[1][1] = MyTrtro.y - 1;
			MyTrtro.Side_Block[2][0] = MyTrtro.x;
			MyTrtro.Side_Block[2][1] = MyTrtro.y - 1;
			break;
		case TetroType::S:
			MyTrtro.x = 5;
			MyTrtro.y = 2;
			MyTrtro.Side_Block[0][0] = MyTrtro.x - 1;
			MyTrtro.Side_Block[0][1] = MyTrtro.y + 1;
			MyTrtro.Side_Block[1][0] = MyTrtro.x;
			MyTrtro.Side_Block[1][1] = MyTrtro.y + 1;
			MyTrtro.Side_Block[2][0] = MyTrtro.x + 1;
			MyTrtro.Side_Block[2][1] = MyTrtro.y;
			break;
		case TetroType::T:
			MyTrtro.x = 4;
			MyTrtro.y = 3;
			MyTrtro.Side_Block[0][0] = MyTrtro.x - 1;
			MyTrtro.Side_Block[0][1] = MyTrtro.y;
			MyTrtro.Side_Block[1][0] = MyTrtro.x;
			MyTrtro.Side_Block[1][1] = MyTrtro.y - 1;
			MyTrtro.Side_Block[2][0] = MyTrtro.x + 1;
			MyTrtro.Side_Block[2][1] = MyTrtro.y;
			break;
		case TetroType::Z:
			MyTrtro.x = 4;
			MyTrtro.y = 2;
			MyTrtro.Side_Block[0][0] = MyTrtro.x - 1;
			MyTrtro.Side_Block[0][1] = MyTrtro.y - 1;
			MyTrtro.Side_Block[1][0] = MyTrtro.x;
			MyTrtro.Side_Block[1][1] = MyTrtro.y - 1;
			MyTrtro.Side_Block[2][0] = MyTrtro.x + 1;
			MyTrtro.Side_Block[2][1] = MyTrtro.y;
			break;
		}
		ContrlDraw();
	}
	bool Delete_Flag = false;
	void KeyInput(char ch);							//对键盘输入的识别,以及对应操作的总函数
	void Move_Down();								//每秒一次,自动执行的下移函数,每次下移前执行固化函数
	
	void ContrlDraw();								//屏幕更新的绘画

	enum class TetroType MyTetroType;				//方块形状的枚举变量
//	int state = 0;
	struct Tetromino MyTrtro;						//方块结构体变量
	
	void Anticlock_whirl();							//逆时针旋转
	void Clock_whirl();								//顺时针旋转
	void Pan_Left();								//左平移
	void Pan_Right();								//右平移
	
};



void Block::Anticlock_whirl() {
	int Side_Block_imme[3][2];
	bool False_Flag = false;
	for (int i = 0; i < 3; i++) {
		Side_Block_imme[i][1] = MyTrtro.y+( MyTrtro.Side_Block[i][0] - MyTrtro.x);
		Side_Block_imme[i][0] = MyTrtro.x-(MyTrtro.Side_Block[i][1] - MyTrtro.y);
		if(Side_Block_imme[i][1] >= MAP_H || Side_Block_imme[i][1] < 0 ||
			Side_Block_imme[i][0] >= MAP_W || Side_Block_imme[i][0] < 0 ||
			GAME_MAP[Side_Block_imme[i][0]][Side_Block_imme[i][1]]==true)
			False_Flag = true;
	}
	if (False_Flag == false)
		for (int i = 0; i < 3; i++)
			for (int j = 0; j < 2; j++)
				MyTrtro.Side_Block[i][j] = Side_Block_imme[i][j];
}

void Block::Clock_whirl() {
	int Side_Block_imme[3][2];
	bool False_Flag = false;
	for (int i = 0; i < 3; i++) {
		Side_Block_imme[i][1] = MyTrtro.y-( MyTrtro.Side_Block[i][0] - MyTrtro.x);
		Side_Block_imme[i][0] = MyTrtro.x+(MyTrtro.Side_Block[i][1] - MyTrtro.y);
		if (Side_Block_imme[i][1] >= MAP_H || Side_Block_imme[i][1] < 0 ||
			Side_Block_imme[i][0] >= MAP_W || Side_Block_imme[i][0] < 0 ||
			GAME_MAP[Side_Block_imme[i][0]][Side_Block_imme[i][1]] == true) {
			False_Flag = true;
			break;
		}
	}
	if (False_Flag == false)
		for (int i = 0; i < 3; i++)
			for (int j = 0; j < 2; j++)
				MyTrtro.Side_Block[i][j] = Side_Block_imme[i][j];

}

void Block::ContrlDraw() {
	system("cls");
	bool GAME_MAP_imme[MAP_W][MAP_H] ;
	for (int i = 0; i < MAP_W; i++)
		for (int j = 0; j < MAP_H; j++)
			GAME_MAP_imme[i][j] = GAME_MAP[i][j];
	GAME_MAP_imme[MyTrtro.x][MyTrtro.y] = true;
	for (int i = 0; i < 3; i++)
		GAME_MAP_imme[MyTrtro.Side_Block[i][0]][MyTrtro.Side_Block[i][1]] = true;

	std::cout << " ---------- " << std::endl;
	for (int i = 4; i < MAP_H; i++) {
		std::cout << "|";
		for (int j = 0; j < MAP_W; j++) {
			if (GAME_MAP_imme[j][i] == true)
				std::cout << "*";
			else
				std::cout << " ";
		}
		std::cout <<"|"<< std::endl;
	}
	std::cout << " ---------- " << std::endl;
}

void Block::Move_Down() {
	bool Flag = false;					//固定标志位判断,为真则固定
	if (MyTrtro.y + 1 >= 24 || GAME_MAP[MyTrtro.x][MyTrtro.y + 1] == true)
		Flag = true;
	for (int i = 0; i < 3; i++) {
		if (MyTrtro.Side_Block[i][1] + 1 >= MAP_H || GAME_MAP[MyTrtro.Side_Block[i][0]][MyTrtro.Side_Block[i][1] + 1] == true)
			Flag = true;
	}

	if (Flag == true) {
		GAME_MAP[MyTrtro.x][MyTrtro.y ] = true;
		for (int i = 0; i < 3; i++)
			GAME_MAP[MyTrtro.Side_Block[i][0]][MyTrtro.Side_Block[i][1]] = true;
		Delete_Flag = true;
		
	}
	else {
		MyTrtro.y = MyTrtro.y + 1;
		for (int i = 0; i < 3; i++)
			MyTrtro.Side_Block[i][1] += 1;

	}

	ContrlDraw();
}



void Block::Pan_Left() {
	if (MyTrtro.x - 1 < 0 || GAME_MAP[MyTrtro.x - 1][MyTrtro.y] == true)
		return ;
	for (int i = 0; i < 3; i++) {
		if (MyTrtro.Side_Block[i][0] - 1 < 0 || GAME_MAP[MyTrtro.Side_Block[i][0] - 1][MyTrtro.Side_Block[i][1]] == true)
			return ;
	}
	MyTrtro.x = MyTrtro.x - 1;
	for (int i = 0; i < 3; i++)
		MyTrtro.Side_Block[i][0] -= 1;
}

void Block::Pan_Right() {
	if (MyTrtro.x + 1 >=10 || GAME_MAP[MyTrtro.x +1][MyTrtro.y] == true)
		return;
	for (int i = 0; i < 3; i++) {
		if (MyTrtro.Side_Block[i][0] + 1  >=MAP_W || GAME_MAP[MyTrtro.Side_Block[i][0] + 1][MyTrtro.Side_Block[i][1]] == true)
			return;
	}
	MyTrtro.x = MyTrtro.x + 1;
	for (int i = 0; i < 3; i++)
		MyTrtro.Side_Block[i][0] += 1;
}

void Block::KeyInput(char ch) {
	if (ch == 'A' || ch == 'a')
		Pan_Left();
	else if (ch == 'D' || ch == 'd')
		Pan_Right();
	else if (ch == 'W' || ch == 'w')
		Clock_whirl();
	else if (ch == 'S' || ch == 's')
		Anticlock_whirl();

	ContrlDraw();
}




void Delay_1s() {
	std::this_thread::sleep_for(std::chrono::seconds(1));
}


void Update(Block** pt) {
	(*pt)->Move_Down();
	

	if ((*pt)->Delete_Flag == true) {
		delete *pt;

		for(int i=0;i<MAP_W;i++)
			if (GAME_MAP[i][4] == true) {
				gameend_flag = 1;
				return;
			}
		
		*pt = new Block;
		
	}



	//遍历整个地图展示的数组,检测是否有整行填满,有则清除加下移
	else {
		for (int i = 0; i < MAP_H; i++) {
			bool flag = true;
			for (int j = 0; j < MAP_W; j++)
				if (GAME_MAP[j][i] == false)
					flag = false;
			if (flag == true) {
				GameScore++;
				for (int n = i; n >= 5; n--)
					for (int j = 0; j < MAP_W; j++)
						GAME_MAP[j][n] = GAME_MAP[j][n - 1];

			}
		}
	}
	(*pt)->ContrlDraw();
}

void GAME_MAP_Init()
{
	gameend_flag = 0;
	GameScore = 0;
	for (int i = 0; i < MAP_W; i++)
	{
		for (int j = 0; j < MAP_H; j++)
			GAME_MAP[i][j] = false;
	}
}


// 函数用来读取高分榜
std::vector<int> readHighScores(const std::string& filename) {
	std::vector<int> scores;
	std::ifstream infile(filename);
	int score;
	while (infile >> score) { // 读取分数
		scores.push_back(score);
	}
	std::sort(scores.begin(), scores.end(), std::greater<int>()); // 排序
	return scores;
}

// 函数用来写入高分榜
void writeHighScores(const std::vector<int>& scores, const std::string& filename) {
	std::ofstream outfile(filename);
	for (const auto& score : scores) { // 将分数写入文件
		outfile << score << std::endl;
	}
}

// 检查并更新高分榜
void updateHighScores(int newScore, std::vector<int>& scores) {
	scores.push_back(newScore);
	std::sort(scores.begin(), scores.end(), std::greater<int>());
	if (scores.size() > 3) {
		scores.pop_back(); // 保持前3名
	}
}

void state_UI(int state) {
	system("cls");
	if (state == 1) 
		std::cout << "开始游戏\t<-" << std::endl << "高分排行" << std::endl << "结束游戏" << std::endl;
	else if(state==2)
		std::cout << "开始游戏" << std::endl << "高分排行\t<-" << std::endl << "结束游戏" << std::endl;
	else if(state==3)
		std::cout << "开始游戏" << std::endl << "高分排行" << std::endl << "结束游戏\t<-" << std::endl;
}

Block* pt;


int main()
{
	srand((unsigned int)time(NULL));															//随机数种子
	int state = 0;


	while (1) {//选择UI界面
		if (state == 0) {
			int state_imme = 1;
			state_UI(state_imme);
			while (1) {
				if (_kbhit()) {
					char input = _getch();
					if (input == '\r') {
						state = state_imme;
						break;
					}
					else if (input == 'w' || input == 'W')
					{
						if (state_imme == 1)
							state_imme = 3;
						else
							state_imme--;
						state_UI(state_imme);
					}
					else if (input == 's' || input == 'S')
					{
						if (state_imme == 3)
							state_imme = 1;
						else
							state_imme++;
						state_UI(state_imme);
					}
				}


			}
		}

		else if (state == 1) {
			GAME_MAP_Init();																			//初始化游戏地图
			pt = new Block;																				//新的方块
			auto Delay = std::async(std::launch::async, Delay_1s);										//一秒的记时
			char ch;
			while (gameend_flag != 1) {
				//检测键盘输入,有则捕获且开启输入判断
				if (_kbhit()) {
					ch = _getch();
					pt->KeyInput(ch);
				}
				//如果一秒延时已完成,更新方块+开启新一秒的计时
				if (Delay.wait_for(std::chrono::seconds(0)) == std::future_status::ready) {
					Update(&pt);
					Delay = std::async(std::launch::async, Delay_1s);
				}

			}
			system("cls");
			std::cout << "GAME OVER" << std::endl << "YOUR SCORES:" << GameScore << std::endl;

			std::string highScoresFile = "highscores.txt"; // 高分榜文件

			// 读取高分榜
			std::vector<int> highScores = readHighScores(highScoresFile);

			// 检查是否需要更新高分榜
			updateHighScores(GameScore, highScores);

			// 保存更新后的高分榜
			writeHighScores(highScores, highScoresFile);
		}
		else if (state == 2) {
			std::string highScoresFile = "highscores.txt"; // 高分榜文件

			// 读取高分榜
			std::vector<int> highScores = readHighScores(highScoresFile);

			// 显示高分榜
			system("cls");
			std::cout << "High Scores:" << std::endl;
			for (const auto& score : highScores) {
				std::cout << score << std::endl;
			}
			std::cout << "请按Q以退出" << std::endl;
			while (1) {
				if (_kbhit()) {
					char input = _getch();
					if (input == 'q' || input == 'Q')
						break;
				}
			}
			state = 0;
		}
		else if (state == 3)
			return 0;
		
	}
	
}

当时写的时候没注意,就成了现在这种没注释也没分文件的蠢模样,懒得弄了,遂鸽。

其实原理还挺简单的,暴力枚举的初始化,确定中心方块后一个个写变换函数 然后异步检测键盘输入和计时每一秒,用一个指针指向最新的活的方块.

其他还有没有主动下移,没有用EasyX画出来等小毛病,但懒得改了,鸽

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值