写了一个俄罗斯方块来检验自己所学,在这里个大家分享一下,程序还有一些不足之处,这里我分享下我个人的思路,第一次写这样的东西,可能的说的不是很清楚,
程序要求:
打印不同类型的方块,使方块自由下落,过程中需要通过按键来实现方块的左移,右移,旋转,加速下落,暂停等功能;另外还要实现当方块到达边界的时候,停止左移,右移,下落,防止方块越界。同时,还需要检测是否右满行,如果有,需要程序将满行消除,同时将其他非满行完整下移;根据消除的行数在右边界面显示实时的分数,以及随着游戏进行,速度的变化****加粗样式
说到这里,问题便是如何检测方块是否到达边界,是否满行等
这里的解决方法是通过一个数组来检测某行某列是否有方块存在,数组的行和列分别对应打印方块的Y,X坐标(行对应Y,列对应X)
另外需要注意的是一个方块在横坐标上等同于输出两个字符,(所以如果你的数组列数为16,去掉用来检测方块是否到达边界的两列,打印方块的区域的大小应该为142=28)纵坐标上与平常字符没有区别。*
接下来是具体实施方法,将数组第一行的第一列和最后一列赋给数值1,第一行和最后一行赋值1,通过检测方块的下一个左标时的数组值是否是1,来检测方块是否到达边界。
我个人的一个思路是先将方块的横纵坐标表示出来,例如:打印田字形方块时,每一个小方块的横坐标依次是{2,4,2,4}(从左往右,从上往下),纵坐标依次是{1,1,2,2};这样就可以在你想要的位置出打印方块
接下来上代码
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <conio.h>
#include <time.h>
#define Lframewidth 32//边框的宽
#define Lframeheight 26//边框的高
#define SX 39//得分显示坐标
#define SY 10
#define SPX 39//速度显示坐标
#define SPY 12
int TYPEX[7][4][4]=//共有七种类型
{
{
{2,4,6,8},{2,2,2,2},{2,4,6,8},{2,2,2,2}
},
{
{2,4,2,4},{2,4,2,4},{2,4,2,4},{2,4,2,4}
},
{
{2,4,6,2},{2,4,4,4},{2,4,6,6},{2,2,2,4}
},
{
{2,2,4,6},{2,4,2,2},{2,4,6,6},{2,4,4,4}
},
{
{2,2,4,4},{2,4,4,6},{2,2,4,4},{2,4,4,6}
},
{
{2,2,4,4},{2,4,4,6},{2,2,4,4},{2,4,4,6}
},
{
{2,4,4,6},{2,2,2,4},{2,4,4,6},{2,4,4,4}
}
};
int TYPEY[7][4][4]=
{
{
{1,1,1,1},{1,2,3,4},{1,1,1,1},{1,2,3,4}
},
{
{1,1,2,2},{1,1,2,2},{1,1,2,2},{1,1,2,2}
},
{
{1,1,1,2},{1,1,2,3},{2,2,2,1},{1,2,3,3}
},
{
{1,2,2,2},{1,1,2,3},{1,1,1,2},{3,1,2,3}
},
{
{1,2,2,3},{2,1,2,1},{1,2,2,3},{2,1,2,1}
},
{
{2,3,1,2},{1,1,2,2},{2,3,1,2},{1,1,2,2}
},
{
{2,1,2,2},{1,2,3,2},{1,1,2,1},{2,1,2,3}
}
};
int array[27][17]={0};
int NextX=36;
int NextY=4;//打印下一个方块的坐标
int shape;
int type;//记录随机类型
int x=8;
int y=0;//确定初始打印方块的位置,在此基础上加上相应的横纵坐标
int m=0;
int speed=400;
int NextType;//下一个方块的属性
int NextShape;
int Score=0;
void HideCursor();//隐藏光标函数
void gotoXY(int x,int y);//光标位置移动函数
void InterInfo();//打印游戏边框
void PrintBricks();//随机生成方块,打印方块
void KeyValue();//通过按键控制左右移动 加速 旋转 暂停
void CleanRow();//消除满行
int main()
{
int i,j;
InterInfo();
for(i=0;i<27;i++)
{
array[i][0]=1;
array[i][16]=1;
}
for(i=0;i<18;i++)
{
array[0][i]=1;
array[26][i]=1;
}
PrintBricks();
}
void HideCursor()
{
CONSOLE_CURSOR_INFO cursor_info = {1, 0};
SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info);
}
void CleanRow()
{
int i,j,countrow=0,countcol=0;
for(i=25;i>0;i--)
{
for(j=2;j<32;j+=2)
{
if(array[i][j/2]==1)
countcol++;
}
if(countcol==15)
{
countrow++;
}
countcol=0;
}
for(i=25;i>25-countrow;i--)
{
for(j=2;j<32;j+=2)
{
gotoXY(j,i);
printf(" ");
array[i][j/2]=0;
}
}
for(i=25-countrow;i>0;i--)
{
for(j=2;j<32;j+=2)
{
if(array[i][j/2]==1)
{
gotoXY(j,i);
printf(" ");
array[i][j/2]=0;
gotoXY(j,i+countrow);
printf("■");
array[i+countrow][j/2]=1;
}
}
}
Score=Score+countrow*10;
gotoXY(SX,SY);
if(countrow==1)
{
printf("%d",Score+10);
}
else if(countrow==2)
{
printf("%d",Score+20);
}
else if(countrow==3)
{
printf("%d",Score+30);
}
else if(countrow>3)
{
printf("%d",Score+60);
}
}
void KeyValue()
{
int i,j,k=1;
int key;
if(kbhit()!=0)
{
setbuf(stdin,NULL);//
if(kbhit()!=0)
key=getch();
setbuf(stdin,NULL);
}
else
{
return;
}
switch(key)
{
case 97:
for(i=0,j=0;i<4,j<4;i++,j++)
{
if(array[y+TYPEY[type][shape][j]+1][x/2+m/2+TYPEX[type][shape][i]/2-1]==1)
k=0;
}
if(k!=0)
m-=2;
break;
case 100:
for(i=0,j=0;i<4,j<4;i++,j++)
{
if(array[y+TYPEY[type][shape][j]+1][x/2+m/2+TYPEX[type][shape][i]/2+1]==1)
k=0;
}
if(k!=0)
m+=2;
break;
case 115:
speed-=300;
Sleep(5);
break;
case 119:
if(shape==0||shape==1||shape==2)
shape++;
else
shape=shape-3;
break;
case 32:
getch();
setbuf(stdin,NULL);
break;
}
}
void PrintBricks()
{
int i,j,k=1,count=0,n=1;
srand((unsigned int)(time(NULL)));
type=rand()%7;
shape=rand()%4;//生成第一个方块
srand((unsigned int)(time(NULL)));
NextType=rand()%7;
NextShape=rand()%4;//生成下一个方块
for(i=0,j=0;i<4,j<4;i++,j++)
{
gotoXY(NextX+TYPEX[NextType][NextShape][i],NextY+TYPEY[NextType][NextShape][j]);
printf("■");//在右边提示栏打印下一个方块
}
while(1)
{
x=10,y=0;
m=0;
while(k)//方块自由下落
{
KeyValue();
for(i=0,j=0;i<4,j<4;i++,j++)
{
HideCursor();
gotoXY(x+m+TYPEX[type][shape][i],y+TYPEY[type][shape][j]);
printf("■");
if(array[y+TYPEY[type][shape][j]+1][x/2+m/2+TYPEX[type][shape][i]/2]==1)
{
k=0;
}
}
if(k==0)
{
for(i=0,j=0;i<4,j<4;i++,j++)
{
HideCursor();
gotoXY(x+m+TYPEX[type][shape][i],y+TYPEY[type][shape][j]);
printf("■");
array[y+TYPEY[type][shape][j]][x/2+m/2+TYPEX[type][shape][i]/2]=1;
}
break;
}
Sleep(500);
for(i=0,j=0;i<4,j<4;i++,j++)
{
HideCursor();
gotoXY(x+m+TYPEX[type][shape][i],y+TYPEY[type][shape][j]);
printf(" ");
}
Sleep(speed);
//speed=speed-count;
if(count==30)
{
speed-=count;
count=0;
}
gotoXY(SPX,SPY);
printf("%d",speed);
y++;
}
CleanRow();
k=1;
for(i=0,j=0;i<4,j<4;i++,j++)
{
gotoXY(NextX+TYPEX[NextType][NextShape][i],NextY+TYPEY[NextType][NextShape][j]);
printf(" ");
}
type=NextType;
shape=NextShape;
srand((unsigned int)(time(NULL)));
NextType=rand()%7;
NextShape=rand()%4;
for(i=0,j=0;i<4,j<4;i++,j++)
{
gotoXY(NextX+TYPEX[NextType][NextShape][i],NextY+TYPEY[NextType][NextShape][j]);
printf("■");
}
CleanRow();
//count++;
/*if(count==50)
{
speed-=50;
count=0;
}
gotoXY(SPX,SPY);
printf("%d",speed);*/
for(i=1;i<16;i++)
{
if(array[1][i]==1)
{
n=0;
}
}
if(n==0)
{
break;
}
}
gotoXY(16,12);
printf("游戏结束!!!");
}
void InterInfo()
{
int i,j;
gotoXY(0,0);
printf("╔");
gotoXY(Lframewidth,0);
printf("╦");
gotoXY(0,Lframeheight);
printf("╚");
gotoXY(Lframewidth,Lframeheight);
printf("╩");
for(i=1;i<Lframewidth;i++)
{
gotoXY(i,0);
printf("═");
gotoXY(i,Lframeheight);
printf("═");
}
for(i=1;i<Lframeheight;i++)
{
gotoXY(0,i);
printf("║");
gotoXY(Lframewidth,i);
printf("║");
}
gotoXY(Lframewidth+16,0);
printf("╗");
gotoXY(Lframewidth+16,Lframeheight);
printf("╝");
for(i=Lframewidth+1;i<Lframewidth+16;i++)
{
gotoXY(i,0);
printf("═");
gotoXY(i,Lframeheight);
printf("═");
}
for(i=1;i<Lframeheight;i++)
{
gotoXY(Lframewidth+16,i);
printf("║");
}
gotoXY(Lframewidth+1,1);
printf("Game Name:Teris");
for(i=Lframewidth+1;i<Lframewidth+16;i++)
{
gotoXY(i,2);
printf("═");
gotoXY(i,9);
printf("═");
gotoXY(i,4);
printf("═");
}
gotoXY(Lframewidth+1,3);
printf("Next Bricks:");
gotoXY(Lframewidth+1,10);
printf("Score:");
gotoXY(Lframewidth+1,12);
printf("Speed:");
for(i=Lframewidth+1;i<Lframewidth+16;i++)
{
gotoXY(i,13);
printf("═");
}
gotoXY(Lframewidth+2,14);
printf("操作方法:");
gotoXY(Lframewidth+2,15);
printf("w 旋转");
gotoXY(Lframewidth+2,16);
printf("a 向左");
gotoXY(Lframewidth+2,17);
printf("d 向右");
gotoXY(Lframewidth+2,18);
printf("s 加速");
gotoXY(Lframewidth+2,19);
printf("空格 暂停");
}
void gotoXY(int x, int y)
{
COORD pos = {x,y};
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);// 获取标准输出设备句柄
SetConsoleCursorPosition(hOut, pos);//两个参数分别是指定哪个窗体,具体位置
}
此代码有不足,关键学习这些东西不能闭门造车,所以贴出来希望可以和大家交流,也希望有大神路过的给予指导,感激不尽