c++俄罗斯方块代码 控制台窗口

大学时无聊写的demo,直接复制可用,用的好像是vs2015,太低版本应该无法使用,直接复制进去就可以运行了

#pragma warning(disable:4996)//sprintf出错加这句
#include<iostream>
#include<string>
#include<stdio.h>
#include <time.h> 
#include <windows.h>
#include <Windows.h> 
#include <thread> 
#include <stdlib.h>
#include <conio.h>  //键盘按下判断相关头文件
#include<cstdio>
#include<cstdlib>

#define XX 20
#define YY 30
#define KEY_DOWN(vk_c) (GetAsyncKeyState(vk_c)&0x8000?1:0)
using namespace std;


char p[31][20][2];//------------------此三维数组前面如果作定义整个系统都会混乱
int spin = 1;//旋转变量
int MX = 0, MY = -4;//默认出现的位置
int FX = MX, FY = MY;
int Time = 500;//初始化下降延时
HANDLE hOutput, hOutBuf;//控制台屏幕缓冲区句柄
COORD coord = { 0,0 };
//双缓冲处理显示
DWORD bytes = 0;
int Gdata = 0;//修改方块信息变量
int weizhi = 0;//修改方块位置变量
int Down = 0;//识别函数下降
int Gp = 0;//识别打印函数
int Clear = 0;//识别清行
int FIX[5], FIY[5];//移动特征量
int fen = 0;
char  o[3] = "▇";
char  k[3] = "  ";char  b[3] = "◆";
char control = 0;
int F1[4][4] = { { 0,1,0,0 },{ 0,1,0,0 },{ 0,1,0,0 },{ 0,1,0,0 } },//条形
    F2[4][4] = { { 0,0,0,0 },{ 1,1,1,1 },{ 0,0,0,0 },{ 0,0,0,0 } },
    F3[4][4] = { { 0,1,1,0 },{ 0,1,1,0 },{ 0,0,0,0 },{ 0,0,0,0 } },//正方形
    F4[4][4] = { { 0,1,0,0 },{ 0,1,1,0 },{ 0,0,1,0 },{ 0,0,0,0 } },//梯形
	F5[4][4] = { { 0,0,1,0 },{ 0,1,1,0 },{ 0,1,0,0 },{ 0,0,0,0 } },
	F6[4][4] = { { 0,0,0,0 },{ 1,0,0,0 },{ 1,1,1,0 },{ 0,0,0,0 } },
	F7[4][4] = { { 0,0,0,0 },{ 0,0,0,1 },{ 0,1,1,1 },{ 0,0,0,0 } },
    F8[4][4] = { { 0,0,0,0 },{ 0,1,0,0 },{ 1,1,1,0 },{ 0,0,0,0 } };
int FF[4][4];//方块位置  当前方块------------	此二维数组需要定义在三维数组后才不冲突!!!!否则整个系统都会混乱

void GW(int x,int y)//修改当前方块位置
{
	if (weizhi == 0)
	{
		weizhi = 1;
		FX = x; FY = y;
		weizhi = 0;
	}
}
void dayin()//初始化边界
{
	for (int y = 0;y <30;y++)
	{
		for (int x = 0;x < 20;x++)
		{
			if (y == 0 || y == 29)
			{
				for (int z = 0;z < 2;z++)
				{
					p[y][x][z] = o[z];
				}
			}

			else
			{
				if (x == 0 || x == 19)
				{
					for (int z = 0;z < 2;z++)
					{
							p[y][x][z] = o[z];
					}
				}
				else
				{
					for (int z = 0;z < 2;z++)
					{
							p[y][x][z] = k[z];
					}
				}
			}
			/*cout << "z=" << p[y][x][2] << endl;*/
		}
		
	}
}

void fo(int y, int x)//(修改p数组)
{
	for (int z = 0;z < 2;z++)
	{
		p[y][x][z] = o[z];
	}
}

void fk(int y, int x)//(修改p数组)
{
	for (int z = 0;z < 2;z++)
	{
		p[y][x][z] = k[z];
	}
}

void print(char p[30][20][2])//打印数组
{
	while (1)
	{
		//创建新的控制台缓冲区
		
		hOutBuf = CreateConsoleScreenBuffer(
			GENERIC_WRITE,//定义进程可以往缓冲区写数据
			FILE_SHARE_WRITE,//定义缓冲区可共享写权限
			NULL,
			CONSOLE_TEXTMODE_BUFFER,
			NULL
		);
		hOutput = CreateConsoleScreenBuffer(
			GENERIC_WRITE,//定义进程可以往缓冲区写数据
			FILE_SHARE_WRITE,//定义缓冲区可共享写权限
			NULL,
			CONSOLE_TEXTMODE_BUFFER,
			NULL
		);
		//隐藏两个缓冲区的光标
		CONSOLE_CURSOR_INFO cci;
		cci.bVisible = 0;
		cci.dwSize = 1;
		SetConsoleCursorInfo(hOutput, &cci);
		SetConsoleCursorInfo(hOutBuf, &cci);
		int x = 0, y = 0;
		if (Gp == 0)
		{
			
			for (int i = 0; i < 31; i++)
			{
				coord.Y = i;
				WriteConsoleOutputCharacterA(hOutBuf, *p[i], 40, coord, &bytes);
			}
		}
		//设置新的缓冲区为活动显示缓冲
		SetConsoleActiveScreenBuffer(hOutBuf);
		Sleep(10);
		if (Gp == 0)
		{	
			for (int i = 0; i < 31; i++)
			{
				coord.Y = i;
				WriteConsoleOutputCharacterA(hOutput, *p[i], 40, coord, &bytes);
			}
		}
		//设置新的缓冲区为活动显示缓冲
		SetConsoleActiveScreenBuffer(hOutput);
		Sleep(10);
	}
}

void clg()
{
	system("mode con cols=40 lines=31");//改变宽高
	system("color fc");//改变颜色
}

void printF(int w)//对当前的方块进行 打印和清除方块 (调用 fo fk 修改p数组)
{
	if (Gp == 0)
	{
		Gp = 1;
		for (int i = 0;i < 4;i++)
		{
			for (int j = 0;j < 4;j++)
			{
				if (FF[i][j] == 1 && w == 1)
				{
					fo(i + FY + 1, j + FX + 1);//打印方块
				}
				else if (FF[i][j] == 1 && w == 0 && i + FY + 1> 0)  // && j + FX + 1 > 0 && j + FX + 1 < 19
				{
					fk(i + FY + 1, j + FX + 1);//清除方块
				}
			}
		}
		Gp = 0;
	}
}
void Fdata(int F[4][4], int x)//改写当前控制方块的数据
{
	if (Gdata == 0)
	{
		Gdata = 1;//正在改写方块数据
		if (x == 1)
		{
			for (int i = 0;i < 4;i++)
			{
				
				for (int j = 0;j < 4;j++)
				{
					FF[i][j] = F[i][j];
				}
			}
		}
		if (x == 0)
		{
			for (int i = 0;i < 4;i++)
			{
				for (int j = 0;j < 4;j++)
				{
					FF[i][j] = -1;//方块删除信息
					GW(MX, MY);//方块初始化位置
				}
			}
		}
		Gdata = 0;//改写方块数据完毕
	}
}

