俄罗斯方块—C语言

xiaoxiao2021-02-28  77

思路: 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("与纪录持平,请突破你的极限!"); else printf("请继续努力,你与最高记录只差:%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("输入错误,请重新输入!"); else break; }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形--1 for(i=1;i<4;i++) dia[2][0].space[i][2]=1; dia[2][0].space[1][1]=1; //L形--2 for(i=0;i<2;i++) { dia[3][0].space[1][i]=1; dia[3][0].space[2][i+1]=1; //Z形--1 dia[4][0].space[1][i+1]=1; dia[4][0].space[2][i]=1;//Z形--2 dia[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("■"); } else face.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; }
转载请注明原文地址: https://www.6miu.com/read-62091.html

最新回复(0)