#include<iostream>
#include<stdio.h>
#include<conio.h>
#include<windows.h>
#include<time.h>
using namespace std;
#define W 10
#define H 20
const int ROWS = H + 2;
const int COLS = W + 2;
const int Btype = 7;
const int BlockColors[Btype] = {
4, 14, 6, 1, 2, 13, 11 };
int mp[ROWS][COLS] = {0};
int x, y, Bid, Bir, NextBid, NextBir;
bool Flag = 0;
int score = 0;
int INTERVAL = 500;
bool paused = 0;
bool Blocks[Btype][4][4][4] = {
{{{0,1,0,0},{1,1,1,0},{0,0,0,0},{0,0,0,0}},{{0,1,0,0},{0,1,1,0},{0,1,0,0},{0,0,0,0}},{{0,0,0,0},{1,1,1,0},{0,1,0,0},{0,0,0,0}},{{0,1,0,0},{1,1,0,0},{0,1,0,0},{0,0,0,0}}},
{{{0,0,0,0},{0,1,1,0},{0,1,1,0},{0,0,0,0}},{{0,0,0,0},{0,1,1,0},{0,1,1,0},{0,0,0,0}},{{0,0,0,0},{0,1,1,0},{0,1,1,0},{0,0,0,0}},{{0,0,0,0},{0,1,1,0},{0,1,1,0},{0,0,0,0}}},
{{{0,1,0,0},{0,1,0,0},{0,1,1,0},{0,0,0,0}},{{0,0,0,0},{1,1,1,0},{1,0,0,0},{0,0,0,0}},{{1,1,0,0},{0,1,0,0},{0,1,0,0},{0,0,0,0}},{{0,0,1,0},{1,1,1,0},{0,0,0,0},{0,0,0,0}}},
{{{0,1,0,0},{0,1,0,0},{0,1,0,0},{0,1,0,0}},{{0,0,0,0},{1,1,1,1},{0,0,0,0},{0,0,0,0}},{{0,1,0,0},{0,1,0,0},{0,1,0,0},{0,1,0,0}},{{0,0,0,0},{1,1,1,1},{0,0,0,0},{0,0,0,0}}},
{{{0,1,0,0},{0,1,1,0},{0,0,1,0},{0,0,0,0}},{{0,0,0,0},{0,1,1,0},{1,1,0,0},{0,0,0,0}},{{0,1,0,0},{0,1,1,0},{0,0,1,0},{0,0,0,0}},{{0,0,0,0},{0,1,1,0},{1,1,0,0},{0,0,0,0}}},
{{{0,0,1,0},{0,1,1,0},{0,1,0,0},{0,0,0,0}},{{0,0,0,0},{1,1,0,0},{0,1,1,0},{0,0,0,0}},{{0,0,1,0},{0,1,1,0},{0,1,0,0},{0,0,0,0}},{{0,0,0,0},{1,1,0,0},{0,1,1,0},{0,0,0,0}}},
{{{0,0,1,0},{0,0,1,0},{0,1,1,0},{0,0,0,0}},{{0,1,0,0},{0,1,1,1},{0,0,0,0},{0,0,0,0}},{{0,1,1,0},{0,1,0,0},{0,1,0,0},{0,0,0,0}},{{0,0,0,0},{1,1,1,0},{0,0,1,0},{0,0,0,0}}}
};
void HideCursor(){
CONSOLE_CURSOR_INFO cursor_info = {1, 0};
SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info);
}
void setPos(int x,int y) {
CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
HANDLE hConsoleOut;
hConsoleOut = GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleScreenBufferInfo(hConsoleOut,&csbiInfo);
csbiInfo.dwCursorPosition.X = x;
csbiInfo.dwCursorPosition.Y = y;
SetConsoleCursorPosition(hConsoleOut,csbiInfo.dwCursorPosition);
}
void cprintf(const char* s, int color){
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(handle, FOREGROUND_INTENSITY | color);
printf(s);
SetConsoleTextAttribute(handle, FOREGROUND_INTENSITY | 7);
}
void tips(){
setPos(W*2+6, 7);
printf("游戏说明:\n");
setPos(W*2+6, 9);
printf("按 WASD 和 ↑ ↓ ← → 操控游戏\n");
setPos(W*2+6, 11);
printf("按↑和W旋转,按AD和← →左右移动,长按S加速下落\n");
setPos(W*2+6, 13);
printf("当前得分:%d\n", score);
}
void init(){
x = W/2-1, y = 1;
Bid = rand()%Btype;
Bir = rand()%4;
NextBid = rand()%Btype;
NextBir = rand()%4;
for(int i=0;i<ROWS;i++){
for(int j=0;j<COLS;j++){
if(i==0 || j==0 || i==ROWS-1 || j==COLS-1) mp[i][j] = 1;
else mp[i][j] = 0;
}
}
}
void draw() {
setPos(0, 0); for (int i = 0; i < ROWS; i++) {
for (int j = 0; j < COLS; j++) {
bool isCurrent = false;
for (int bi = 0; bi < 4 && !isCurrent; bi++) {
for (int bj = 0; bj < 4; bj++) {
if (Blocks[Bid][Bir][bi][bj] && y + bi == i && x + bj == j) {
isCurrent = true;
break;
}
}
}
if (isCurrent) {
cprintf("■", BlockColors[Bid]);
} else if (mp[i][j]) {
if (i == 0 || j == 0 || i == ROWS - 1 || j == COLS - 1)
cprintf("■", 7);
else
cprintf("■", BlockColors[mp[i][j] - 1]);
} else {
printf(" ");
}
}
if (i == 7) {
printf(" 游戏说明:");
} else if (i == 9) {
printf(" WASD / 方向键 控制,Q 暂停");
} else if (i == 11) {
printf(" ↑/W: 旋转,←→/AD: 移动");
} else if (i == 13) {
printf(" 当前得分:%d", score);
} else if (paused && i == 15) {
HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(h, FOREGROUND_RED | FOREGROUND_INTENSITY);
printf(" 游戏已暂停");
SetConsoleTextAttribute(h, FOREGROUND_INTENSITY | 7);
} else if (paused && i == 16) {
HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(h, FOREGROUND_RED | FOREGROUND_INTENSITY);
printf(" 按 Q 继续");
SetConsoleTextAttribute(h, FOREGROUND_INTENSITY | 7);
} else if (i >= 1 && i <= 4) {
printf(" ");
for (int j = 0; j < 4; j++) {
if (Blocks[NextBid][NextBir][i-1][j])
cprintf("■", BlockColors[NextBid]);
else
printf(" ");
}
} else {
printf(" "); }
printf("\n");
}
setPos(0, ROWS + 2);
}
bool IsPlace(int tx, int ty, int tid, int tir){
if(tx<0) return 0;
for(int i=0; i<4; i++){
for(int j=0; j<4; j++){
if(Blocks[tid][tir][i][j]){
if(ty+i<0 || ty+i>=ROWS || tx+j<0 || tx+j>=COLS) return 0;
if(mp[ty+i][tx+j]) return 0;
}
}
}
return 1;
}
void DelLine() {
bool vis[ROWS] = {0}; int cnt = 0;
for (int i = 1; i <= H; i++) {
bool isFull = true;
for (int j = 1; j <= W; j++) {
if (!mp[i][j]) {
isFull = false;
break;
}
}
if (isFull) {
vis[i] = true;
cnt++;
}
}
if (cnt == 0) return;
int L = H;
for (int i = H; i >= 1; i--) {
if (!vis[i]) { if (L != i) {
for (int j = 0; j < COLS; j++) {
mp[L][j] = mp[i][j];
}
}
L--;
}
}
for (int i = 1; i <= L; i++) {
for (int j = 1; j <= W; j++) {
mp[i][j] = false;
}
mp[i][0] = mp[i][COLS-1] = true; }
if(cnt == 1) score += 100;
else if(cnt==2) score += 200;
else if(cnt==3) score += 400;
else score += 800;
INTERVAL = max(150, 500-score/100);
}
void Move(){
if(IsPlace(x, y+1, Bid, Bir)) y++;
else{
for(int i=0; i<4; i++){
for(int j=0; j<4; j++){
if(Blocks[Bid][Bir][i][j]) mp[y+i][x+j] = Bid + 1;
}
}
DelLine();
Flag = 1;
}
}
void Create(){
Bid = NextBid, Bir = NextBir;
NextBid = rand()%Btype, NextBir = rand()%4, x = W/2-1, y = 1;
}
void KeyInput(){
if (GetAsyncKeyState('A') & 0x8000 || GetAsyncKeyState(VK_LEFT) & 0x8000) {
static DWORD lastMoveLeft = 0;
DWORD now = GetTickCount();
if (now - lastMoveLeft > 100) { if (IsPlace(x-1, y, Bid, Bir)) x--;
lastMoveLeft = now;
}
}
if (GetAsyncKeyState('D') & 0x8000 || GetAsyncKeyState(VK_RIGHT) & 0x8000) {
static DWORD lastMoveRight = 0;
DWORD now = GetTickCount();
if (now - lastMoveRight > 100) {
if (IsPlace(x+1, y, Bid, Bir)) x++;
lastMoveRight = now;
}
}
static bool rotated = false;
if (GetAsyncKeyState('W') & 0x8000 || GetAsyncKeyState(VK_UP) & 0x8000) {
if (!rotated) {
if (IsPlace(x, y, Bid, (Bir+1)%4)) Bir = (Bir+1)%4;
rotated = true;
}
}
else rotated = false;
if (GetAsyncKeyState('S') & 0x8000 || GetAsyncKeyState(VK_DOWN) & 0x8000) {
if(IsPlace(x, y+1, Bid, Bir)) y++;
Sleep(10);
}
static bool ispause = false;
if (GetAsyncKeyState('Q') & 0x8000) {
if (!ispause) {
paused = !paused;
ispause = true;
}
}
else ispause = false;
}
int main(){
HideCursor();
srand(time(0));
init();
DWORD LastTime = GetTickCount();
while(1){
KeyInput();
if(!paused){
DWORD NowTime = GetTickCount();
if(NowTime-LastTime >= INTERVAL){
Move();
LastTime = NowTime;
}
if(Flag){
Create();
if(!IsPlace(x, y, Bid, Bir)) break;
Flag = 0;
}
}
draw();
Sleep(50);
}
setPos((W+1)/2,(H-1)/2);
cprintf("游戏结束!", 4);
setPos(0,H+2);
system("pause");
return 0;
}