int printFI(int x)//获取方块当前方块的移动特征量(x=0,左;x=1,右;x=2,下)
{
	if (Gdata == 0)
	{
		if (x == 0)//获取最左侧的特征量(左移时)
		{
			for (int i = 0;i <4;i++)
			{
				int a = 0;
				for (int j = 0;j < 4;j++)
				{
					if (FF[i][j] == 1&&FY+i>=0)//存在位置
					{
						FIX[i] = j;//获取最左侧特征量
						FIY[i] = i;
						a = 1;//获取成功
						j = 5;//获取成功后跳出循环
					}
				}
				if (a == 0)//当获取不成功特征量时
				{
					FIX[i] = -1;//特征量=-1
					FIY[i] = -1;
				}
			}
		}
		else if (x == 1)//获取最右测的特征量(右移时)
		{
			for (int i = 0;i <4;i++)
			{
				int a = 0;
				for (int j = 3;j >= 0;j--)
				{
					if (FF[i][j] == 1 && FY + i >= 0)//存在位置
					{
						FIX[i] = j;//获取最右侧特征量
						FIY[i] = i;
						a = 1;//获取成功
						j = -1;//获取成功后跳出循环
					}
				}
				if (a == 0)//当获取不成功特征量时
				{
					FIX[i] = -1;//特征量=-1
					FIY[i] = -1;
				}
			}
		}

		else if (x == 2)//获取最底下的特征量(下降时)
		{
			int aa;
			
			for (int i = 0;i < 4;i++)
			{
				aa = 0;


				for (int j = 3;j >= 0;j--)
				{
					if (FF[j][i] == 1)//存在位置
					{
						FIX[i] = i;//获取最下特征量
						FIY[i] = j;
						aa = 1;//获取成功
						break;//获取成功后跳出循环
					}
				}
				if (aa == 0)//当获取不成功特征量时
				{
					FIX[i] = -1;//特征量=-1
					FIY[i] = -1;
				}
			}
		}
		return 1;//证明获取成功特征量
	}
	else { return 0; }//证明获取失败特征量
}
void chushif()//随机生成方块
{
	if (Gdata == 0)
	{
		int xun;
		xun = (rand() % 8) + 1;//其随机域为0~MAX-1
		switch (xun)
		{
		case 1:Fdata(F1, 1);SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_BLUE);break;
		case 2:Fdata(F2, 1);SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_GREEN);break;
		case 3:Fdata(F3, 1);SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED |FOREGROUND_BLUE);break;
		case 4:Fdata(F4, 1);SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_GREEN |FOREGROUND_BLUE);break;
		case 5:Fdata(F5, 1);SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY);break;
		case 6:Fdata(F6, 1);SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED);break;
		case 7:Fdata(F7, 1);SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED |FOREGROUND_GREEN | FOREGROUND_BLUE);break;
		case 8:Fdata(F8, 1);SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_GREEN);break;
		}
	}
}
void Fdown()//方块下降函数(执行一次,判断是否能下降,可以的话下降一次)
{
	if (Gdata == 0&&weizhi==0&&Down == 0&&Gp==0 && Clear == 0)
	{
		Down = 1;
	
		int x0 = 0, x1 = 0;

		//获取下降的特征量
		if (printFI(2) ==1)//当获取成功特征量时才执行以下操作
		{
			for (int i = 0;i < 4;i++)
			{
				if (FIX[i] >= 0) //当特征量存在时
				{
					x0 = x0 + 1; //计算有几个特征量
					if (p[FY + FIY[i] + 2][FX + FIX[i] + 1][1] != '~' || FY + FIY[i] + 2 <= 0)//识别特征量下是否有空位,当特征量下的位置是<=0时,方块还未出现,默认有空位
					{
						x1 = x1 + 1;//计算有几个特征量下的空位
					}
				}
			}
			if (x0 != 0 && x0 != x1)//当特征量和特征量底下空位数量不相等时,清除当前控制的方块信息(位置和数据)
			{
				Fdata(F1, 0);
				GW(7, -4);
				spin = 1;
				chushif();
				Time = Time - 1;
				Clear = 1;
			}
			if (x0 != 0 && x0 == x1)//当特征量和特征量底下空位数量相等时,可以向下移动
			{
				printF(0);//清除现在的图像
				GW(FX, FY + 1);//当前Y轴位置加1
				printF(1);//打印下移后的图像
				
			}
		}
		Down = 0;
	}
}


