C语言—俄罗斯方块(新手向)

下面我记录下我用C语言写俄罗斯方块的方法和思路。
方法是参考b站的教学视频并且进行一定的改进。
这个是用控制台实现的,不需要用到graphics.h头文件, 对各种编译器应该都是兼容的。
原视频链接:https://www.bilibili.com/video/BV1v441157F7from=search&seid=12333251085306036433
下面是我对原代码的分析和改进。

代码思路

数据类型设计:
在这里插入图片描述
就是提前设置好起始的X,Y(不是从(0,0) 开始的)长度宽度,定义好上下左右, 后面用到就很方便;
在这里插入图片描述
关键是:

  1. 用一个结构体表示俄罗斯方块的中心块(不是全部),包含它的坐标x y,类型(1到19),对应的颜色,下一个方块类型 ,
  2. 用一个坐标数组储存每个坐标的状态(0. 空白, 1. 已下落的方块,2.墙壁 ,3. 还在下落的方块
    游戏整体框架:
    主体框架

乍一看好像挺简单的样子。但是实际操作起来。需要主要注意两个模块。
一. 怎么移动俄罗斯方块
写过贪吃蛇的都知道。或者说没有写过应该也知道:
移动就是把旧的一部分擦掉, 把新的打印出来
方块结构体
怎么打印 / 消除当前方块?
这里我们用一个中心方块(一个结构体类型,储存当前坐标的x,y值,当前方块的类型编号)来代表当前的俄罗斯方块。因为每个俄罗斯方块都是由4个小方块组成的,因此我们可以通过他们和中心方块的相对位置来表示。

我用的(其实是视频中的方法)办法:写一个传递函数, 传入中心块结构体地址,把俄罗斯方块全部的19种类型的排列方式都写好对应的坐标赋值为3,就可以按照各种编号打印出方块的整体了。

这里对19种类型说明一下:
在这里插入图片描述
举个栗子,比如:
我们要打印一个田字形:
在这里插入图片描述
中心块坐标已经赋值好了是x= tetris->x, y= tetris->y, 那么根据相对位置:
1号是 x=tetris->x+1; y=tetris->y;
2号的 x=tetris->x; y=tetris->y+1;(向下是y+1)
3号的 x=tetris->x+1; y=tetris->y+1;
我们把它们赋值为sign(是1,或者是0,或者是3)
在这里插入图片描述
19种慢慢写就好了;
然后我们对标记为3的进行打印, 对标记为0的进行消除;
打印就是对这4×4的矩阵遍历一遍, 如果遇到3,那么打印一个小方块’■’;
如图:
在这里插入图片描述

消除同理遍历一遍, 如果遇到0,那么打印一个空格‘ ’。
另外再写这2个函数即可。

二. 怎么判断能否移动

不能移动就代表着:**如果移动了,那么会碰到(或者说重叠)墙壁或者其他方块。**这样子我们可以写一个ifmove函数来判断。
这个函数很长, 我用的是笨办法, 对传入的中心块类型进行对应的判断,
如果有一个值不是0,那么说明不能移动,结构与上面差不多,这里就不赘述了;

虽说还有其他的函数, 但是理解了这两个其他的就很容易上手了。

上代码:*(一些关键的函数说明放在后面)

#include<stdio.h>                         
#include<stdlib.h>                        
#include<time.h>                         
#include<windows.h>                    
#include<conio.h>                       
#define FrameX 13                      
#define FrameY 3                          
#define Frame_width 18             
#define Frame_hight 20                
#define UP    72                           
#define DOWN  80                      
#define LEFT  75                        
#define RIGHT 77                      
#define ESC   27                         
#define SPACE 32                             
int a[80][80]={0}/*存储每个坐标的状态*/,gr=1/*游戏结束标注*/,co[80][80]={0}/*储存对应的颜色*/;                                                 //0 空白, 1 块 2 墙
int speed=200 /*速度*/, score = 0 /*得分*/, highest=0  /*最高得分*/, m=0 /*是否第一个生成的方块*/;
struct Tetris{
	int x;
	int y;
	int flag;                                         //类型序号 
	int color;
	int next;                                           //下一个的类型
};
///
void gotoxy(int x,int y);
void DrawGameframe();
void creat_tetris();
///移动光标
void gotoxy(int x,int y)                                                
{
    COORD coord;
    coord.X=x;
    coord.Y=y;
    SetConsoleCursorPosition( GetStdHandle( STD_OUTPUT_HANDLE ), coord );
}
///改变打印颜色
int color(int c)
{
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), c);        //更改文字颜色
    return 0;
}
///隐藏光标(调用一次就行了)
void hidden_cursor()//隐藏光标
{
  HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
  CONSOLE_CURSOR_INFO cci;
  GetConsoleCursorInfo(hOut,&cci);
  cci.bVisible=0;//赋1为显示,赋0为隐藏
  SetConsoleCursorInfo(hOut,&cci);
} 
///标题
void title(){
	color(11);
	gotoxy(30,2);
	printf("趣 味 俄 罗 斯"); 
	color(14);                             
	gotoxy(18,4);
	printf("■"); 
	gotoxy(18,5);
	printf("■■");
	gotoxy(18,6);
	printf("■");
	
	color(13);
	gotoxy(26,4);
	printf("■■"); 
	gotoxy(28,5);
	printf("■■");
	
	color(12);
	gotoxy(36,4);
	printf("■■"); 
	gotoxy(36,5);
	printf("■■");
	
	color(11);
	gotoxy(44,4);
	printf("■"); 
	gotoxy(44,5);
	printf("■");
	gotoxy(44,6);
	printf("■");
	gotoxy(44,7);
	printf("■");
	
	color(3);
	gotoxy(54,4);
	printf("■"); 
	gotoxy(50,5);
	printf("■■■");
} 
void welcome(){                                             //欢迎界面 
	int i,j=1;
	color(10);
	for(i=15;i<60;i++){
		for(j=8;j<18;j++){
			gotoxy(i,j);
			if(j==8||j==17)printf("=");
			else if(i==15||i==59)printf("||");}}
	gotoxy(26,11);
	color(11);
	printf("1. 开始游戏");
	gotoxy(26,15);
	printf("3. 最高记录");
	gotoxy(41,11);
	printf("2. 游戏说明");
	gotoxy(41,15);
	printf("4. 退出游戏");
	gotoxy(30,19);
	color(13);
	printf("请选择: [ ]\b\b");
}
void initial_frame(){                                             //初始化框架 
	system("cls");
	int i,j;
	for(i=FrameX;i<=FrameX + Frame_width*2 -2;i+=2)
	    for(j=FrameY;j<=FrameY + Frame_hight;j++){
	    	gotoxy(i,j);
	    	if(i==FrameX||i==FrameX + Frame_width*2 -2){
	    		a[i][j]=2;
	    	printf("■");	
			} 
			else if(j==FrameY + Frame_hight){
				a[i][j]=2;
			printf("■"); 	
			}
			else if(j==FrameY){
				printf("■");                   //上界不需要赋值2 
			}
		}
	color(7);
	gotoxy(FrameX+Frame_width*2+3,FrameY + 1);
	printf("左  A / ←右  D / →");
	gotoxy(FrameX+Frame_width*2+3,FrameY + 3);
	printf("旋转   ↑   ");
	gotoxy(FrameX+Frame_width*2+3,FrameY + 5);
	printf("加速  S / ↓");
	gotoxy(FrameX+Frame_width*2+3,FrameY + 7);
	printf("暂停  SPACE ");
	gotoxy(FrameX+Frame_width*2+3,FrameY + 9);
	printf("退出  ESC ");
	color(9);
	gotoxy(FrameX + Frame_width*2 + 3,FrameY+10);                      //分数 
	printf("最高记录 : %d",highest);
	gotoxy(FrameX + Frame_width*2 + 4,FrameY+11);                      //分数 
	printf("SOCRE : %d",score);
	gotoxy(FrameX + Frame_width*2 + 3,FrameY+12);                      //分数 
	printf("当前速度: %d",500-speed);
	gotoxy(FrameX+Frame_width*2+3,FrameY + 13);
	color(4);
	printf("下一个:");
	color(10);
	gotoxy(FrameX+Frame_width*2+3,FrameY + 14);           //next 
	printf("***************");
	gotoxy(FrameX+Frame_width*2+3,FrameY + 20);
	printf("***************");

}
void mark_tetris(struct Tetris *tetris,int sign){                                  //19种情况
    a[tetris->x][tetris->y]=sign;                                                  
	switch(tetris->flag){
		case 1:                                                       /* ■ ■ 
		                                                                 ■ ■      */
        a[tetris->x][tetris->y + 1] = sign;
        a[tetris->x+2][tetris->y + 1] = sign;
        a[tetris->x+2][tetris->y] = sign;
        break;
    case 2:                                                        /*                ■ 
	                                                                             ■ ■ ■         */ 
        a[tetris->x-2][tetris->y] = sign; 
        a[tetris->x+2][tetris->y] = sign;
        a[tetris->x+2][tetris->y-1] = sign;break;
    case 3: 
	    a[tetris->x][tetris->y-1] = sign; 
        a[tetris->x][tetris->y+1] = sign;
        a[tetris->x+2][tetris->y+1] = sign;break;
    case 4:
    	a[tetris->x-2][tetris->y] = sign; 
        a[tetris->x+2][tetris->y] = sign;
        a[tetris->x-2][tetris->y+1] = sign;break;
    case 5:
    	a[tetris->x][tetris->y-1] = sign;
        a[tetris->x][tetris->y+1] = sign;
        a[tetris->x-2][tetris->y-1] = sign;break;
    case 6:                                                      /* ■
	                                                                ■ ■ ■    */ 
        a[tetris->x-2][tetris->y] = sign;
        a[tetris->x+2][tetris->y] = sign;
        a[tetris->x-2][tetris->y-1] = sign;break;
    case 7: 
	    a[tetris->x][tetris->y-1] = sign; 
        a[tetris->x][tetris->y+1] = sign;
        a[tetris->x+2][tetris->y-1] = sign;break;
    case 8:
    	a[tetris->x-2][tetris->y] = sign;
        a[tetris->x+2][tetris->y] = sign;
        a[tetris->x+2][tetris->y+1] = sign;break;
    case 9:
    	a[tetris->x][tetris->y-1] = sign;
        a[tetris->x][tetris->y+1] = sign;
        a[tetris->x-2][tetris->y+1] = sign;break;
    case 10:                                                             /*■ ■ ■ ■ */                                                   
        a[tetris->x-2][tetris->y] = sign;
        a[tetris->x+2][tetris->y] = sign;
        a[tetris->x+4][tetris->y] = sign;break;
    case 11:                                                                                                           
        a[tetris->x][tetris->y-1] = sign;
        a[tetris->x][tetris->y+1] = sign;
        a[tetris->x][tetris->y+2] = sign;break;
    case 12:                                                             /*      ■ ■
	                                                                               ■ ■  */   
        a[tetris->x+2][tetris->y-1] = sign;
        a[tetris->x+2][tetris->y] = sign;
        a[tetris->x][tetris->y+1] = sign;break;
    case 13:                                                              
        a[tetris->x-2][tetris->y] = sign;
        a[tetris->x+2][tetris->y+1] = sign;
        a[tetris->x][tetris->y+1] = sign;break;
    case 14:                                                             /*    ■ ■
	                                                                         ■ ■  */   
        a[tetris->x+2][tetris->y] = sign;
        a[tetris->x+2][tetris->y+1] = sign;
        a[tetris->x][tetris->y-1] = sign;break; 
    case 15:                                                             
        a[tetris->x+2][tetris->y] = sign;
        a[tetris->x-2][tetris->y+1] = sign;
        a[tetris->x][tetris->y+1] = sign;break; 
    case 16:                                                        /*          ■
	                                                                          ■ ■ ■  */   
        a[tetris->x][tetris->y-1] = sign;
        a[tetris->x+2][tetris->y] = sign;
        a[tetris->x-2][tetris->y] = sign;break;
    case 17:
        a[tetris->x][tetris->y-1] = sign;
        a[tetris->x][tetris->y+1] = sign;
        a[tetris->x+2][tetris->y] = sign;break;
    case 18:                                                       
        a[tetris->x][tetris->y+1] = sign;
        a[tetris->x+2][tetris->y] = sign;
        a[tetris->x-2][tetris->y] = sign;break; 
    case 19:
        a[tetris->x][tetris->y-1] = sign;
        a[tetris->x][tetris->y+1] = sign;
        a[tetris->x-2][tetris->y] = sign;break;
	}
}
void print_tetris(struct Tetris *tetris){
    int i,j;
    color(tetris->color); 
    for(i=tetris->x-2;i<=tetris->x+4;i+=2)
        for(j=tetris->y-1;j<=tetris->y+2;j++){
        	if(a[i][j]==3&&j>=FrameY+1){
        		gotoxy(i,j);
        		co[i][j]=tetris->color;                      //颜色数组 
        		printf("■");  
			}
		}
		gotoxy(0,FrameY+Frame_hight+1);
}
int  ifmove(struct Tetris *tetris){                                   //按照视频的思路
    if(tetris->y>=FrameY+Frame_hight||tetris->x<=FrameX||tetris->x>=FrameX+Frame_width*2-2||a[tetris->x][tetris->y]!=0)
	return 0; 
	switch(tetris->flag){
	case 1:                                                           /* ■ ■ 
		                                                                 ■ ■      */
        if(a[tetris->x][tetris->y + 1] == 0&&
        a[tetris->x+2][tetris->y + 1] ==0&&
        a[tetris->x+2][tetris->y] ==0)return 1;break;
    case 2:                                                        /*                ■ 
	                                                                             ■ ■ ■         */ 
        if(a[tetris->x-2][tetris->y] ==0&& 
        a[tetris->x+2][tetris->y] ==0&&
        a[tetris->x+2][tetris->y-1] ==0)return 1;break;
    case 3: 
	    if(a[tetris->x][tetris->y-1]==0&&
        a[tetris->x][tetris->y+1]==0&&
        a[tetris->x+2][tetris->y+1]==0)return 1;break;
    case 4:
    	if(a[tetris->x-2][tetris->y]==0&&
        a[tetris->x+2][tetris->y]==0&&
        a[tetris->x-2][tetris->y+1]==0)return 1;break;
    case 5:
    	if(a[tetris->x][tetris->y-1] ==0&&
        a[tetris->x][tetris->y+1]==0&&
        a[tetris->x-2][tetris->y-1] ==0)return 1;break;
    case 6:                                                      /* ■
	                                                                ■ ■ ■    */                                                     
        if(a[tetris->x-2][tetris->y]==0&&
        a[tetris->x+2][tetris->y] ==0&&
        a[tetris->x-2][tetris->y-1]==0)return 1;break;
    case 7: 
	    if(a[tetris->x][tetris->y-1]==0&& 
        a[tetris->x][tetris->y+1]==0&&
        a[tetris->x+2][tetris->y-1]==0)return 1;break;
    case 8:
    	if(a[tetris->x-2][tetris->y] ==0&& 
        a[tetris->x+2][tetris->y]==0&&
        a[tetris->x+2][tetris->y+1]==0)return 1;break;
    case 9:
    	if(a[tetris->x][tetris->y-1]==0&&
        a[tetris->x][tetris->y+1]==0&&
        a[tetris->x-2][tetris->y+1]==0)return 1;break;
    case 10:                                                             /*■ ■ ■ ■ */                                                   
        if(a[tetris->x-2][tetris->y]==0&&
        a[tetris->x+2][tetris->y]==0&&
        a[tetris->x+4][tetris->y]==0)return 1;break;
    case 11:                                                                                                           
        if(a[tetris->x][tetris->y-1]==0&&
        a[tetris->x][tetris->y+1]==0&&
        a[tetris->x][tetris->y+2]==0)return 1;break;
    case 12:                                                             /*     ■ ■
	                                                                               ■ ■  */   
        if(a[tetris->x+2][tetris->y-1]==0&&
        a[tetris->x+2][tetris->y]==0&&
        a[tetris->x][tetris->y+1]==0)return 1;break;
    case 13:                                                              
        if(a[tetris->x-2][tetris->y]==0&&
        a[tetris->x+2][tetris->y+1]==0&&
        a[tetris->x][tetris->y+1]==0)return 1;break;
    case 14:                                                             /*    ■ ■
	                                                                        ■ ■  */   
        if(a[tetris->x+2][tetris->y]==0&&
        a[tetris->x+2][tetris->y+1]==0&&
        a[tetris->x][tetris->y-1]==0)return 1;break; 
    case 15:                                                             
        if(a[tetris->x+2][tetris->y]==0&&
        a[tetris->x-2][tetris->y+1]==0&&
        a[tetris->x][tetris->y+1]==0)return 1;break;         
    case 16:                                                        /*        ■
	                                                                       ■ ■ ■  */   
        if(a[tetris->x][tetris->y-1]==0&&
        a[tetris->x+2][tetris->y]==0&&
        a[tetris->x-2][tetris->y]==0)return 1;break;
    case 17:
        if(a[tetris->x][tetris->y-1]==0&&
        a[tetris->x][tetris->y+1]==0&&
        a[tetris->x+2][tetris->y]==0)return 1;break;
    case 18:                                                       
        if(a[tetris->x][tetris->y+1]==0&&
        a[tetris->x+2][tetris->y]==0&&
        a[tetris->x-2][tetris->y]==0)return 1;break; 
    case 19:
        if(a[tetris->x][tetris->y-1]==0&&
        a[tetris->x][tetris->y+1]==0&&
        a[tetris->x-2][tetris->y]==0)return 1;break;
	}return 0;
}
void creat_tetris(struct Tetris *tetris){                                     //产生新的方块 
	int i,j;
	if(m++==0)tetris->flag =rand()%19+1;                        //19种
	else tetris->flag=tetris->next;
	tetris->next =rand()%19+1;                        //下一个 
  	tetris->color=rand()%15+1; 
	tetris->x=FrameX + Frame_width;
	tetris->y=FrameY + 1;
	if(!ifmove(tetris))gr=0;                   //游戏结束
	else mark_tetris(tetris,3) ;                      //这些方块已经标记了 3 
}
void clean_tetris(struct Tetris *tetris){                                  //消除原位置方块 
	int i,j;
    for(i=tetris->x-2;i<=tetris->x+4;i+=2)
        for(j=tetris->y-1;j<=tetris->y+2;j++){
        	if(a[i][j]==0&&j>=FrameY+1){
        		gotoxy(i,j);
        		co[i][j]=0;                                   //颜色改变 
        		printf("  ");          //看情况1个空格或两个
			}
		}
}
void change_flag(struct Tetris *tetris){                                      //旋转 
	mark_tetris(tetris,0);
	int X=tetris->x,Y=tetris->y,Flag=tetris->flag;
	clean_tetris(tetris);
	switch(tetris->flag){
	    case 5:case 9:case 19:tetris->flag-=3;break;
	    case 11:case 13:case 15:tetris->flag--;break;
	    case 1:break; 
		default:tetris->flag++;break;
	}
	if(ifmove(tetris)){}
    else{
		tetris->x=X;
		tetris->y=Y;
		tetris->flag=Flag;                         //类型要换回来
	}
	mark_tetris(tetris,3);
    print_tetris(tetris);
	
}
void print_next(struct Tetris *tetris,int sign){                           //打印下一个 
	Tetris r,*q=&r;
	q->flag=tetris->next;
	q->x=FrameX + Frame_width*2+7;
	q->y=FrameY + 16;
	if(sign!=0){
		mark_tetris(q,3);
		print_tetris(q);
	}
	else{
	    mark_tetris(q,0);
		clean_tetris(q);
	} 
}
void fullline(){                                               //消除满行, 假装没有bug 
    int i,j,k,l,sign=0;
	for(j= FrameY + Frame_hight -1; j >= FrameY+1 ;j--){
		sign=0;
		for(i=FrameX+2;i<=Frame_width*2+FrameX-4;i+=2){               //x坐标
		    if(a[i][j]==0) sign=1;                                   //不能消行 
		}
		if(sign==0){
			for(k=FrameX+2;k<=Frame_width*2+FrameX-4;k+=2){
				gotoxy(k,j);
				a[k][j]=0;
				co[k][j]=0;
				printf("  ");
			}
			for(l=j-1;l>=FrameY + 1;l--)
			    for(k=FrameX+2;k<=Frame_width*2+FrameX-4;k+=2){
				    if(a[k][l]==1&&l+1!=FrameY+Frame_hight){             //可以下移 
				    	gotoxy(k,l);
				    	a[k][l]=0;
				    	printf("  "); //因为方块占有两个字符(看情况)
				    	color(co[k][l]);
				    	gotoxy(k,l+1);
				    	co[k][l]=co[k][l-1];
				    	printf("■");                               
						a[k][l+1]=1; 
					}
			}
			j++;
			gotoxy(FrameX + Frame_width*2 + 12,FrameY+11); 
			color(12);
			printf("%d",score+=100);
			if(score%100==3)speed-=100;
			gotoxy(FrameX + Frame_width*2 + 13,FrameY+12);                      //分数 
	        printf("%d",500-speed);
		}
	}
}
int preservation(){                                           //保存记录 
	FILE *fp;
	if((fp=fopen("D:\\els_record.txt","rb"))!=NULL){                         //用wb+会删掉原数据?? 
	fscanf(fp,"%d",&highest);                   //读出原记录 
	fclose(fp);}
	if(score <= highest)return 0;
	else {
	fp=fopen("D:\\els_record.txt","wb+");	
    fprintf(fp,"%d",score);                      //写入新纪录 
	highest = score;
	fclose(fp);	
	}
	return 1; 
}
void startgame(){                                 //开始游戏 
	gr=1;score=0;speed=200,m=0;
	int i,j;
	for(i=0;i<80;i++)
	    for(j=0;j<80;j++){                                   //重新初始化 ,第一次不用 
		a[i][j]=0;co[i][j]=1;
	}
	struct Tetris t,*tetris=&t;                             
	int X,Y,A,B;
	char ch;
	initial_frame();
	creat_tetris(tetris);
	print_tetris(tetris);
	print_next(tetris,0);                             //清除原来的next  
	print_next(tetris,1);
	while(1)
    {
	if(kbhit()){
	    mark_tetris(tetris,0);                         //一定要先置为0 
		A=tetris->x;B=tetris->y;X=tetris->x;
		ch=getch();
		switch(ch){
		    case UP   :case 'w': change_flag(tetris);Y=tetris->y;                               break;
		    case DOWN :case 's': Y=(tetris->y+4 < FrameY+Frame_hight?tetris->y = FrameY+Frame_hight-3:tetris->y++);break;
            case LEFT :case 'a': X=tetris->x-=2;Y=tetris->y;                                     break;                                    //不知道开始为什么用不了上下左右啊 
		    case RIGHT:case 'd': X=tetris->x+=2;Y=tetris->y;                                    break;
		    case ESC  :gr=0;break;
		    case SPACE:fflush(stdin);
			gotoxy(FrameX+Frame_width-3,FrameY-1);
         	printf("已经暂停");getchar();
			gotoxy(FrameX+Frame_width-3,FrameY-1);
         	printf("        ");break;                           //懒得再写函数了 
            default :Y=tetris->y; break;
		}                
		if(ifmove(tetris)){                            //如果可以的话就移动
		    tetris->x=A;tetris->y=B;                   //不忘初位 
		    mark_tetris(tetris,0);                     //保证旋转后也要置为0 
			clean_tetris(tetris);
		    tetris->x=X;tetris->y=Y;		
		    mark_tetris(tetris,3);
            print_tetris(tetris);   
		}
		else{                                          //不可以的话就回去 
		    tetris->x=A;
			tetris->y=B;
		}
	}
	else                                     //只能下落 
	{
        mark_tetris(tetris,0);
        if(tetris->y++,ifmove(tetris)){      //要置为0才能用ifmove() 
        tetris->y--;
		clean_tetris(tetris);
		tetris->y++;		
		mark_tetris(tetris,3);
        print_tetris(tetris);   
	    }
		else{                               //不能下落呢 
		tetris->y--;
		mark_tetris(tetris,1);              //已经到头了, 标记为 1 
		fullline();	 
		print_next(tetris,0);               //清除原来的next  
		creat_tetris(tetris);
		print_next(tetris,1);               //打印现在的
		}   
	}Sleep(speed);
	if(gr==0)break;
	}
	fflush(stdin);
	gotoxy(FrameX+Frame_width-3,FrameY+10);
	printf("GAMEOVER!");
	preservation();
	getch();
	gotoxy(0,FrameY+Frame_hight);
}
void game_explain(){
	system("cls");
	title();
	int i,j;
	color(13);
	for(i=15;i<60;i++){
		for(j=8;j<18;j++){
			gotoxy(i,j);
			if(j==8||j==17)printf("=");
			else if(i==15||i==59)printf("||");}}
	color(9);
	gotoxy(FrameX+Frame_width-8,FrameY + 6);
	printf("1. 左 右 上 或  A  D S 移动/旋转方块");
	gotoxy(FrameX+Frame_width-8,FrameY + 8);
	printf("2. [空格键]暂停, [ESC]键退出");
	gotoxy(FrameX+Frame_width-8,FrameY + 10);
	printf("3. 消除越多, 得分越高噢");
	gotoxy(FrameX+Frame_width-8,FrameY + 12);
	printf("4. 每行填满方块即可消除");
	gotoxy(30,19);
	color(13);
	fflush(stdin);
	printf("[任意键继续]");
	getch();
}
void game_record(){
	gotoxy(FrameX+Frame_width,FrameY+9);
	printf("最高记录: %d",highest);
	gotoxy(FrameX+Frame_width,FrameY+11);
	printf("[按任意键继续]");
	fflush(stdin);
	getch(); 
}
main(){
	int k;
	srand((unsigned)time(NULL));
	hidden_cursor(); 
	label:{
	title();
	welcome();
	preservation();
    scanf("%d",&k);
	while(k!=4){
	switch(k){
    case 1: startgame();break;	
    case 2: game_explain();break;
    case 3: game_record();break;
    default: break; 
	}
	system("cls");
	title();
	welcome();
	fflush(stdin);
    scanf("%d",&k);
	}}
	printf("                          确认离开[N/Y]:[ ]\b\b");
	fflush(stdin);
	char ch=getchar();
	if(ch=='n'||'N')goto label;
}

