C++实现俄罗斯方块
写在卸载之前
一个蒟蒻无力的挣扎
如果你是在阅读本人的博文来实现俄罗斯方块
在实现俄罗斯方块之前 本人建议先左转贪吃蛇
正式开始
本来还是想秉持拿来主义 像贪吃蛇一样从网上随随便便找一个拿来写写
但是由于网上的俄罗斯方块 实在是要么看不懂要么运行不了这话好像已经说过了
所以没有办法 只好自己手写一个轻描淡写的一句话 背后是逝去的头发
同时由于我所使用的是exe显示 所以为了舒适看着顺眼 最好手动调节一下显示exe的比例和字体大小
大致写出来就是这样
这里添加了黑暗模式也就是盲打俄罗斯方块 如果有想玩但是网上找不到的朋友可以试试
并且理解代码之后 你发现你甚至可以通过修改参数来在开头生成残块
俄罗斯方块的写法跟贪吃蛇硬件类似 软件不同
这里的我有很多都用到了贪吃蛇里面的代码 例如Windows API
1.初始化游戏设置
跟贪吃蛇类似
class GameSetting
{
public:
static const int window_height=22;
static const int window_width=28;
public:
static void GameInit()
{//调节屏幕尺寸
char buffer[32];
sprintf(buffer,"mode con cols=%d lines=%d",window_width,window_height);
system(buffer);
//隐藏光标
HANDLE handle=GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_CURSOR_INFO cursor;
GetConsoleCursorInfo(handle,&cursor);
cursor.bVisible=false;
SetConsoleCursorInfo(handle,&cursor);
//随机种子
srand((unsigned int)time((int)(998244353==19260817)));
}
static void GameStart()
{//开始游戏界面
system("cls");
for(int i=1;i<=window_width;++i) putchar('#');
putchar('\n');
for(int i=2;i<window_height;++i)
{
for(int j=1;j<=window_width;++j)
if(j==1||j==window_width) putchar('#');
else putchar(' ');
putchar('\n');
}
for(int i=1;i<=window_width;++i) putchar('#');
gotoxy(7,9);printf("俄罗斯方块");
gotoxy(7,11);printf("方向键控制");
gotoxy(7,13);printf("请选择模式:");
gotoxy(4,15);printf("↑:正常 ↓:黑暗");
}
static void GameOver(int score)
{//游戏结束界面
for(int i=3;i<=17;++i)
for(int j=7;j<=13;++j)
gotoxy(i,j),putchar(' ');
gotoxy(7,9);printf("游戏结束!");
gotoxy(5,11);printf("当前分数为:%03d",score);
}
};
2.打印相关的游戏信息
/*
1
****
2
**
**
3
*
***
4
*
***
5
*
***
6
**
**
7
**
**
*/
class PrintInfo
{
public:
static void DrawMap()
{//打印初始版面
system("cls");
for(int i=1;i<=GameSetting::window_width;++i) putchar('#');
putchar('\n');
for(int i=2;i<GameSetting::window_height;++i)
{
for(int j=1;j<=GameSetting::window_width;++j)
if(i==11&&j>=12) putchar('#');
else if(j==1||j==GameSetting::window_width||j==12) putchar('#');
else putchar(' ');
putchar('\n');
}
for(int i=1;i<=GameSetting::window_width;++i) putchar('#');
for(int i=1;i<=20;++i) {gotoxy(i,21);nowhave[i][21]=1;}
}
static void DrawNext(int knd)
{//俄罗斯方块需要有下一个的提示 所以我们需要在右上角显示下一个方块的信息
gotoxy(13,2);printf("Next:");
switch(knd)
{//具体为什么会这么打印 跟上面的对应吧
case 1:
gotoxy(14+2,3+2);putchar('*');
gotoxy(15+2,3+2);putchar('*');
gotoxy(16+2,3+2);putchar('*');
gotoxy(17+2,3+2);putchar('*');
break;
case 2:
gotoxy(14+2,3+2);putchar('*');
gotoxy(15+2,3+2);putchar('*');
gotoxy(14+2,4+2);putchar('*');
gotoxy(15+2,4+2);putchar('*');
break;
case 3:
gotoxy(15+2,3+2);putchar('*');
gotoxy(14+2,4+2);putchar('*');
gotoxy(15+2,4+2);putchar('*');
gotoxy(16+2,4+2);putchar('*');
break;
case 4:
gotoxy(14+2,3+2);putchar('*');
gotoxy(14+2,4+2);putchar('*');
gotoxy(15+2,4+2);putchar('*');
gotoxy(16+2,4+2);putchar('*');
break;
case 5:
gotoxy(16+2,3+2);putchar('*');
gotoxy(14+2,4+2);putchar('*');
gotoxy(15+2,4+2);putchar('*');
gotoxy(16+2,4+2);putchar('*');
break;
case 6:
gotoxy(14+2,3+2);putchar('*');
gotoxy(15+2,3+2);putchar('*');
gotoxy(15+2,4+2);putchar('*');
gotoxy(16+2,4+2);putchar('*');
break;
case 7:
gotoxy(15+2,3+2);putchar('*');
gotoxy(16+2,3+2);putchar('*');
gotoxy(14+2,4+2);putchar('*');
gotoxy(15+2,4+2);putchar('*');
break;
}
}
static void ClearNext()
{//每一次打印完之后为了防止覆盖下一个 我们需要清理
gotoxy(14+2,3+2);putchar(' ');
gotoxy(15+2,3+2);putchar(' ');
gotoxy(16+2,3+2);putchar(' ');
gotoxy(17+2,3+2);putchar(' ');
gotoxy(14+2,4+2);putchar(' ');
gotoxy(15+2,4+2);putchar(' ');
gotoxy(16+2,4+2);putchar(' ');
}
static void DrawScore(int hard,int line,int score)
{//显示当前游戏信息
gotoxy(13,13);printf("游戏等级:%02d\n",hard);
gotoxy(13,15);printf("消灭行数:%03d\n",line);
gotoxy(13,17);printf("玩家分数:%03d\n",score);
gotoxy(13,19);printf("作者:破晓晨光");
}
static void DrawNowHave()
{//打印下方已经存在还没有消去的块
for(int i=1;i<=20;++i)
for(int j=1;j<=10;++j)
{
gotoxy(j,i);
putchar(nowhave[j][i] ? '*':' ');
}
}
};
3.关于方块
class Square
{
private:
vector<Node> NowL,tmp;//存储当前下降方块的坐标 以及用于临时存储的vector
int NowKnd,nowdir;//当前方框的种类和朝向
int NextKnd;//下一个方块的种类
public:
Square()
{//初始构造函数
NowKnd=rand()%7+1;nowdir=0;
NextKnd=rand()%7+1;
NowL.clear();
switch(NowKnd)
{//初始的方块所在显示屏幕的位置
case 1:
NowL.push_back((Node){4,0});
NowL.push_back((Node){5,0});
NowL.push_back((Node){6,0});
NowL.push_back((Node){7,0});
break;
case 2:
NowL.push_back((Node){5,-1});
NowL.push_back((Node){6,-1});
NowL.push_back((Node){5,0});
NowL.push_back((Node){6,0});
break;
case 3:
NowL.push_back((Node){6,-1});
NowL.push_back((Node){5,0});
NowL.push_back((Node){6,0});
NowL.push_back((Node){7,0});
break;
case 4:
NowL.push_back((Node){5,-1});
NowL.push_back((Node){5,0});
NowL.push_back((Node){6,0});
NowL.push_back((Node){7,0});
break;
case 5:
NowL.push_back((Node){7,-1});
NowL.push_back((Node){5,0});
NowL.push_back((Node){6,0});
NowL.push_back((Node){7,0});
break;
case 6:
NowL.push_back((Node){4,-1});
NowL.push_back((Node){5,-1});
NowL.push_back((Node){5,0});
NowL.push_back((Node){6,0});
break;
case 7:
NowL.push_back((Node){5,-1});
NowL.push_back((Node){6,-1});
NowL.push_back((Node){4,0});
NowL.push_back((Node){5,0});
break;
}
}
void getNew()
{//获取新的下降方块 其种类就是当前的下一个的种类
NowKnd=NextKnd;nowdir=0;NowL.clear();
NextKnd=rand()%7+1;
switch(NowKnd)
{
case 1:
NowL.push_back((Node){4,0});
NowL.push_back((Node){5,0});
NowL.push_back((Node){6,0});
NowL.push_back((Node){7,0});
break;
case 2:
NowL.push_back((Node){5,-1});
NowL.push_back((Node){6,-1});
NowL.push_back((Node){5,0});
NowL.push_back((Node){6,0});
break;
case 3:
NowL.push_back((Node){6,-1});
NowL.push_back((Node){5,0});
NowL.push_back((Node){6,0});
NowL.push_back((Node){7,0});
break;
case 4:
NowL.push_back((Node){5,-1});
NowL.push_back((Node){5,0});
NowL.push_back((Node){6,0});
NowL.push_back((Node){7,0});
break;
case 5:
NowL.push_back((Node){7,-1});
NowL.push_back((Node){5,0});
NowL.push_back((Node){6,0});
NowL.push_back((Node){7,0});
break;
case 6:
NowL.push_back((Node){4,-1});
NowL.push_back((Node){5,-1});
NowL.push_back((Node){5,0});
NowL.push_back((Node){6,0});
break;
case 7:
NowL.push_back((Node){5,-1});
NowL.push_back((Node){6,-1});
NowL.push_back((Node){4,0});
NowL.push_back((Node){5,0});
break;
}
}
void listen_keyboard()
{//监听键盘
char ch;
if(_kbhit())
{
ch=_getch();
ch=_getch();//72向上 80向下 75向左 77向右
int maxn=-1,minn=35;
bool okay=1;
for(int i=0;i<4;++i)
{//我们分别判断左移 右移 加速下降是否合法
minn=min(minn,NowL[i].xx),maxn=max(maxn,NowL[i].xx);
for(int j=1;j<=3;++j)
if(NowL[i].yy+j>20||nowhave[NowL[i].xx][NowL[i].yy+j]) okay=0;
}
if(ch==75&&minn>1)
{
for(int i=0;i<4;++i) NowL[i].xx--;
}
if(ch==77&&maxn<10)
{
for(int i=0;i<4;++i) NowL[i].xx++;
}
if(ch==80&&okay)
{
for(int i=0;i<4;++i) NowL[i].yy+=3;
}
if(ch==72)
{//最复杂的旋转操作 建议看代码的同时自己手动模拟 以便理解
tmp.clear();
switch(NowKnd)
{
case 1:
if(nowdir==0)
{
int nowx=NowL[1].xx,nowy=NowL[1].yy;
bool flag=1;
tmp.push_back((Node){nowx,nowy-1});
tmp.push_back((Node){nowx,nowy});
tmp.push_back((Node){nowx,nowy+1});
tmp.push_back((Node){nowx,nowy+2});
for(int i=0;i<4;++i) if(tmp[i].xx<1||tmp[i].xx>10||tmp[i].yy<1||tmp[i].yy>20||nowhave[tmp[i].xx][tmp[i].yy]) {flag=0;break;}
if(flag)
{
NowL.clear();
for(int i=0;i<4;++i) NowL.push_back((Node){tmp[i].xx,tmp[i].yy});
}
}
else
{
int nowx=NowL[1].xx,nowy=NowL[1].yy;
bool flag=1;
tmp.push_back((Node){nowx-1,nowy});
tmp.push_back((Node){nowx,nowy});
tmp.push_back((Node){nowx+1,nowy});
tmp.push_back((Node){nowx+2,nowy});
for(int i=0;i<4;++i) if(tmp[i].xx<1||tmp[i].xx>10||tmp[i].yy<1||tmp[i].yy>20||nowhave[tmp[i].xx][tmp[i].yy]) {flag=0;break;}
if(flag)
{
NowL.clear();
for(int i=0;i<4;++i) NowL.push_back((Node){tmp[i].xx,tmp[i].yy});
}
}
nowdir=(nowdir+1)%2;
break;
case 2:
break;
case 3:
if(nowdir==0)
{
int nowx=NowL[2].xx,nowy=NowL[2].yy;
bool flag=1;
tmp.push_back((Node){nowx,nowy-1});
tmp.push_back((Node){nowx+1,nowy});
tmp.push_back((Node){nowx,nowy});
tmp.push_back((Node){nowx,nowy+1});
for(int i=0;i<4;++i) if(tmp[i].xx<1||tmp[i].xx>10||tmp[i].yy<1||tmp[i].yy>20||nowhave[tmp[i].xx][tmp[i].yy]) {flag=0;break;}
if(flag)
{
NowL.clear();
for(int i=0;i<4;++i) NowL.push_back((Node){tmp[i].xx,tmp[i].yy});
}
}
else if(nowdir==1)
{
int nowx=NowL[2].xx,nowy=NowL[2].yy;
bool flag=1;
tmp.push_back((Node){nowx+1,nowy});
tmp.push_back((Node){nowx-1,nowy});
tmp.push_back((Node){nowx,nowy});
tmp.push_back((Node){nowx,nowy+1});
for(int i=0;i<4;++i) if(tmp[i].xx<1||tmp[i].xx>10||tmp[i].yy<1||tmp[i].yy>20||nowhave[tmp[i].xx][tmp[i].yy]) {flag=0;break;}
if(flag)
{
NowL.clear();
for(int i=0;i<4;++i) NowL.push_back((Node){tmp[i].xx,tmp[i].yy});
}
}
else if(nowdir==2)
{
int nowx=NowL[2].xx,nowy=NowL[2].yy;
bool flag=1;
tmp.push_back((Node){nowx,nowy-1});
tmp.push_back((Node){nowx-1,nowy});
tmp.push_back((Node){nowx,nowy});
tmp.push_back((Node){nowx,nowy+1});
for(int i=0;i<4;++i) if(tmp[i].xx<1||tmp[i].xx>10||tmp[i].yy<1||tmp[i].yy>20||nowhave[tmp[i].xx][tmp[i].yy]) {flag=0;break;}
if(flag)
{
NowL.clear();
for(int i=0;i<4;++i) NowL.push_back((Node){tmp[i].xx,tmp[i].yy});
}
}
else if(nowdir==3)
{
int nowx=NowL[2].xx,nowy=NowL[2].yy;
bool flag=1;
tmp.push_back((Node){nowx+1,nowy});
tmp.push_back((Node){nowx-1,nowy});
tmp.push_back((Node){nowx,nowy});
tmp.push_back((Node){nowx,nowy-1});
for(int i=0;i<4;++i) if(tmp[i].xx<1||tmp[i].xx>10||tmp[i].yy<1||tmp[i].yy>20||nowhave[tmp[i].xx][tmp[i].yy]) {flag=0;break;}
if(flag)
{
NowL.clear();
for(int i=0;i<4;++i) NowL.push_back((Node){tmp[i].xx,tmp[i].yy});
}
}
nowdir=(nowdir+1)%4;
break;
case 4:
if(nowdir==0)
{
int nowx=NowL[1].xx,nowy=NowL[1].yy;
bool flag=1;
tmp.push_back((Node){nowx+1,nowy});
tmp.push_back((Node){nowx,nowy});
tmp.push_back((Node){nowx,nowy+1});
tmp.push_back((Node){nowx,nowy+2});
for(int i=0;i<4;++i) if(tmp[i].xx<1||tmp[i].xx>10||tmp[i].yy<1||tmp[i].yy>20||nowhave[tmp[i].xx][tmp[i].yy]) {flag=0;break;}
if(flag)
{
NowL.clear();
for(int i=0;i<4;++i) NowL.push_back((Node){tmp[i].xx,tmp[i].yy});
}
}
else if(nowdir==1)
{
int nowx=NowL[1].xx,nowy=NowL[1].yy;
bool flag=1;
tmp.push_back((Node){nowx,nowy+1});
tmp.push_back((Node){nowx,nowy});
tmp.push_back((Node){nowx-1,nowy});
tmp.push_back((Node){nowx-2,nowy});
for(int i=0;i<4;++i) if(tmp[i].xx<1||tmp[i].xx>10||tmp[i].yy<1||tmp[i].yy>20||nowhave[tmp[i].xx][tmp[i].yy]) {flag=0;break;}
if(flag)
{
NowL.clear();
for(int i=0;i<4;++i) NowL.push_back((Node){tmp[i].xx,tmp[i].yy});
}
}
else if(nowdir==2)
{
int nowx=NowL[1].xx,nowy=NowL[1].yy;
bool flag=1;
tmp.push_back((Node){nowx-1,nowy});
tmp.push_back((Node){nowx,nowy});
tmp.push_back((Node){nowx,nowy-1});
tmp.push_back((Node){nowx,nowy-2});
for(int i=0;i<4;++i) if(tmp[i].xx<1||tmp[i].xx>10||tmp[i].yy<1||tmp[i].yy>20||nowhave[tmp[i].xx][tmp[i].yy]) {flag=0;break;}
if(flag)
{
NowL.clear();
for(int i=0;i<4;++i) NowL.push_back((Node){tmp[i].xx,tmp[i].yy});
}
}
else if(nowdir==3)
{
int nowx=NowL[1].xx,nowy=NowL[1].yy;
bool flag=1;
tmp.push_back((Node){nowx,nowy-1});
tmp.push_back((Node){nowx,nowy});
tmp.push_back((Node){nowx+1,nowy});
tmp.push_back((Node){nowx+2,nowy});
for(int i=0;i<4;++i) if(tmp[i].xx<1||tmp[i].xx>10||tmp[i].yy<1||tmp[i].yy>20||nowhave[tmp[i].xx][tmp[i].yy]) {flag=0;break;}
if(flag)
{
NowL.clear();
for(int i=0;i<4;++i) NowL.push_back((Node){tmp[i].xx,tmp[i].yy});
}
}
nowdir=(nowdir+1)%4;
break;
case 5:
if(nowdir==0)
{
int nowx=NowL[1].xx,nowy=NowL[1].yy;
bool flag=1;
tmp.push_back((Node){nowx+1,nowy});
tmp.push_back((Node){nowx,nowy});
tmp.push_back((Node){nowx,nowy-1});
tmp.push_back((Node){nowx,nowy-2});
for(int i=0;i<4;++i) if(tmp[i].xx<1||tmp[i].xx>10||tmp[i].yy<1||tmp[i].yy>20||nowhave[tmp[i].xx][tmp[i].yy]) {flag=0;break;}
if(flag)
{
NowL.clear();
for(int i=0;i<4;++i) NowL.push_back((Node){tmp[i].xx,tmp[i].yy});
}
}
else if(nowdir==1)
{
int nowx=NowL[1].xx,nowy=NowL[1].yy;
bool flag=1;
tmp.push_back((Node){nowx,nowy+1});
tmp.push_back((Node){nowx,nowy});
tmp.push_back((Node){nowx+1,nowy});
tmp.push_back((Node){nowx+2,nowy});
for(int i=0;i<4;++i) if(tmp[i].xx<1||tmp[i].xx>10||tmp[i].yy<1||tmp[i].yy>20||nowhave[tmp[i].xx][tmp[i].yy]) {flag=0;break;}
if(flag)
{
NowL.clear();
for(int i=0;i<4;++i) NowL.push_back((Node){tmp[i].xx,tmp[i].yy});
}
}
else if(nowdir==2)
{
int nowx=NowL[1].xx,nowy=NowL[1].yy;
bool flag=1;
tmp.push_back((Node){nowx-1,nowy});
tmp.push_back((Node){nowx,nowy});
tmp.push_back((Node){nowx,nowy+1});
tmp.push_back((Node){nowx,nowy+2});
for(int i=0;i<4;++i) if(tmp[i].xx<1||tmp[i].xx>10||tmp[i].yy<1||tmp[i].yy>20||nowhave[tmp[i].xx][tmp[i].yy]) {flag=0;break;}
if(flag)
{
NowL.clear();
for(int i=0;i<4;++i) NowL.push_back((Node){tmp[i].xx,tmp[i].yy});
}
}
else if(nowdir==3)
{
int nowx=NowL[1].xx,nowy=NowL[1].yy;
bool flag=1;
tmp.push_back((Node){nowx,nowy-1});
tmp.push_back((Node){nowx,nowy});
tmp.push_back((Node){nowx-1,nowy});
tmp.push_back((Node){nowx-2,nowy});
for(int i=0;i<4;++i) if(tmp[i].xx<1||tmp[i].xx>10||tmp[i].yy<1||tmp[i].yy>20||nowhave[tmp[i].xx][tmp[i].yy]) {flag=0;break;}
if(flag)
{
NowL.clear();
for(int i=0;i<4;++i) NowL.push_back((Node){tmp[i].xx,tmp[i].yy});
}
}
nowdir=(nowdir+1)%4;
break;
case 6:
if(nowdir==0)
{
int nowx=NowL[1].xx,nowy=NowL[1].yy;
bool flag=1;
tmp.push_back((Node){nowx,nowy-1});
tmp.push_back((Node){nowx,nowy});
tmp.push_back((Node){nowx-1,nowy});
tmp.push_back((Node){nowx-1,nowy+1});
for(int i=0;i<4;++i) if(tmp[i].xx<1||tmp[i].xx>10||tmp[i].yy<1||tmp[i].yy>20||nowhave[tmp[i].xx][tmp[i].yy]) {flag=0;break;}
if(flag)
{
NowL.clear();
for(int i=0;i<4;++i) NowL.push_back((Node){tmp[i].xx,tmp[i].yy});
}
}
else
{
int nowx=NowL[1].xx,nowy=NowL[1].yy;
bool flag=1;
tmp.push_back((Node){nowx-1,nowy});
tmp.push_back((Node){nowx,nowy});
tmp.push_back((Node){nowx,nowy+1});
tmp.push_back((Node){nowx+1,nowy+1});
for(int i=0;i<4;++i) if(tmp[i].xx<1||tmp[i].xx>10||tmp[i].yy<1||tmp[i].yy>20||nowhave[tmp[i].xx][tmp[i].yy]) {flag=0;break;}
if(flag)
{
NowL.clear();
for(int i=0;i<4;++i) NowL.push_back((Node){tmp[i].xx,tmp[i].yy});
}
}
nowdir=(nowdir+1)%2;
break;
case 7:
if(nowdir==0)
{
int nowx=NowL[0].xx,nowy=NowL[0].yy;
bool flag=1;
tmp.push_back((Node){nowx,nowy});
tmp.push_back((Node){nowx,nowy+1});
tmp.push_back((Node){nowx-1,nowy});
tmp.push_back((Node){nowx-1,nowy-1});
for(int i=0;i<4;++i) if(tmp[i].xx<1||tmp[i].xx>10||tmp[i].yy<1||tmp[i].yy>20||nowhave[tmp[i].xx][tmp[i].yy]) {flag=0;break;}
if(flag)
{
NowL.clear();
for(int i=0;i<4;++i) NowL.push_back((Node){tmp[i].xx,tmp[i].yy});
}
}
else
{
int nowx=NowL[0].xx,nowy=NowL[0].yy;
bool flag=1;
tmp.push_back((Node){nowx,nowy});
tmp.push_back((Node){nowx+1,nowy});
tmp.push_back((Node){nowx-1,nowy+1});
tmp.push_back((Node){nowx,nowy+1});
for(int i=0;i<4;++i) if(tmp[i].xx<1||tmp[i].xx>10||tmp[i].yy<1||tmp[i].yy>20||nowhave[tmp[i].xx][tmp[i].yy]) {flag=0;break;}
if(flag)
{
NowL.clear();
for(int i=0;i<4;++i) NowL.push_back((Node){tmp[i].xx,tmp[i].yy});
}
}
nowdir=(nowdir+1)%2;
break;
}
}
}
}
int getNext(){return NextKnd;}//获取下一个方块的种类
bool CanMove()
{//判断当前下降方块是否可以下降
for(int i=0;i<4;++i)
{
int nowx=NowL[i].xx,nowy=NowL[i].yy;
if(nowhave[nowx][nowy+1]||nowy+1>20) return 0;
}
return 1;
}
void Move()
{//向下移动
listen_keyboard();
if(CanMove())
for(int i=0;i<4;++i) ++NowL[i].yy;
}
void MapChange()
{//更新下方存在没有消去的方块
for(int i=0;i<4;++i) nowhave[NowL[i].xx][NowL[i].yy]=1;
}
void Draw()
{//打印下方存在没有消去的方块
for(int i=0;i<4;++i)
{
if(NowL[i].xx>=1&&NowL[i].xx<=10&&NowL[i].yy>=1&&NowL[i].yy<=20)
{
gotoxy(NowL[i].xx,NowL[i].yy);putchar('*');
}
}
}
void print()
{//打印下降方块的二维坐标
for(int i=0;i<4;++i) printf("%d %d\n",NowL[i].xx,NowL[i].yy);
}
void ClearL()
{//在显示屏幕上消除下降方块
for(int i=0;i<4;++i)
{
if(NowL[i].xx>=1&&NowL[i].xx<=10&&NowL[i].yy>=1&&NowL[i].yy<=20)
{
gotoxy(NowL[i].xx,NowL[i].yy);putchar(' ');
}
}
}
bool HaveBeenOver()
{//如果当前下降方块还没有开始下降便已经无法下降 就代表游戏结束
for(int i=0;i<4;++i) if(NowL[i].yy<=0) return 1;
return 0;
}
};
4.消去方块
int Speed=500,Score,cnt=1,tot,resline;
void CheckScore()
{
bool flag=0;int tottmp=0;
for(int j=20;j;--j)
{
flag=1;
for(int i=1;i<=10;++i) if(nowhave[i][j]==0) {flag=0;break;}
if(flag) solo[++tottmp]=j;//存在可以消去的整行
}
if(tottmp==0) return;//如果没有可以消去的整行
memset(nowtmp,0,sizeof nowtmp);
for(int j=20,x=1,y=20;j;--j)
{//这里的话 使用了一个移动指针法来让没有被消去的重新积累在一起
if(x<=tottmp&&j==solo[x]) ++x;
else
{
for(int i=1;i<=10;++i) nowtmp[i][y]=nowhave[i][j];
--y;
}
}
if(eyeflag)
{//正常模式下先删除过去的
for(int j=20;j;--j)
for(int i=1;i<=10;++i)
{gotoxy(i,j);putchar(' ');}
}
for(int j=20;j;--j)
for(int i=1;i<=10;++i)
nowhave[i][j]=nowtmp[i][j];
if(eyeflag)
{//然后在打印出新的
for(int j=20;j;--j)
for(int i=1;i<=10;++i)
{gotoxy(i,j);putchar(nowhave[i][j] ? '*':' ');}
}
tot+=tottmp;resline+=tottmp;//这里也是我自定义的计分制度 不适应的可以自定义
if(resline>=50) ++cnt,resline%=50,Speed=Speed*4/5;
if(tottmp==1) Score+=tottmp*cnt;
if(tottmp==2) Score+=(tottmp*cnt)*5/4;
if(tottmp==3) Score+=(tottmp*cnt)*4/3;
if(tottmp==4) Score+=(tottmp*cnt)*3/2;
}
5.主函数
我们把上面的拼在一起
bool Choice()
{
char ch;
ch=_getch();
ch=_getch();
if(ch==72) return 1;
else return 0;
}
int main()
{
GameSetting newset;
PrintInfo print_info;
Square nowL;
newset.GameInit();newset.GameStart();//游戏初始化,载入开始界面
eyeflag=Choice();//上下键选择模式(可视化还是不可视)
print_info.DrawMap();//打印初始版面
while(true)
{
print_info.DrawScore(cnt,tot,Score);//打印游戏信息
print_info.ClearNext();//先清理旧的下一个块
print_info.DrawNext(nowL.getNext());//再打印当前的下一个块
if(eyeflag) print_info.DrawNowHave();//如果正常 打印已经存在且没有被消去的块
if(nowL.CanMove()==0)
{//如果不可以移动的话
if(nowL.HaveBeenOver())
{//判断游戏是否结束
newset.GameOver(Score);
break;
}
nowL.MapChange();//更新已经存在且没有被消去的块
CheckScore();//更新成绩
nowL.getNew();//更新下降的块
continue;
}
nowL.Move();nowL.Draw();//下降的块的移动和打印
Sleep(Speed);
nowL.ClearL();//再在显示屏幕上删除下降的块
}
return 0;
}
其实从这里 我们可以发现 算法在现实中也是具有较大作用的
完整代码CODE:
#include<bits/stdc++.h>
#include<windows.h>
#include<conio.h>
using namespace std;
int Speed=500,Score,cnt=1,tot,resline;
bool nowhave[30][30],nowtmp[30][30];
int solo[40];
bool eyeflag;
struct Node
{
int xx,yy;
};
void gotoxy(short x, short y)
{
COORD coord={x, y};
//COORD是Windows API中定义的一种结构体类型,表示控制台屏幕上的坐标。
//上面语句是定义了COORD类型的变量coord,并以形参x和y进行初始化。
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),coord);
//GetStdHandle(STD_OUTPUT_HANDLE); 获取控制台输出句柄
//然后用SetConsoleCursorPosition设置控制台(cmd)光标位置
}
class GameSetting
{
public:
static const int window_height=22;
static const int window_width=28;
public:
static void GameInit()
{//调节屏幕尺寸
char buffer[32];
sprintf(buffer,"mode con cols=%d lines=%d",window_width,window_height);
system(buffer);
//隐藏光标
HANDLE handle=GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_CURSOR_INFO cursor;
GetConsoleCursorInfo(handle,&cursor);
cursor.bVisible=false;
SetConsoleCursorInfo(handle,&cursor);
//随机种子
srand((unsigned int)time((int)(998244353==19260817)));
}
static void GameStart()
{//开始游戏界面
system("cls");
for(int i=1;i<=window_width;++i) putchar('#');
putchar('\n');
for(int i=2;i<window_height;++i)
{
for(int j=1;j<=window_width;++j)
if(j==1||j==window_width) putchar('#');
else putchar(' ');
putchar('\n');
}
for(int i=1;i<=window_width;++i) putchar('#');
gotoxy(7,9);printf("俄罗斯方块");
gotoxy(7,11);printf("方向键控制");
gotoxy(7,13);printf("请选择模式:");
gotoxy(4,15);printf("↑:正常 ↓:黑暗");
}
static void GameOver(int score)
{//游戏结束界面
for(int i=3;i<=17;++i)
for(int j=7;j<=13;++j)
gotoxy(i,j),putchar(' ');
gotoxy(7,9);printf("游戏结束!");
gotoxy(5,11);printf("当前分数为:%03d",score);
}
};
/*
1
****
2
**
**
3
*
***
4
*
***
5
*
***
6
**
**
7
**
**
*/
class PrintInfo
{
public:
static void DrawMap()
{//打印初始版面
system("cls");
for(int i=1;i<=GameSetting::window_width;++i) putchar('#');
putchar('\n');
for(int i=2;i<GameSetting::window_height;++i)
{
for(int j=1;j<=GameSetting::window_width;++j)
if(i==11&&j>=12) putchar('#');
else if(j==1||j==GameSetting::window_width||j==12) putchar('#');
else putchar(' ');
putchar('\n');
}
for(int i=1;i<=GameSetting::window_width;++i) putchar('#');
for(int i=1;i<=20;++i) {gotoxy(i,21);nowhave[i][21]=1;}
}
static void DrawNext(int knd)
{//俄罗斯方块需要有下一个的提示 所以我们需要在右上角显示下一个方块的信息
gotoxy(13,2);printf("Next:");
switch(knd)
{//具体为什么会这么打印 跟上面的对应吧
case 1:
gotoxy(14+2,3+2);putchar('*');
gotoxy(15+2,3+2);putchar('*');
gotoxy(16+2,3+2);putchar('*');
gotoxy(17+2,3+2);putchar('*');
break;
case 2:
gotoxy(14+2,3+2);putchar('*');
gotoxy(15+2,3+2);putchar('*');
gotoxy(14+2,4+2);putchar('*');
gotoxy(15+2,4+2);putchar('*');
break;
case 3:
gotoxy(15+2,3+2);putchar('*');
gotoxy(14+2,4+2);putchar('*');
gotoxy(15+2,4+2);putchar('*');
gotoxy(16+2,4+2);putchar('*');
break;
case 4:
gotoxy(14+2,3+2);putchar('*');
gotoxy(14+2,4+2);putchar('*');
gotoxy(15+2,4+2);putchar('*');
gotoxy(16+2,4+2);putchar('*');
break;
case 5:
gotoxy(16+2,3+2);putchar('*');
gotoxy(14+2,4+2);putchar('*');
gotoxy(15+2,4+2);putchar('*');
gotoxy(16+2,4+2);putchar('*');
break;
case 6:
gotoxy(14+2,3+2);putchar('*');
gotoxy(15+2,3+2);putchar('*');
gotoxy(15+2,4+2);putchar('*');
gotoxy(16+2,4+2);putchar('*');
break;
case 7:
gotoxy(15+2,3+2);putchar('*');
gotoxy(16+2,3+2);putchar('*');
gotoxy(14+2,4+2);putchar('*');
gotoxy(15+2,4+2);putchar('*');
break;
}
}
static void ClearNext()
{//每一次打印完之后为了防止覆盖下一个 我们需要清理
gotoxy(14+2,3+2);putchar(' ');
gotoxy(15+2,3+2);putchar(' ');
gotoxy(16+2,3+2);putchar(' ');
gotoxy(17+2,3+2);putchar(' ');
gotoxy(14+2,4+2);putchar(' ');
gotoxy(15+2,4+2);putchar(' ');
gotoxy(16+2,4+2);putchar(' ');
}
static void DrawScore(int hard,int line,int score)
{//显示当前游戏信息
gotoxy(13,13);printf("游戏等级:%02d\n",hard);
gotoxy(13,15);printf("消灭行数:%03d\n",line);
gotoxy(13,17);printf("玩家分数:%03d\n",score);
gotoxy(13,19);printf("作者:破晓晨光");
}
static void DrawNowHave()
{//打印下方已经存在还没有消去的块
for(int i=1;i<=20;++i)
for(int j=1;j<=10;++j)
{
gotoxy(j,i);
putchar(nowhave[j][i] ? '*':' ');
}
}
};
class Square
{
private:
vector<Node> NowL,tmp;//存储当前下降方块的坐标 以及用于临时存储的vector
int NowKnd,nowdir;//当前方框的种类和朝向
int NextKnd;//下一个方块的种类
public:
Square()
{//初始构造函数
NowKnd=rand()%7+1;nowdir=0;
NextKnd=rand()%7+1;
NowL.clear();
switch(NowKnd)
{//初始的方块所在显示屏幕的位置
case 1:
NowL.push_back((Node){4,0});
NowL.push_back((Node){5,0});
NowL.push_back((Node){6,0});
NowL.push_back((Node){7,0});
break;
case 2:
NowL.push_back((Node){5,-1});
NowL.push_back((Node){6,-1});
NowL.push_back((Node){5,0});
NowL.push_back((Node){6,0});
break;
case 3:
NowL.push_back((Node){6,-1});
NowL.push_back((Node){5,0});
NowL.push_back((Node){6,0});
NowL.push_back((Node){7,0});
break;
case 4:
NowL.push_back((Node){5,-1});
NowL.push_back((Node){5,0});
NowL.push_back((Node){6,0});
NowL.push_back((Node){7,0});
break;
case 5:
NowL.push_back((Node){7,-1});
NowL.push_back((Node){5,0});
NowL.push_back((Node){6,0});
NowL.push_back((Node){7,0});
break;
case 6:
NowL.push_back((Node){4,-1});
NowL.push_back((Node){5,-1});
NowL.push_back((Node){5,0});
NowL.push_back((Node){6,0});
break;
case 7:
NowL.push_back((Node){5,-1});
NowL.push_back((Node){6,-1});
NowL.push_back((Node){4,0});
NowL.push_back((Node){5,0});
break;
}
}
void getNew()
{//获取新的下降方块 其种类就是当前的下一个的种类
NowKnd=NextKnd;nowdir=0;NowL.clear();
NextKnd=rand()%7+1;
switch(NowKnd)
{
case 1:
NowL.push_back((Node){4,0});
NowL.push_back((Node){5,0});
NowL.push_back((Node){6,0});
NowL.push_back((Node){7,0});
break;
case 2:
NowL.push_back((Node){5,-1});
NowL.push_back((Node){6,-1});
NowL.push_back((Node){5,0});
NowL.push_back((Node){6,0});
break;
case 3:
NowL.push_back((Node){6,-1});
NowL.push_back((Node){5,0});
NowL.push_back((Node){6,0});
NowL.push_back((Node){7,0});
break;
case 4:
NowL.push_back((Node){5,-1});
NowL.push_back((Node){5,0});
NowL.push_back((Node){6,0});
NowL.push_back((Node){7,0});
break;
case 5:
NowL.push_back((Node){7,-1});
NowL.push_back((Node){5,0});
NowL.push_back((Node){6,0});
NowL.push_back((Node){7,0});
break;
case 6:
NowL.push_back((Node){4,-1});
NowL.push_back((Node){5,-1});
NowL.push_back((Node){5,0});
NowL.push_back((Node){6,0});
break;
case 7:
NowL.push_back((Node){5,-1});
NowL.push_back((Node){6,-1});
NowL.push_back((Node){4,0});
NowL.push_back((Node){5,0});
break;
}
}
void listen_keyboard()
{//监听键盘
char ch;
if(_kbhit())
{
ch=_getch();
ch=_getch();//72向上 80向下 75向左 77向右
int maxn=-1,minn=35;
bool okay=1;
for(int i=0;i<4;++i)
{//我们分别判断左移 右移 加速下降是否合法
minn=min(minn,NowL[i].xx),maxn=max(maxn,NowL[i].xx);
for(int j=1;j<=3;++j)
if(NowL[i].yy+j>20||nowhave[NowL[i].xx][NowL[i].yy+j]) okay=0;
}
if(ch==75&&minn>1)
{
for(int i=0;i<4;++i) NowL[i].xx--;
}
if(ch==77&&maxn<10)
{
for(int i=0;i<4;++i) NowL[i].xx++;
}
if(ch==80&&okay)
{
for(int i=0;i<4;++i) NowL[i].yy+=3;
}
if(ch==72)
{//最复杂的旋转操作 建议看代码的同时自己手动模拟 以便理解
tmp.clear();
switch(NowKnd)
{
case 1:
if(nowdir==0)
{
int nowx=NowL[1].xx,nowy=NowL[1].yy;
bool flag=1;
tmp.push_back((Node){nowx,nowy-1});
tmp.push_back((Node){nowx,nowy});
tmp.push_back((Node){nowx,nowy+1});
tmp.push_back((Node){nowx,nowy+2});
for(int i=0;i<4;++i) if(tmp[i].xx<1||tmp[i].xx>10||tmp[i].yy<1||tmp[i].yy>20||nowhave[tmp[i].xx][tmp[i].yy]) {flag=0;break;}
if(flag)
{
NowL.clear();
for(int i=0;i<4;++i) NowL.push_back((Node){tmp[i].xx,tmp[i].yy});
}
}
else
{
int nowx=NowL[1].xx,nowy=NowL[1].yy;
bool flag=1;
tmp.push_back((Node){nowx-1,nowy});
tmp.push_back((Node){nowx,nowy});
tmp.push_back((Node){nowx+1,nowy});
tmp.push_back((Node){nowx+2,nowy});
for(int i=0;i<4;++i) if(tmp[i].xx<1||tmp[i].xx>10||tmp[i].yy<1||tmp[i].yy>20||nowhave[tmp[i].xx][tmp[i].yy]) {flag=0;break;}
if(flag)
{
NowL.clear();
for(int i=0;i<4;++i) NowL.push_back((Node){tmp[i].xx,tmp[i].yy});
}
}
nowdir=(nowdir+1)%2;
break;
case 2:
break;
case 3:
if(nowdir==0)
{
int nowx=NowL[2].xx,nowy=NowL[2].yy;
bool flag=1;
tmp.push_back((Node){nowx,nowy-1});
tmp.push_back((Node){nowx+1,nowy});
tmp.push_back((Node){nowx,nowy});
tmp.push_back((Node){nowx,nowy+1});
for(int i=0;i<4;++i) if(tmp[i].xx<1||tmp[i].xx>10||tmp[i].yy<1||tmp[i].yy>20||nowhave[tmp[i].xx][tmp[i].yy]) {flag=0;break;}
if(flag)
{
NowL.clear();
for(int i=0;i<4;++i) NowL.push_back((Node){tmp[i].xx,tmp[i].yy});
}
}
else if(nowdir==1)
{
int nowx=NowL[2].xx,nowy=NowL[2].yy;
bool flag=1;
tmp.push_back((Node){nowx+1,nowy});
tmp.push_back((Node){nowx-1,nowy});
tmp.push_back((Node){nowx,nowy});
tmp.push_back((Node){nowx,nowy+1});
for(int i=0;i<4;++i) if(tmp[i].xx<1||tmp[i].xx>10||tmp[i].yy<1||tmp[i].yy>20||nowhave[tmp[i].xx][tmp[i].yy]) {flag=0;break;}
if(flag)
{
NowL.clear();
for(int i=0;i<4;++i) NowL.push_back((Node){tmp[i].xx,tmp[i].yy});
}
}
else if(nowdir==2)
{
int nowx=NowL[2].xx,nowy=NowL[2].yy;
bool flag=1;
tmp.push_back((Node){nowx,nowy-1});
tmp.push_back((Node){nowx-1,nowy});
tmp.push_back((Node){nowx,nowy});
tmp.push_back((Node){nowx,nowy+1});
for(int i=0;i<4;++i) if(tmp[i].xx<1||tmp[i].xx>10||tmp[i].yy<1||tmp[i].yy>20||nowhave[tmp[i].xx][tmp[i].yy]) {flag=0;break;}
if(flag)
{
NowL.clear();
for(int i=0;i<4;++i) NowL.push_back((Node){tmp[i].xx,tmp[i].yy});
}
}
else if(nowdir==3)
{
int nowx=NowL[2].xx,nowy=NowL[2].yy;
bool flag=1;
tmp.push_back((Node){nowx+1,nowy});
tmp.push_back((Node){nowx-1,nowy});
tmp.push_back((Node){nowx,nowy});
tmp.push_back((Node){nowx,nowy-1});
for(int i=0;i<4;++i) if(tmp[i].xx<1||tmp[i].xx>10||tmp[i].yy<1||tmp[i].yy>20||nowhave[tmp[i].xx][tmp[i].yy]) {flag=0;break;}
if(flag)
{
NowL.clear();
for(int i=0;i<4;++i) NowL.push_back((Node){tmp[i].xx,tmp[i].yy});
}
}
nowdir=(nowdir+1)%4;
break;
case 4:
if(nowdir==0)
{
int nowx=NowL[1].xx,nowy=NowL[1].yy;
bool flag=1;
tmp.push_back((Node){nowx+1,nowy});
tmp.push_back((Node){nowx,nowy});
tmp.push_back((Node){nowx,nowy+1});
tmp.push_back((Node){nowx,nowy+2});
for(int i=0;i<4;++i) if(tmp[i].xx<1||tmp[i].xx>10||tmp[i].yy<1||tmp[i].yy>20||nowhave[tmp[i].xx][tmp[i].yy]) {flag=0;break;}
if(flag)
{
NowL.clear();
for(int i=0;i<4;++i) NowL.push_back((Node){tmp[i].xx,tmp[i].yy});
}
}
else if(nowdir==1)
{
int nowx=NowL[1].xx,nowy=NowL[1].yy;
bool flag=1;
tmp.push_back((Node){nowx,nowy+1});
tmp.push_back((Node){nowx,nowy});
tmp.push_back((Node){nowx-1,nowy});
tmp.push_back((Node){nowx-2,nowy});
for(int i=0;i<4;++i) if(tmp[i].xx<1||tmp[i].xx>10||tmp[i].yy<1||tmp[i].yy>20||nowhave[tmp[i].xx][tmp[i].yy]) {flag=0;break;}
if(flag)
{
NowL.clear();
for(int i=0;i<4;++i) NowL.push_back((Node){tmp[i].xx,tmp[i].yy});
}
}
else if(nowdir==2)
{
int nowx=NowL[1].xx,nowy=NowL[1].yy;
bool flag=1;
tmp.push_back((Node){nowx-1,nowy});
tmp.push_back((Node){nowx,nowy});
tmp.push_back((Node){nowx,nowy-1});
tmp.push_back((Node){nowx,nowy-2});
for(int i=0;i<4;++i) if(tmp[i].xx<1||tmp[i].xx>10||tmp[i].yy<1||tmp[i].yy>20||nowhave[tmp[i].xx][tmp[i].yy]) {flag=0;break;}
if(flag)
{
NowL.clear();
for(int i=0;i<4;++i) NowL.push_back((Node){tmp[i].xx,tmp[i].yy});
}
}
else if(nowdir==3)
{
int nowx=NowL[1].xx,nowy=NowL[1].yy;
bool flag=1;
tmp.push_back((Node){nowx,nowy-1});
tmp.push_back((Node){nowx,nowy});
tmp.push_back((Node){nowx+1,nowy});
tmp.push_back((Node){nowx+2,nowy});
for(int i=0;i<4;++i) if(tmp[i].xx<1||tmp[i].xx>10||tmp[i].yy<1||tmp[i].yy>20||nowhave[tmp[i].xx][tmp[i].yy]) {flag=0;break;}
if(flag)
{
NowL.clear();
for(int i=0;i<4;++i) NowL.push_back((Node){tmp[i].xx,tmp[i].yy});
}
}
nowdir=(nowdir+1)%4;
break;
case 5:
if(nowdir==0)
{
int nowx=NowL[1].xx,nowy=NowL[1].yy;
bool flag=1;
tmp.push_back((Node){nowx+1,nowy});
tmp.push_back((Node){nowx,nowy});
tmp.push_back((Node){nowx,nowy-1});
tmp.push_back((Node){nowx,nowy-2});
for(int i=0;i<4;++i) if(tmp[i].xx<1||tmp[i].xx>10||tmp[i].yy<1||tmp[i].yy>20||nowhave[tmp[i].xx][tmp[i].yy]) {flag=0;break;}
if(flag)
{
NowL.clear();
for(int i=0;i<4;++i) NowL.push_back((Node){tmp[i].xx,tmp[i].yy});
}
}
else if(nowdir==1)
{
int nowx=NowL[1].xx,nowy=NowL[1].yy;
bool flag=1;
tmp.push_back((Node){nowx,nowy+1});
tmp.push_back((Node){nowx,nowy});
tmp.push_back((Node){nowx+1,nowy});
tmp.push_back((Node){nowx+2,nowy});
for(int i=0;i<4;++i) if(tmp[i].xx<1||tmp[i].xx>10||tmp[i].yy<1||tmp[i].yy>20||nowhave[tmp[i].xx][tmp[i].yy]) {flag=0;break;}
if(flag)
{
NowL.clear();
for(int i=0;i<4;++i) NowL.push_back((Node){tmp[i].xx,tmp[i].yy});
}
}
else if(nowdir==2)
{
int nowx=NowL[1].xx,nowy=NowL[1].yy;
bool flag=1;
tmp.push_back((Node){nowx-1,nowy});
tmp.push_back((Node){nowx,nowy});
tmp.push_back((Node){nowx,nowy+1});
tmp.push_back((Node){nowx,nowy+2});
for(int i=0;i<4;++i) if(tmp[i].xx<1||tmp[i].xx>10||tmp[i].yy<1||tmp[i].yy>20||nowhave[tmp[i].xx][tmp[i].yy]) {flag=0;break;}
if(flag)
{
NowL.clear();
for(int i=0;i<4;++i) NowL.push_back((Node){tmp[i].xx,tmp[i].yy});
}
}
else if(nowdir==3)
{
int nowx=NowL[1].xx,nowy=NowL[1].yy;
bool flag=1;
tmp.push_back((Node){nowx,nowy-1});
tmp.push_back((Node){nowx,nowy});
tmp.push_back((Node){nowx-1,nowy});
tmp.push_back((Node){nowx-2,nowy});
for(int i=0;i<4;++i) if(tmp[i].xx<1||tmp[i].xx>10||tmp[i].yy<1||tmp[i].yy>20||nowhave[tmp[i].xx][tmp[i].yy]) {flag=0;break;}
if(flag)
{
NowL.clear();
for(int i=0;i<4;++i) NowL.push_back((Node){tmp[i].xx,tmp[i].yy});
}
}
nowdir=(nowdir+1)%4;
break;
case 6:
if(nowdir==0)
{
int nowx=NowL[1].xx,nowy=NowL[1].yy;
bool flag=1;
tmp.push_back((Node){nowx,nowy-1});
tmp.push_back((Node){nowx,nowy});
tmp.push_back((Node){nowx-1,nowy});
tmp.push_back((Node){nowx-1,nowy+1});
for(int i=0;i<4;++i) if(tmp[i].xx<1||tmp[i].xx>10||tmp[i].yy<1||tmp[i].yy>20||nowhave[tmp[i].xx][tmp[i].yy]) {flag=0;break;}
if(flag)
{
NowL.clear();
for(int i=0;i<4;++i) NowL.push_back((Node){tmp[i].xx,tmp[i].yy});
}
}
else
{
int nowx=NowL[1].xx,nowy=NowL[1].yy;
bool flag=1;
tmp.push_back((Node){nowx-1,nowy});
tmp.push_back((Node){nowx,nowy});
tmp.push_back((Node){nowx,nowy+1});
tmp.push_back((Node){nowx+1,nowy+1});
for(int i=0;i<4;++i) if(tmp[i].xx<1||tmp[i].xx>10||tmp[i].yy<1||tmp[i].yy>20||nowhave[tmp[i].xx][tmp[i].yy]) {flag=0;break;}
if(flag)
{
NowL.clear();
for(int i=0;i<4;++i) NowL.push_back((Node){tmp[i].xx,tmp[i].yy});
}
}
nowdir=(nowdir+1)%2;
break;
case 7:
if(nowdir==0)
{
int nowx=NowL[0].xx,nowy=NowL[0].yy;
bool flag=1;
tmp.push_back((Node){nowx,nowy});
tmp.push_back((Node){nowx,nowy+1});
tmp.push_back((Node){nowx-1,nowy});
tmp.push_back((Node){nowx-1,nowy-1});
for(int i=0;i<4;++i) if(tmp[i].xx<1||tmp[i].xx>10||tmp[i].yy<1||tmp[i].yy>20||nowhave[tmp[i].xx][tmp[i].yy]) {flag=0;break;}
if(flag)
{
NowL.clear();
for(int i=0;i<4;++i) NowL.push_back((Node){tmp[i].xx,tmp[i].yy});
}
}
else
{
int nowx=NowL[0].xx,nowy=NowL[0].yy;
bool flag=1;
tmp.push_back((Node){nowx,nowy});
tmp.push_back((Node){nowx+1,nowy});
tmp.push_back((Node){nowx-1,nowy+1});
tmp.push_back((Node){nowx,nowy+1});
for(int i=0;i<4;++i) if(tmp[i].xx<1||tmp[i].xx>10||tmp[i].yy<1||tmp[i].yy>20||nowhave[tmp[i].xx][tmp[i].yy]) {flag=0;break;}
if(flag)
{
NowL.clear();
for(int i=0;i<4;++i) NowL.push_back((Node){tmp[i].xx,tmp[i].yy});
}
}
nowdir=(nowdir+1)%2;
break;
}
}
}
}
int getNext(){return NextKnd;}//获取下一个方块的种类
bool CanMove()
{//判断当前下降方块是否可以下降
for(int i=0;i<4;++i)
{
int nowx=NowL[i].xx,nowy=NowL[i].yy;
if(nowhave[nowx][nowy+1]||nowy+1>20) return 0;
}
return 1;
}
void Move()
{//向下移动
listen_keyboard();
if(CanMove())
for(int i=0;i<4;++i) ++NowL[i].yy;
}
void MapChange()
{//更新下方存在没有消去的方块
for(int i=0;i<4;++i) nowhave[NowL[i].xx][NowL[i].yy]=1;
}
void Draw()
{//打印下方存在没有消去的方块
for(int i=0;i<4;++i)
{
if(NowL[i].xx>=1&&NowL[i].xx<=10&&NowL[i].yy>=1&&NowL[i].yy<=20)
{
gotoxy(NowL[i].xx,NowL[i].yy);putchar('*');
}
}
}
void print()
{//打印下降方块的二维坐标
for(int i=0;i<4;++i) printf("%d %d\n",NowL[i].xx,NowL[i].yy);
}
void ClearL()
{//在显示屏幕上消除下降方块
for(int i=0;i<4;++i)
{
if(NowL[i].xx>=1&&NowL[i].xx<=10&&NowL[i].yy>=1&&NowL[i].yy<=20)
{
gotoxy(NowL[i].xx,NowL[i].yy);putchar(' ');
}
}
}
bool HaveBeenOver()
{//如果当前下降方块还没有开始下降便已经无法下降 就代表游戏结束
for(int i=0;i<4;++i) if(NowL[i].yy<=0) return 1;
return 0;
}
};
void CheckScore()
{
bool flag=0;int tottmp=0;
for(int j=20;j;--j)
{
flag=1;
for(int i=1;i<=10;++i) if(nowhave[i][j]==0) {flag=0;break;}
if(flag) solo[++tottmp]=j;//存在可以消去的整行
}
if(tottmp==0) return;//如果没有可以消去的整行
memset(nowtmp,0,sizeof nowtmp);
for(int j=20,x=1,y=20;j;--j)
{//这里的话 使用了一个移动指针法来让没有被消去的重新积累在一起
if(x<=tottmp&&j==solo[x]) ++x;
else
{
for(int i=1;i<=10;++i) nowtmp[i][y]=nowhave[i][j];
--y;
}
}
if(eyeflag)
{//正常模式下先删除过去的
for(int j=20;j;--j)
for(int i=1;i<=10;++i)
{gotoxy(i,j);putchar(' ');}
}
for(int j=20;j;--j)
for(int i=1;i<=10;++i)
nowhave[i][j]=nowtmp[i][j];
if(eyeflag)
{//然后在打印出新的
for(int j=20;j;--j)
for(int i=1;i<=10;++i)
{gotoxy(i,j);putchar(nowhave[i][j] ? '*':' ');}
}
tot+=tottmp;resline+=tottmp;//这里也是我自定义的计分制度 不适应的可以自定义
if(resline>=50) ++cnt,resline%=50,Speed=Speed*4/5;
if(tottmp==1) Score+=tottmp*cnt;
if(tottmp==2) Score+=(tottmp*cnt)*5/4;
if(tottmp==3) Score+=(tottmp*cnt)*4/3;
if(tottmp==4) Score+=(tottmp*cnt)*3/2;
}
bool Choice()
{
char ch;
ch=_getch();
ch=_getch();
if(ch==72) return 1;
else return 0;
}
int main()
{
GameSetting newset;
PrintInfo print_info;
Square nowL;
newset.GameInit();newset.GameStart();//游戏初始化,载入开始界面
eyeflag=Choice();//上下键选择模式(可视化还是不可视)
print_info.DrawMap();//打印初始版面
while(true)
{
print_info.DrawScore(cnt,tot,Score);//打印游戏信息
print_info.ClearNext();//先清理旧的下一个块
print_info.DrawNext(nowL.getNext());//再打印当前的下一个块
if(eyeflag) print_info.DrawNowHave();//如果正常 打印已经存在且没有被消去的块
if(nowL.CanMove()==0)
{//如果不可以移动的话
if(nowL.HaveBeenOver())
{//判断游戏是否结束
newset.GameOver(Score);
break;
}
nowL.MapChange();//更新已经存在且没有被消去的块
CheckScore();//更新成绩
nowL.getNew();//更新下降的块
continue;
}
nowL.Move();nowL.Draw();//下降的块的移动和打印
Sleep(Speed);
nowL.ClearL();//再在显示屏幕上删除下降的块
}
return 0;
}