void Fleft()//方块左移函数
{
	if (Gdata == 0 && weizhi == 0)
	{
		int x0 = 0, x1 = 0;
		//获取左移的特征量
		if (printFI(0) == 1)//当获取成功特征量时才执行以下操作
		{
			for (int i = 0;i < 4;i++)
			{
				if (FIX[i] >= 0) //当特征量存在时
				{
					x0 = x0 + 1; //计算有几个特征量
					if (p[FY + FIY[i] + 1][FX + FIX[i] ][1] != '~')//识别特征量左是否有空位
					{
						x1 = x1 + 1;//计算有几个特征量左的空位
					}
				}
			}
			if (x0 != 0 && x0 == x1)//当特征量和特征量底下空位数量相等时,可以向左移动
			{
				printF(0);//清除现在的图像
				GW(FX-1, FY );//当前X轴位置减一
				printF(1);//打印左移后的图像
			}
		}
	}
}

void Fright()//方块右移函数
{
	if (Gdata == 0 && weizhi == 0)
	{
		int x0 = 0, x1 = 0;
		//获取右移的特征量
		if (printFI(1) == 1)//当获取成功特征量时才执行以下操作
		{
			for (int i = 0;i < 4;i++)
			{
				if (FIX[i] >= 0) //当特征量存在时
				{
					x0 = x0 + 1; //计算有几个特征量
					if (p[FY + FIY[i] + 1][FX + FIX[i]+2 ][1] != '~')//识别特征量右是否有空位
					{
						x1 = x1 + 1;//计算有几个特征量右的空位
					}
				}
			}
			if (x0 != 0 && x0 == x1)//当特征量和特征量右空位数量相等时,可以向右移动
			{
				printF(0);//清除现在的图像
				GW(FX +1, FY);//当前X轴位置加1
				printF(1);//打印右移后的图像
			}
		}
	}
}

void Fspin()//方块旋转函数
{
	
	if (Gdata == 0 && weizhi == 0&&Down == 0)
	{
		Gdata = 1;
		int GFF[4][4];
		if (spin == 4)
		{
			for (int i = 0, y = 3;i < 4 && y >= 0;i++, y--)//右转四次
			{
				for (int j = 0, x = 3;j < 4 && x >= 0;j++, x--)
				{
					GFF[i][j] = FF[x][i];
				}
			}
			
		}

	   else if (spin == 3)
		{
			for (int i = 0, y = 3;i < 4 && y >= 0;i++, y--)//右转三次
			{
				for (int j = 0, x = 3;j < 4 && x >= 0;j++, x--)
				{
					GFF[x][i] = FF[y][x];
				}
			}
			
		}
		else if (spin == 2)
		{
			for (int i = 0, y = 3;i < 4 && y >= 0;i++, y--)//右转两次
			{
				for (int j = 0, x = 3;j < 4 && x >= 0;j++, x--)
				{
					GFF[y][x] = FF[j][y];
				}

			}
			
		}
		else if (spin == 1)
		{
			for (int i = 0, y = 3;i < 4 && y >= 0;i++, y--)//右转一次
			{
				for (int j = 0, x = 3;j < 4 && x >= 0;j++, x--)
				{
					GFF[j][y] = FF[i][j];
				}
			}
			
		}
		int x0 = 0, x1 = 0;
		for (int i = 0;i < 4;i++)
		{
			for (int j = 0;j < 4;j++)
			{
				if (GFF[i][j] == 1&& FF[i][j] != GFF[i][j])//判断是否可以旋转
				{
					x0 = x0 + 1;
					if (p[FY + i+1][FX + j+1][1] != '~')
					{
						x1 = x1 + 1;
					}
				}
			}
		}
		if (x0 != 0 && x0 == x1)//当特征量和空位数量相等时,可以旋转
		{
			
			if (spin == 4)
			{
				spin = 1;
			}
			else
			{ 
				spin = spin + 1; 
			}
			printF(0);//清除现在的图像
			for (int i = 0;i < 4;i++)
			{
				for (int j = 0;j < 4;j++)
				{
					FF[i][j] = GFF[i][j];
				}
			}
			printF(1);//打印旋转后的图像
		}
		Gdata = 0;
	}
}