几个关键函数(我觉得):
主菜单和游戏边界的话,视频上讲的挺清楚了, 大不了就若干个printf进行调试,需要注意的是每个方块占用2个宽度;
1. 光标移动函数gotoxy():
传递xy坐标就可以把光标移动到那里了;
横向是x,纵向是y,都从0开始,逐行递增;
2. 颜色改变函数color();
输入一个数(1到16)改变字符颜色;
3. 隐藏光标hidden_cursor();
没什么好说的,调用一次就行了;
4. 标记函数 mark_print();
这个函数要传递指针和一个整型sign(可取0,1,3)
函数的作用就是把当前的方块坐标全部赋值为sign;
5. 打印/消除函数
双重循环判断是不是3 / 0;
如果是的话就打印 方块/ 消除(打印空格);
6. 旋转函数change_flag();
先用X,Y储存好原来的坐标(避免失败无法恢复)
然后根据19种情况,加啊,减啊;
然后判断能否旋转,可以的话消除原来的, 打印现在的;
如果不能,就赋值回X,Y,假装没事发生,结束函数;
7. 消除满行函数 fullline();
这个不用传递结构体指针;
用两层循环, 从下到上, 从左到右判断是否有坐标为0(注意x坐标每次加2)
如果没有为0的, 就可以消行了;
消行的操作就是:
先把当前行全部打印空白并且全部赋值0;
再用两层循环, 一个从当前行+1向上循环,一个从左往右:
如果坐标为1,那它下面的坐标赋值1,当前的赋值0,消除, 打印;如此反复;
颜色也要另外改变, 可以保证消除没问题再改;
对了, 消除完一行一定要回到当前行(j++或者j–), 不然如果要消除两行就会忽略一行;

