#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];
					}
				}
			}
			
		}

	}
}

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

void fk(int y, int x)
{
   
	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)
{
   
	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)
{
   
	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;
					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;
					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;
					FIY[i] = -1;
				}
			}
		}
		return 1;
	}
	else {
    return 0; }
}
void chushif()
{
   
	if (Gdata == 0)
	{
   
		int xun;
		xun = (rand() % 8) + 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);
				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); 
				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); 
				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 (_getch())
		{
   
			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];
		}
		
	}



}
int main()
{
   
	srand((unsigned)time(NULL));
	clg();
	dayin();
	chushif();
	GW(7, -4);
	thread task01(anjian);
	thread task03(print, p);
	task01.detach();
	task03.detach();
	while (1)
	{
   
		printfen();
		Fdown();
		Gameover();
		clear();
		if (over == 1)
		{
   
			dayin();
			chushif();
			GW(7, -4);
			over = 0;
		}

		Sleep(Time);
	}
}

运行结果如下: