写在卸载之前
一个蒟蒻无力的挣扎
如果你是在阅读本人的博文来实现俄罗斯方块
在实现俄罗斯方块之前 本人建议先左转贪吃蛇
正式开始
本来还是想秉持拿来主义 像贪吃蛇一样从网上随随便便找一个拿来写写
但是由于网上的俄罗斯方块 实在是要么看不懂要么运行不了这话好像已经说过了
所以没有办法 只好自己手写一个轻描淡写的一句话 背后是逝去的头发
同时由于我所使用的是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;
}