void anjian()//检测键盘输入数据
{
	char ch;
	for (;;)
	{
		if (_kbhit())
		{
			ch = _getch();
			if (ch == 'P')//向下
			{
				Fdown();
				ch = ' ';
			}

			else if (ch == 'K')//向左
			{
				Fleft();
				ch = ' ';
			}

			else if (ch == 'M')//向右
			{
				Fright();
				ch = ' ';
			}
			else if (ch == 'H')//向上
			{
				Fspin();
				ch = ' ';
			}
		}
	}
}
void clear()//检测是否需要清行
{
	if (Gp == 0 && Down == 0&&Clear==1)
	{
		Gp = 1;
		int x0 = 0;
		for (int i = 1;i < 29;i++)
		{
			x0 = 0;
			for (int j = 1;j < 19;j++)
			{
				if (p[i][j][1] == '~')
				{
					x0 = x0 + 1;
				}
			}
			if (x0 == 18)
			{
				fen = fen + 1;
				for (int j = 1;j < 19;j++)
				{
					for (int z = 0;z < 2;z++)
					{
						
						p[i][j][z] = k[z];

					}
				}

				for (int y = i;y > 0;y--)
				{
					for (int x = 1;x < 19;x++)
					{
						for (int z = 0;z < 2;z++)
						{
							if (y - 1 > 0)
							{
								p[y][x][z] = p[y - 1][x][z];
							}
						}
					}
				}
			}
		}
		Gp = 0;Clear = 0;
	}
}
int over = 0;
void Gameover()//检测游戏是否结束
{
	int x0 = 0;
		for (int j = 1;j < 19;j++)
		{
			if (p[1][j][1] == '~')
			{
				int a = 0;
				for (int y = 0;y < 4;y++)
				{
					for (int x = 0;x < 4;x++)
					{
						if (FF[y][x] == 1&&FY + y+1 ==1 &&FX + x+1 == j)//判断是否是当前方块
						{
							a = 1;
						}
					}
				}
				if (a == 0)
				{
					x0 = x0 + 1;
					break;
				}
			}
		}
	
		if (x0 == 1)
		{
			over=::MessageBox(NULL, TEXT("游戏结束,菜鸡!\n是否重新开始?"), TEXT("操作提示"), 1);
		}
	
}


void printfen()
{
	if (Gp == 0)
	{
		char z1[3] = "得";
		char z2[3] = "分";
		char z3[3] = ":";
		char f[20];
		sprintf(f, "%d", fen);

		for (int z = 0;z < 2;z++)
		{
			p[30][3][z] = z1[z];
			p[30][5][z] = z2[z];
			p[30][7][z] = z3[z];
			p[30][9][z] = f[z];
		}
		/*	p[8][7][1] = char(fen - '0');p[8][7][2] = '/0';*/
	}
			
		
	
}
void main()
{
	srand((unsigned)time(NULL));//srand()函数产生一个以当前时间开始的随机种子
	clg();//初始化窗口
	dayin();//初始化界面
	chushif();//随机方块
	GW(7, -4);//初始化位置
	thread task01(anjian);//检测按键
	thread task03(print, p);//打印p数组
	task01.detach();//检测按键
	task03.detach();//打印p数组
	while (1)
	{
		printfen();
		Fdown();//下降方块
		Gameover();//检测游戏结束
		clear();//检测清行
		if (over == 1)//检测重启游戏
		{
			dayin();
			chushif();
			GW(7, -4);
			over = 0;
		}
		
		Sleep(Time);//方块下降延迟
	}
}
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值