#include<iostream>
#include<conio.h>//头文件,包含_kbhit、_getch
#include<Windows.h>
#include"games.h"
using namespace std;
const int sq[7][4][4] =//规定可能出现方块的形状
{
{
{ 0, 1, 0, 0 },
{ 0, 1, 0, 0 },
{ 0, 1, 0, 0 },
{ 0, 1, 0, 0 }
},
{
{ 0, 1, 0, 0 },
{ 0, 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, 0, 0, 0 },
{ 0, 1, 1, 0 },
{ 0, 1, 1, 0 },
{ 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, 1, 0, 0 },
{ 0, 1, 1, 0 },
{ 0, 1, 0, 0 }
},
{
{ 0, 0, 0, 0 },
{ 0, 0, 1, 0 },
{ 0, 1, 1, 0 },
{ 0, 1, 0, 0 }
}
};
bool Spin(int a[][24], int lox, int loy)//旋转方块,参数为二维数组,和方块所在位置的坐标
{
if (lox < 0 || lox>6)return false;//靠边的方块不能旋转,直接退出函数
if (loy > 20)return false;
int copya[4][4];//定义一个二维数组,把坐标位置的情况进行翻转变换,并赋值进去
for (int i2 = 0; i2 < 4; i2++)
{
for (int i1 = 0; i1 < 4; i1++)
{
if (a[lox + i1][loy + i2] == 1)
{
copya[3 - i2][i1] = a[lox + i1][loy + i2];
}
else
{
copya[3 - i2][i1] = 0;
}
}
}
for (int i2 = 0; i2 < 4; i2++)//对copya数组进行检测,假如如此旋转会覆盖其他方块,则无法旋转,退出函数
{
for (int i1 = 0; i1 < 4; i1++)
{
if (copya[i1][i2] == 1 && a[lox + i1][loy + i2] == 2)
{
return 0;
}
}
}
for (int i2 = 0; i2 < 4; i2++)//赋值
{
for (int i1 = 0; i1 < 4; i1++)
{
if (a[lox + i1][loy + i2] != 2)
{
a[lox + i1][loy + i2] = copya[i1][i2];
}
}
}
return true;
}
void MakeNew(int a[][24])//生成新的方块
{
int l = random(0, 10);
if (l == 7||l==8)l = 0;
else if (l == 9)l = 3;
int f = random(0, 4);
for (int i2 = 0; i2 < 4; i2++)//随机生成一个方块,旋转随机次数,将其放置在二维数组中不显示的最上方位置
{
for (int i1 = 3; i1 <= 6; i1++)
{
a[i1][i2] = sq[l][i1 - 3][i2];
}
}
for (int i = 0; i <= f; i++)
{
Spin(a, 3, 0);//旋转随机次数
}
return;
}
void Gamescreen(int a[][24], int sc)//输出屏幕
{
system("cls");
cout << " ____________________ \n";
for (int i2 = 4; i2 < 24; i2++)
{
cout << "|";
for (int i1 = 0; i1 < 10; i1++)
{
if (a[i1][i2] == 0)//空白区域
cout << " ";
else if (a[i1][i2] == 1)//漂浮方块
cout << "□";
else if (a[i1][i2] == 2)//落地方块
{
cout << "■";
}
}
cout << "|" << endl;
}
cout << "|--------------------|\n";
cout << " 分数:" << sc << endl;
return;
}
bool Candown(int a[][24])//检测方块是否可以继续下落
{
for (int i2 = 23; i2 >= 0; i2--)
{
for (int i1 = 9; i1 >= 0; i1--)
{
if (a[i1][i2] == 1 && (a[i1][i2 + 1] == 2 || i2 + 1 == 24))
{
return false;
}
}
}
return true;
}
bool Canleft(int a[][24])//检测方块是否可以左移
{
for (int i1 = 0; i1 < 10; i1++)
{
for (int i2 = 0; i2 < 24; i2++)
{
if (a[i1][i2] == 1 && (a[i1 - 1][i2] == 2 || i1 - 1 < 0))
{
return false;
}
}
}
return true;
}
bool Canright(int a[][24])//检测方块是否可以右移
{
for (int i1 = 9; i1 >= 0; i1--)
{
for (int i2 = 0; i2 < 24; i2++)
{
if (a[i1][i2] == 1 && (a[i1 + 1][i2] == 2 || i1 + 1 > 9))
{
return false;
}
}
}
return true;
}
int Clearline(int a[][24])//清除所有满方块行,并下落
{
int line = 0;
for (int i2 = 23; i2 >= 0; i2--)
{
bool isn2 = true;
for (int i1 = 0; i1 < 10; i1++)
{
if (a[i1][i2] != 2)
{
isn2 = false;
break;
}
}
if (isn2)
{
line++;
for (int i1 = 0; i1 < 10; i1++)
{
a[i1][i2] = 0;
}
}
}
int copyline = 23;
for (int i2 = 23; i2 >= 0; i2--)
{
bool isn0 = true;
for (int i1 = 0; i1 < 10; i1++)
{
if (a[i1][i2] != 0)
{
isn0 = false;
break;
}
}
if (!isn0)
{
int ls[10];
for (int i1 = 0; i1 < 10; i1++)
{
ls[i1] = a[i1][i2];
a[i1][i2] = 0;
a[i1][copyline] = ls[i1];
}
copyline--;
}
}
return line;
}
bool ende(int a[][24])//检测是否达到游戏结束条件
{
for (int i = 0; i < 10; i++)
{
if (a[i][4] == 2)
return true;
}
return false;
}
int main()
{
for (;;)
{
int select = 1;
bool re;
for (;;)
{
system("cls");
cout << " ___________________\n";
cout << "| C++俄罗斯方块 |\n";
cout << "| V1.3 |\n";
cout << "|W:上S:下 ENTER:确认|\n";
cout << "| " << ((select == 1) ? "●" : "○") << " 开始游戏 |\n";
cout << "| " << ((select == 2) ? "●" : "○") << " 游戏规则 |\n";
cout << "| " << ((select == 3) ? "●" : "○") << " 操作说明 |\n";
cout << "| " << ((select == 4) ? "●" : "○") << " 关于 |\n";
cout << "|___________________|\n";
cout << " 请先关闭中文输入法\n";
cout << " Made By ECNU 15-匡 \n";
cout << "V1.3更新:修复了旋转时会擦除周围方块的BUG。\n";
char an = _getch();
if (an == 'w' || an == 'W')
{
select--;
}
else if (an == 's' || an == 'S')
{
select++;
}
else if (an == '\r')
{
if (select == 1)
{
re = false;
break;
}
else if (select == 2)
{
system("cls");
cout << "由小方块组成的不同形状\n";
cout << "的板块陆续从屏幕上方落\n";
cout << "下来,玩家通过调整板块\n";
cout << "的位置和方向,使它们在\n";
cout << "屏幕底部拼出完整的一条\n";
cout << "或几条。这些完整的横条\n";
cout << "会随即消失,给新落下来\n";
cout << "的板块腾出空间,与此同\n";
cout << "时,玩家得到分数奖励。\n";
cout << "没有被消除掉的方块不断\n";
cout << "堆积起来,一旦堆到屏幕\n";
cout << "顶端,玩家便告输,游戏\n";
cout << "结束。\n";
system("pause");
}
else if (select == 3)
{
system("cls");
cout << "\nA:左移 D:右移\n\n";
cout << "W:旋转 S:立即下落\n\n";
cout << "SPACE:暂停 R:返回\n\n";
system("pause");
}
else if (select == 4)
{
system("cls");
cout << "C++俄罗斯方块 V1.0\n";
cout << "Made by ECNU 15级软工C班\n匡申升 \n";
cout << "QQ:472563655\n微博: @理科全才匡申升 \n";
cout << "本程序仅供交流学习使用\n";
system("pause");
}
}
if (select == 0)select = 4;
if (select == 5)select = 1;
}
srands();//重置随机数
for (;;)
{
int score = 0, time = 500;
int gm[10][24];
for (int i2 = 0; i2 < 24; i2++)
{
for (int i1 = 0; i1 < 10; i1++)
gm[i1][i2] = 0;
}
for (;;)
{
Gamescreen(gm, score);
MakeNew(gm);
int sqx = 3, sqy = 0;
int leftml = 0, rightml = 0, spinml = 0;
for (;;)
{
char an;
Sleep(time);
int hittime = 0;
for (;;)
{
if (_kbhit())
{
hittime++;
an = _getch();
}
if (an == 'W' || an == 'w')
{
if (Spin(gm, sqx, sqy))
{
Sleep(int(time / 4));
Gamescreen(gm, score);
}
}
else if (an == 'A' || an == 'a')
{
if (Canleft(gm))
{
for (int i1 = 0; i1 < 10; i1++)
{
for (int i2 = 0; i2 < 24; i2++)
{
if (gm[i1][i2] == 1)
{
swap(gm[i1][i2], gm[i1 - 1][i2]);
}
}
}
Gamescreen(gm, score);
Sleep(int(time / 4));
sqx--;
}
}
else if (an == 'D' || an == 'd')
{
if (Canright(gm))
{
for (int i1 = 9; i1 >= 0; i1--)
{
for (int i2 = 0; i2 < 24; i2++)
{
if (gm[i1][i2] == 1)
{
swap(gm[i1][i2], gm[i1 + 1][i2]);
}
}
}
sqx++;
Gamescreen(gm, score);
Sleep(int(time / 4));
}
//右移
}
else if (an == 'S' || an