#include<iostream>
#include<windows.h>
#include<time.h>
#include<conio.h>
using namespace std;
HANDLE handle;
COORD crd;
const short LMARGIN = 7;
const short TMARGIN = 5;
char type[19][17] =
{
"1100011000000000","0010011001000000",
"0110110000000000","0100011000100000",
"0000111100000000","0100010001000100",
"0000011001100000",
"0100111000000000","0100110001000000","1110010000000000","1000110010000000",
"0010111000000000","0110001000100000","1110100000000000","0100010001100000",
"1000111000000000","0010001001100000","1110001000000000","0110010001000000"
};
char rotate_hinder[19][17] =
{
"0010000001100000","1100000000100000",
"0000001011100000","0010100011000000",
"1111000001110111","1011101100110011",
"0000000000000000",
"1010000011000000","1010001000100000","0000100010000000","0100001001100000",
"0100000011100000","1000110000000000","0000010011100000","1010101000000000",
"0110000011100000","1010101000100000","0000110011000000","1000101000100000"
};
short Alter(short n)
{
switch (n)
{
case 1:case 3:case 5:return n - 1; break;
case 6:return 6; break;
case 10:case 14:case 18:return n - 3; break;
default:return n + 1; break;
}
}
void SetPos(short x, short y)
{
crd.X = x; crd.Y = y;
SetConsoleCursorPosition(handle, crd);
}
void SetColor(short front, short back)
{
SetConsoleTextAttribute(handle, front + back * 0x10);
}
short Menu()
{
short choice = 1;
char c;
system("cls");
SetPos(9, 12);
cout << "┌────────────────┐";
SetPos(9, 13);
cout << "│ 俄 罗 斯 方 块 │";
SetPos(9, 14);
cout << "└────────────────┘";
SetPos(7, 21);
cout << "按方向键控制方块";
SetPos(7, 23);
cout << "按空格键暂停/继续";
while (1)
{
SetPos(15, 16);
if (choice == 1)
{
SetColor(2, 7);
}
else
SetColor(2, 0);
cout << " 开始游戏 ";
SetPos(15, 18);
if (choice == 2)
{
SetColor(2, 7);
}
else
SetColor(2, 0);
cout << " 离 开 ";
c = _getch();
if (c == VK_RETURN)
break;
if (c == 72 || c == 80)
choice = choice == 1 ? 2 : 1;
}
SetColor(7, 0);
return choice;
}
void PrintGameOver()
{
SetPos(12, 9);
SetColor(5, 6);
cout << " Game Over! ";
SetColor(7, 0);
}
class Score
{
private:
short ln;
public:
void Reset() { ln = 0; }
void Print()
{
SetPos(4, 1);
SetColor(2, 7);
cout << " Lines: " << ln << " ";
SetColor(7, 0);
}
Score() { Reset(); }
void Update(short n)
{
ln += n;
}
};
class Shape
{
friend class Board;
private:
short present;
short color;
short x;
short y;
public:
Shape(short, short, short);
void Draw(bool, bool);
bool Rotate(Board&);
short Collision(Board&);
bool Move(short direction, Board&brd);
bool Fall(Board& brd);
void DrawElsewhere(short _x, short _y);
};
class Board
{
friend class Shape;
private:
bool wall[22][14];
short bottom_line;
public:
void Clear()
{
for (short i = 0; i < 22; i++)
{
for (short j = 0; j < 14; j++)
if (j > 1 && j < 12 && i < 20)
wall[i][j] = 0;
else
wall[i][j] = 1;
}
}
Board() { Clear(); }
void DrawBoard()
{
short i;
SetColor(0xe, 0xe);
for (i = 0; i < 21; i++)
{
SetPos(LMARGIN - 2, TMARGIN + i - 1);
cout << "口";
}
for (i = 0; i < 21; i++)
{
SetPos(LMARGIN +20, TMARGIN + i - 1);
cout << "口";
}
for (i = 0; i < 10; i++)
{
SetPos(LMARGIN +i*2, TMARGIN + 19);
cout << "口";
}
SetColor(7, 0);
}
short SetBlockValue(Shape& shp)
{
for (short i = 0; i < 16; i++)
{
if (type[shp.present][i] == '1')
{
if (shp.y == 0) return -1;
wall[shp.y + i / 4][shp.x + i % 4] = true;
}
}
return 0;
}
short Drop(Shape& shp)
{
short i, n;
short y, _y = -1;
short j;
short k;
short lines = 0;
short top;
short l;
for (i = 0, n = 0; n < 4 && i < 16; i++)
{
if (type[shp.present][i] == '1')
{
y = shp.y + i / 4;
n++;
if (y == _y)continue;
_y = y;
for (j = 2; j < 12; j++)
if (!wall[y][j])break;
if (j==12)
{
lines++;
for (k = y; k > 0; k--)
{
top = 0;
for (l = 2; l< 12; l++)
{
wall[k][l] = wall[k - 1][l];
top += wall[k - 1][l];
}
if (top == 0)
break;
}
}
}
}
bottom_line = _y;
return lines;
}
void DrawPile()
{
for (short i = 0; i <= bottom_line; i++)
{
for (short j = 2; j < 12; j++)
{
SetPos(LMARGIN - 4 + j * 2, TMARGIN - 1 + i);
if (wall[i][j])
{
SetColor(7, 7);
cout << "口";
}
else
{
SetColor(0, 0);
cout << " ";
}
}
}
}
};
Shape::Shape(short _color, short _x=5, short _y=0) :color(_color), x(_x), y(_y)
{
switch (_color)
{
case 1:present = 0; break;
case 2:present = 2; break;
case 3:present = 4; break;
case 4:present = 6; break;
case 5:present = 7; break;
case 6:present = 11; break;
default:
color = 8; present = 15;
break;
}
}
void Shape::Draw(bool flag = true, bool active = true)
{
if (!flag)
SetColor(0, 0);
else
if (active) SetColor(color, color);
else SetColor(7, 7);
for(short i=0;i<16;i++)
if (type[present][i] == '1')
{
SetPos(LMARGIN-4 + (x + i % 4)*2 , TMARGIN + y + i / 4 - 1);
cout << "口";
}
SetColor(7, 0);
}
bool Shape:: Rotate(Board& brd)
{
for (short i = 0; i < 16; i++)
{
if (brd.wall[y + i / 4][x + i % 4] && rotate_hinder[present][i] == '1')
return false;
}
Draw(false);
present = Alter(present);
Draw();
return true;
}
short Shape::Collision(Board& brd)
{
short result = 0;
for (short i = 0; i < 16; i++)
{
if (type[present][i] == '1')
{
if (brd.wall[y + i / 4][x + i % 4 - 1])
result |= 1;
if (brd.wall[y + i / 4][x + i % 4 + 1])
result |= 2;
if (brd.wall[y + i / 4+1][x + i % 4 ])
result |= 4;
}
}
return result;
}
bool Shape:: Move(short direction, Board&brd)
{
if (direction == 1 && !(Collision(brd) & 1))
{
Draw(false, true);
x--;
Draw();
return true;
}
if (direction == 2 && !(Collision(brd) & 2))
{
Draw(false, true);
x++;
Draw();
return true;
}
return false;
}
bool Shape::Fall(Board& brd)
{
if (Collision(brd) & 4)
{
Draw(true, false);
return false;
}
Draw(false, true);
y++;
Draw();
return true;
}
void Shape::DrawElsewhere(short _x, short _y)
{
short i;
SetPos(_x, _y);
SetColor(7, 0);
cout << "next: ";
_x += 6;
SetColor(0, 0);
for (i = 0; i < 12; i++)
{
SetPos(_x + i % 4 * 2, _y + i / 4);
cout << " ";
}
SetColor(color, color);
_y -= (present == 6 || present == 4);
for (i = 0; i < 12; i++)
{
if (type[present][i] == '1')
{
SetPos(_x + i % 4 * 2, _y + i / 4);
cout << "口";
}
}
}
int main()
{
system("mode con cols=35 lines=27");
handle = GetStdHandle(STD_OUTPUT_HANDLE);
Board board;
short tmp;
Shape* shp, * shp_next;
short times;
srand(time(0));
char ch;
Score score;
while (Menu()==1)
{
system("cls");
board.Clear();
board.DrawBoard();
score.Reset();
score.Print();
shp_next= new Shape(rand() % 7 + 1);
while (true)
{
shp = shp_next;
shp_next = new Shape(rand() % 7 + 1);
shp_next->DrawElsewhere(17, 1);
times = 0;
while (1)
{
shp->Draw();
if (GetAsyncKeyState(VK_LEFT) == -32767)
shp->Move(1, board);
if (GetAsyncKeyState(VK_RIGHT) == -32767)
shp->Move(2, board);
if (GetAsyncKeyState(VK_UP) == -32767)
shp->Rotate(board);
if (GetAsyncKeyState(VK_DOWN) == -32767)
shp->Fall(board);
if (GetAsyncKeyState(VK_SPACE)==-32767)
{
while (!(GetAsyncKeyState(VK_SPACE) == -32767))
Sleep(25);
}
Sleep(25);
times++;
if (times == 10)
{
times = 0;
if (!shp->Fall(board))
break;
}
}
if (board.SetBlockValue(*shp) == -1)
{
PrintGameOver();
while ((ch = _getch()) != VK_RETURN && ch != EOF);
delete shp_next;
break;
}
if (tmp = board.Drop(*shp))
{
board.DrawPile();
score.Update(tmp);
score.Print();
}
delete shp;
}
}
return 0;
}