(作者:KX)
(code:C)
/***********************************
源码:俄罗斯方块
作者:王卫祥&KX&2017211836
版本:18070701
代码使用请保留版权
***********************************/
#include <stdio.h>
#include <windows.h>
#include <conio.h>
#include <time.h>
#define X(x) (2+2*(x))//棋盘坐标转屏幕绝对坐标
#define Y(y) (y)//棋盘坐标转屏幕绝对坐标
#define Grade(score) ((score)/50)//由分数计算等级
#define BorderCode "▓"//边框字符
#define FoodCode "□"//食物字符
#define SpaceCode " "//空白出字符
#define BlockCode "■"//蛇身字符
int block[7][4][4][4]=
{
{//第一种方块:正方形
{
{1,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,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}
},
},
{//第二种方块:直线
{
{0,0,0,0},
{1,1,1,1},
{0,0,0,0},
{0,0,0,0}
},
{
{0,1,0,0},
{0,1,0,0},
{0,1,0,0},
{0,1,0,0}
},
{
{0,0,0,0},
{1,1,1,1},
{0,0,0,0},
{0,0,0,0}
},
{
{0,1,0,0},
{0,1,0,0},
{0,1,0,0},
{0,1,0,0}
},
},
{//第三种方块:S形
{
{1,0,0,0},
{1,1,0,0},
{0,1,0,0},
{0,0,0,0}
},
{
{0,1,1,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}
},
{
{0,1,1,0},
{1,1,0,0},
{0,0,0,0},
{0,0,0,0}
},
},
{//第四种方块:Z形
{
{0,1,0,0},
{1,1,0,0},
{1,0,0,0},
{0,0,0,0}
},
{
{1,1,0,0},
{0,1,1,0},
{0,0,0,0},
{0,0,0,0}
},
{
{0,1,0,0},
{1,1,0,0},
{1,0,0,0},
{0,0,0,0}
},
{
{1,1,0,0},
{0,1,1,0},
{0,0,0,0},
{0,0,0,0}
},
},
{//第五种方块:J形
{
{1,0,0,0},
{1,1,1,0},
{0,0,0,0},
{0,0,0,0}
},
{
{0,1,1,0},
{0,1,0,0},
{0,1,0,0},
{0,0,0,0}
},
{
{0,0,0,0},
{1,1,1,0},
{0,0,1,0},
{0,0,0,0}
},
{
{0,1,0,0},
{0,1,0,0},
{1,1,0,0},
{0,0,0,0}
},
},
{//第六种方块:┷形
{
{0,1,0,0},
{1,1,1,0},
{0,0,0,0},
{0,0,0,0}
},
{
{0,1,0,0},
{0,1,1,0},
{0,1,0,0},
{0,0,0,0}
},
{
{0,0,0,0},
{1,1,1,0},
{0,1,0,0},
{0,0,0,0}
},
{
{0,1,0,0},
{1,1,0,0},
{0,1,0,0},
{0,0,0,0}
},
},
{//第七种方块:L形
{
{0,0,1,0},
{1,1,1,0},
{0,0,0,0},
{0,0,0,0}
},
{
{0,1,0,0},
{0,1,0,0},
{0,1,1,0},
{0,0,0,0}
},
{
{0,0,0,0},
{1,1,1,0},
{1,0,0,0},
{0,0,0,0}
},
{
{1,1,0,0},
{0,1,0,0},
{0,1,0,0},
{0,0,0,0}
},
},
};
int type,rotate,posiX,posiY;//当前下落方块的类型、旋转角度类型、(0,0)在屏幕上的位置
int preType,preRotate;//下一个方块的类型、旋转角度类型
int width=10,height=30;//棋盘大小
int sta[20][10];//静态方块
int actExist=0;//下落方块是否存在
int score;//本局得分
void printGround();//打印背景
void menu(int x,int y);//主菜单
void start();//初始化游戏
void run();//运行游戏
void operate();//用户操控游戏
void creatAct();//创建新的活动方块
void rotateAct();//旋转活动方块
void moveAct(int dire);//移动活动方块
void clearAct();//在屏幕上清除活动方块
void printAct();//在屏幕上打印活动方块
void clearStaLine();//清除静态方块补全的行
void clearSta();//清除所有静态方块
int canFall();//判断活动方块是否可继续下落
int isDeath();//判断玩家是否死亡
void tipDeath();//提示用户死亡
void act2Sta();//活动方块转静态方块
void printScore();//打印分数、等级
void printLine(int num,char *c);//在屏幕上打印num个字符c
//int getMaxScore();//获取最高分数
//void puttMaxScore(); //写入最高分数
void gotoxy(int x, int y); //光标定位
void setColor(unsigned short foreColor,unsigned short backGroundColor);//改变打印颜色
void hideCursor();//隐藏光标
int main(int argc, char *argv[])
{
system("title 俄罗斯方块");
system("mode con cols=39 lines=22");
system("color F0");
hideCursor();
while(1)
menu(7,8);
getch();
return 0;
}
void printGround()
{
int i;
setColor(3,15);
gotoxy(0,0);
for(i=0;i<20;i++)
{
printf("%s",BorderCode);
printLine(10,SpaceCode);
printf("%s",BorderCode);
printLine(6,SpaceCode);
printf("%s",BorderCode);
printf("\n");
}
printLine(19,BorderCode);
return;
}
void menu(int x,int y)
{
char key;
printGround();
gotoxy(x,y);
printf("俄罗斯方块");
gotoxy(x,y+3);
printf("1.开始游戏");
gotoxy(x,y+4);
printf("0.退出游戏");
key=getch();
switch(key)
{
case '1':start();run();break;
case '0':exit(0);break;
}
}
void start()
{
int i,j;
score=0;
actExist=0;
clearSta();
printGround();
setColor(0,15);
gotoxy(X(11),Y(0));
//maxScore=getMaxScore();
//printf("最高分:%4d",maxScore);
gotoxy(X(11),Y(2));
printf("分数:");
gotoxy(X(11),Y(4));
printf("等级:");
gotoxy(X(11),Y(6));
printf("下一个:");
gotoxy(X(11),Y(16));
printf("1.暂停游戏");
gotoxy(X(11),Y(17));
printf("2.重新开始");
gotoxy(X(11),Y(18));
printf("0.退出游戏");
printScore();
srand((unsigned) time(NULL));
creatAct();
}
void run()
{
int delayTime;
clock_t lastTime=clock();
while(1)
{
if(!actExist)
{
posiX=4;
posiY=-2;
type=preType;
rotate=preRotate;
creatAct();
if(isDeath())
{
tipDeath();
getch();
break;
}
actExist=1;
printAct();
}
delayTime=1000-Grade(score)*5;
if(delayTime<200)
{
delayTime=200;
}
if(1000*((double)(clock()-lastTime)/CLOCKS_PER_SEC)>delayTime)
{
moveAct(3);
lastTime= clock();
}
if(kbhit())
{
operate();
}
}
}
void operate()
{
char key;
if(!kbhit())
{
return;
}
key=getch();
switch(key)
{
case 'a':
case 'A':
case 75:
moveAct(0);break;
case 'w':
case 'W':
case 72:
rotateAct();break;
case 'd':
case 'D':
case 77:
moveAct(2);break;
case 's':
case 'S':
case 80:
moveAct(3);break;
case ' ':
case '\r':
while(canFall())moveAct(3);break;
case '1':
getch();break;
case '2':
start();run();break;
case '0':
exit(0);break;
}
}
void rotateAct()
{
int canRotate=1;
int i,j;
for(i=0;i<4 && canRotate;i++)
{
for(j=0;j<4 && canRotate;j++)
{
if(block[type][(rotate+1)%4][i][j]==1 && (posiX+j <0 || posiX+j>=10 || posiY+i>=20 || sta[posiY+i][posiX+j]==1))
{
canRotate=0;
}
}
}
if(canRotate)
{
clearAct();
rotate=rotate==3?0:rotate+1;
printAct();
}
}
void creatAct()
{
preType=rand()%7;
preRotate=rand()%4;
int i,j;
for(i=0;i<4;i++)
{
for(j=0;j<4;j++)
{
gotoxy(X(13+j),Y(8+i));
if(block[preType][preRotate][i][j]==1)
{
printf("%s",BlockCode);
}
else
{
printf("%s",SpaceCode);
}
}
}
}
void printAct()
{
int i,j;
setColor((type+preType+preRotate+score)%15,15);
for(i=0;i<4;i++)
{
for(j=0;j<4;j++)
{
if(block[type][rotate][i][j]==1 && posiY+i>=0)
{
gotoxy(X(posiX+j),Y(posiY+i));
printf("%s",BlockCode);
}
}
}
}
void clearAct()
{
int i,j;
for(i=0;i<4;i++)
{
for(j=0;j<4;j++)
{
if(posiX+j>=0 && posiX+j<10 && posiY+i>=0 && posiY+i<20 && sta[posiY+i][posiX+j]==0)
{
gotoxy(X(posiX+j),Y(posiY+i));
printf("%s",SpaceCode);
}
}
}
}
void moveAct(int dire)
{
int i,j;
int canMove=1;
if(dire==0)//左
{
for(i=0;i<4;i++)
{
for(j=0;j<4;j++)
{
if(block[type][rotate][i][j]==1 && (posiX+j<=0 || (posiY>0 && sta[posiY+i][posiX+j-1]==1)))
{
return;
}
}
}
clearAct();
posiX--;
printAct();
}
else if(dire==2)//右
{
for(i=0;i<4;i++)
{
for(j=0;j<4;j++)
{
if(block[type][rotate][i][j]==1 && (posiX+j>=9 || (posiY>0 &&sta[posiY+i][posiX+j+1]==1)))
{
return;
}
}
}
clearAct();
posiX++;
printAct();
}
else if(dire==3)//下
{
if(canFall())
{
clearAct();
posiY++;
printAct();
}
else
{
act2Sta();
clearStaLine();
actExist=0;
}
}
}
void clearStaLine()//清除排完的行
{
int clearNum=0;
int i,j;
for(i=19;i>=0;i--)
{
for(j=0;j<10;j++)
{
if(sta[i][j]==0)
{
break;
}
}
if(j==10)//第i行可以清空
{
clearNum++;
score+=clearNum*i+Grade(score);//加分
continue;
}
else if(clearNum!=0)
{
for(j=0;j<10;j++)
{
sta[i+clearNum][j]=sta[i][j];
}
}
}
while(clearNum)//顶部新生成的行赋值为0
{
clearNum--;
for(j=0;j<9;j++)
{
sta[clearNum][j]=0;
}
}
setColor(8,15);
for(i=0;i<20;i++)
{
for(j=0;j<10;j++)
{
gotoxy(X(j),Y(i));
printf("%s",sta[i][j]==1?BlockCode:SpaceCode);
}
}
printScore();
/*
if(score>maxScore)
{
maxScore=score;
putMaxScore();
printScore();
}
*/
}
void clearSta()
{
int i,j;
for(i=0;i<20;i++)
{
for(j=0;j<10;j++)
{
sta[i][j]=0;
}
}
}
int canFall()
{
int i,j;
for(i=0;i<4;i++)
{
for(j=0;j<4;j++)
{
if(block[type][rotate][i][j]==1 && (posiY+i>=19 || (posiY+i+1>=0 && sta[posiY+i+1][posiX+j]==1)))
{
return 0;
}
}
}
return 1;
}
int isDeath()
{
if(sta[0][5]==1)
{
return 1;
}
return 0;
}
void tipDeath()
{
gotoxy(X(11),Y(12));
setColor(12,15);
printf("游戏结束");
}
void act2Sta()
{
int i,j;
for(i=0;i<4;i++)
{
for(j=0;j<4;j++)
{
if(block[type][rotate][i][j]==1)
{
sta[posiY+i][posiX+j]=block[type][rotate][i][j];
}
}
}
}
void printScore()
{
//gotoxy(X(14),Y(0));
//printf("%5d",maxScore);
gotoxy(X(14),Y(2));
printf("%5d",score);
gotoxy(X(14),Y(4));
printf("%5d",Grade(score));
}
void printLine(int num,char *c)
{
int i;
for(i=0;i<num;i++)
{
printf("%s",c);
}
return;
}
/*
int getMaxScore()
{
FILE *fp;
fp=fopen("tetris/maxScore.txt","r");
if(fp==NULL)
{
maxScore=0;
}
else
{
fscanf(fp,"%d",&maxScore);
fclose(fp);
}
return maxScore;
}
void putMaxScore()
{
FILE *fp;
fp=fopen("tetris/maxScore.txt","w");
fprintf(fp,"%d",maxScore);
fclose(fp);
}
*/
void gotoxy(int x, int y) //光标定位
{
COORD pos;
pos.X = x;
pos.Y = y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),pos);
}
void setColor(unsigned short foreColor,unsigned short backGroundColor)
{
HANDLE handle=GetStdHandle(STD_OUTPUT_HANDLE);//获取当前窗口句柄
SetConsoleTextAttribute(handle,foreColor+backGroundColor*0x10);//设置颜色
}
void hideCursor()
{
CONSOLE_CURSOR_INFO cursor_info = {1, 0};
SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info);
}
/****Powered by KX****/
(/code)