思路:
1.初始化界面,用一个矩阵来保存界面的每一个位置,包括颜色跟数值,数值用来区分是墙还是方块还是空格,便于运行时的判断。
2.初始化方块,用4*4矩阵保存,1表示方块,0表示空格。初始7个方块,再利用矩阵旋转,得到剩下的21个方块。
3.运行时先判断再运行,可以保证不会越过墙。每一步判断4*4的方块矩阵下一格是否是方块,是方块就落在上面。
4.一个方块落到底便判断是否满一行,满一行减掉,在判断是否满一行,未满则生成下一个方块。
5.判断游戏结束:即判断最顶上一行是否有方块。
游戏图片:
代码:
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<windows.h>
#include<conio.h>
#define SPACE 32
#define LEFT 75
#define RIGHT 77
#define DOWN 80
#define ESC 27
#define Wall 2
#define Box 1
#define Kong 0
#define FACE_X 29
#define FACE_Y 20 //界面尺寸
void gotoxy(int x,int y); //移动光标
int color(int c); //颜色
void hidden_cursor(); //隐藏光标
void inter_face(); //初始化界面
void init_dia(); //初始化方块信息
void draw_dia(int base,int space_c,int x,int y); //覆盖方块
void draw_kong(int base,int space_c,int x,int y); //画方块
int pd(int n,int space_c,int x,int y); //判断是否到底
void start_game(); //开始游戏
int xc();//消除
void read_file(); //读写最高记录
void write_file(); //写最高纪录
int grade=0;//当前分数
int max=0;//最高记录
int nn=0;
struct Face
{int data[FACE_X][FACE_Y+10]; //数值,为1是方块,为0是空格int color[FACE_X][FACE_Y+10]; //对应方块的颜色
}face;
typedef struct Diamonds
{ int space[4][4]; //4*4矩阵,为1为方块,为0 为空
}Dia;
Dia dia[7][4]; //一维基础7个方块,二维表示旋转次数
int main()
{ system("cls");system("title 俄罗斯方块");color(7);system("mode con cols=60 lines=30"); //窗口宽度高度 hidden_cursor();srand(time(NULL));read_file();grade=0;inter_face();init_dia();nn=rand()%7;while(1){start_game();}return 0;
}
/////////////////////////////////////////////////
void start_game()
{ int n,ch,t=0,x=0,y=FACE_Y/2-2,i,j;int space_c=0;//旋转次数draw_kong(nn,space_c,4,FACE_Y+3);n=nn; nn=rand()%7; //随机生成下一块color(nn);draw_dia(nn,space_c,4,FACE_Y+3);while(1){ color(n);draw_dia(n,space_c,x,y);//画出图形if(t==0)t=15000;while(--t){ if(kbhit()!=0)//有输入就跳出break; }if(t==0){if(pd(n,space_c,x+1,y)==1){ draw_kong(n,space_c,x,y);x++; //向下降落}else{for(i=0;i<4;i++){for(j=0;j<4;j++){ if(dia[n][space_c].space[i][j]==1){ face.data[x+i][y+j]=Box;face.color[x+i][y+j]=n;while(xc());}}}return;}}else{ch=getch();switch(ch) //移动{case LEFT: if(pd(n,space_c,x,y-1)==1) //判断是否可以移动{ draw_kong(n,space_c,x,y);y--;}break;case RIGHT: if(pd(n,space_c,x,y+1)==1){ draw_kong(n,space_c,x,y);y++;}break;case DOWN: if(pd(n,space_c,x+1,y)==1){ draw_kong(n,space_c,x,y);x++;}break;case SPACE: if(pd(n,(space_c+1)%4,x+1,y)==1){ draw_kong(n,space_c,x,y);space_c=(space_c+1)%4;}break;case ESC : system("cls");gotoxy(FACE_X/2,FACE_Y);printf("---游戏结束!---\n\n");gotoxy(FACE_X/2+2,FACE_Y);printf("---按任意键退出!---\n");getch();exit(0);break;case 'R':case 'r': main();exit(0);case 'S':case 's': while(1){ if(kbhit()!=0)//有输入就跳出break; }break;}}}
}
int xc()
{int i,j,k,sum;for(i=FACE_X-2;i>4;i--){sum=0;for(j=1;j<FACE_Y-1;j++){sum+=face.data[i][j]; }if(sum==0)break;if(sum==FACE_Y-2) //满一行,减掉{ grade+=100;color(7);gotoxy(FACE_X-4,2*FACE_Y+2);printf("分数:%d",grade);for(j=1;j<FACE_Y-1;j++){face.data[i][j]=Kong;gotoxy(i,2*j);printf(" ");}for(j=i;j>1;j--){ sum=0;for(k=1;k<FACE_Y-1;k++){sum+=face.data[j-1][k]+face.data[j][k];face.data[j][k]=face.data[j-1][k];if(face.data[j][k]==Kong){gotoxy(j,2*k);printf(" ");}else{gotoxy(j,2*k);color(face.color[j][k]);printf("■");}}if(sum==0)return 1;}}}for(i=1;i<FACE_Y-1;i++){if(face.data[1][i]==Box){char n;Sleep(2000); //延时system("cls");color(7);gotoxy(FACE_X/2-2,2*(FACE_Y/3));if(grade>max){printf("恭喜您打破记录,目前最高纪录为:%d",grade);write_file();}else if(grade==max)printf("与纪录持平,请突破你的极限!");elseprintf("请继续努力,你与最高记录只差:%d",max-grade);gotoxy(FACE_X/2,2*(FACE_Y/3));printf("GAME OVER!\n");do{gotoxy(FACE_X/2+2,2*(FACE_Y/3));printf("是否重新开始游戏(y/n): ");scanf("%c",&n);gotoxy(FACE_X/2+4,2*(FACE_Y/3));if(n!='n' && n!='N' && n!='y' && n!='Y')printf("输入错误,请重新输入!");elsebreak;}while(1);if(n=='n' || n=='N'){gotoxy(FACE_X/2+4,2*(FACE_Y/3));printf("按任意键退出游戏!");exit(0);}else if(n=='y' || n=='Y')main();} }return 0;
}
//////////////////////////////////////////////
void read_file() //读取最高记录
{FILE *fp;fp=fopen("俄罗斯方块记录.txt","r+");if(fp==NULL){fp=fopen("俄罗斯方块记录.txt","w+");fwrite(&max,sizeof(int),1,fp);}fseek(fp,0,0);fread(&max,sizeof(int),1,fp);fclose(fp);
}
void write_file() //保存最高记录
{FILE *fp;fp=fopen("俄罗斯方块记录.txt","r+");fwrite(&grade,sizeof(int),1,fp);fclose(fp);
}
///////////////////////////////////////////////
int pd(int n,int space_c,int x,int y) //判断是否到底
{int i,j;for(i=0;i<4;i++){for(j=0;j<4;j++){if(dia[n][space_c].space[i][j]==0)continue;else if(face.data[x+i][y+j]==Wall || face.data[x+i][y+j]==Box)return 0;}}return 1;
}
void draw_kong(int base,int space_c,int x,int y)
{int i,j;for(i=0;i<4;i++){for(j=0;j<4;j++){gotoxy(x+i,2*(y+j));if(dia[base][space_c].space[i][j]==1)printf(" ");}}}
void draw_dia(int base,int space_c,int x,int y)
{int i,j;for(i=0;i<4;i++){for(j=0;j<4;j++){gotoxy(x+i,2*(y+j));if(dia[base][space_c].space[i][j]==1)printf("■");}}
}
void init_dia()
{int i,j,k,z;int tmp[4][4];for(i=0;i<3;i++)dia[0][0].space[1][i]=1;dia[0][0].space[2][1]=1; //土形for(i=1;i<4;i++)dia[1][0].space[i][1]=1;dia[1][0].space[1][2]=1; //L形--1for(i=1;i<4;i++)dia[2][0].space[i][2]=1;dia[2][0].space[1][1]=1; //L形--2for(i=0;i<2;i++){ dia[3][0].space[1][i]=1;dia[3][0].space[2][i+1]=1; //Z形--1dia[4][0].space[1][i+1]=1;dia[4][0].space[2][i]=1;//Z形--2dia[5][0].space[1][i+1]=1;dia[5][0].space[2][i+1]=1;//田字形}for(i=0;i<4;i++)dia[6][0].space[i][2]=1;//1形 //////////////////////////////////基础7个形状for(i=0;i<7;i++){for(z=0;z<3;z++){for(j=0;j<4;j++){for(k=0;k<4;k++){tmp[j][k]=dia[i][z].space[j][k];} }for(j=0;j<4;j++){for(k=0;k<4;k++){dia[i][z+1].space[j][k]=tmp[4-k-1][j];} }}}///////////////////////////////////旋转后的21个形状
}
//////////////////////////////////////
void inter_face()//界面
{ int i,j;for(i=0;i<FACE_X;i++){ for(j=0;j<FACE_Y+10;j++){ if(j==0 || j==FACE_Y-1 || j==FACE_Y+9){ face.data[i][j]=Wall;gotoxy(i,2*j);printf("■");}else if(i==FACE_X-1){ face.data[i][j]=Box;gotoxy(i,2*j);printf("■");}elseface.data[i][j]=Kong;}}gotoxy(FACE_X-18,2*FACE_Y+2);printf("左移:←");gotoxy(FACE_X-16,2*FACE_Y+2);printf("右移:→");gotoxy(FACE_X-14,2*FACE_Y+2);printf("旋转:space");gotoxy(FACE_X-12,2*FACE_Y+2);printf("暂停: S");gotoxy(FACE_X-10,2*FACE_Y+2);printf("退出: ESC");gotoxy(FACE_X-8,2*FACE_Y+2);printf("重新开始:R");gotoxy(FACE_X-6,2*FACE_Y+2);printf("最高纪录:%d",max);gotoxy(FACE_X-4,2*FACE_Y+2);printf("分数:%d",grade);}
//////////////////////////////////////////////////
void gotoxy(int x,int y) //移动坐标
{COORD coord;coord.X=y;coord.Y=x;SetConsoleCursorPosition( GetStdHandle( STD_OUTPUT_HANDLE ), coord );
}
//////////////////////////////////////////////////
void hidden_cursor()//隐藏光标
{HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);CONSOLE_CURSOR_INFO cci;GetConsoleCursorInfo(hOut,&cci);cci.bVisible=0;//赋1为显示,赋0为隐藏SetConsoleCursorInfo(hOut,&cci);
}
int color(int c)
{switch(c){case 0: c=9;break;case 1:case 2: c=12;break;case 3:case 4: c=14;break;case 5: c=10;break;case 6: c=13;break;default: c=7;break;}SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), c); //更改文字颜色return 0;
}






![[4G5G专题-12]:功能-LTE载波聚合CA对空口协议栈的影响概述](https://img-blog.csdnimg.cn/20210119102107107.png)