**可能遇到的问题:
1. 颜色同化
每次打印赋值3, 不要都赋值1, 这样原来是1的也会再打印一遍
2.怎么显示下一个方块:
提前生成下一个方块的类型(甚至是颜色),下次生成就读取上次的就好了
3. 穿透bug:
要么是19种排列方式没写对,就是忘记赋值1或者3/0;

  • 31
    点赞
  • 201
    收藏
    觉得还不错? 一键收藏
  • 14
    评论
很抱歉,我无法提供完整的C语言俄罗斯方块游戏代码。但是,我可以给你一些关于C语言俄罗斯方块游戏代码的思路和方法。 在C语言中实现俄罗斯方块游戏,你可以使用控制台来显示游戏界面和方块。以下是一些实现俄罗斯方块游戏的基本步骤和思路: 1. 定义方块的形状和类型:你可以使用二维数组来表示不同类型的方块,每个方块由4个小方块组成。可以使用数字或字符来表示方块的形状。 2. 初始化游戏界面:使用二维数组来表示游戏界面,每个元素代表一个方块的状态(是否被占据)。可以使用空字符或特殊字符来表示空白位置和已占据位置。 3. 生成新的方块:随机选择一个方块类型,并将其放置在游戏界面的顶部中央位置。 4. 移动方块:根据用户的输入(例如按下键盘上的方向键),移动当前方块的位置。可以通过改变方块的坐标来实现移动。 5. 碰撞检测:在移动方块之前,检查方块是否与已占据的位置或游戏界面的边界发生碰撞。如果发生碰撞,则停止移动方块。 6. 方块固定和消除:当方块无法继续下落时,将方块固定在游戏界面上,并检查是否有完整的行。如果有完整的行,则将其消除,并更新游戏界面。 7. 游戏结束判断:当方块无法放置在游戏界面的顶部中央位置时,游戏结束。 以上是实现俄罗斯方块游戏的基本思路和步骤。你可以根据这些思路来编写自己的C语言俄罗斯方块游戏代码。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值