俄罗斯方块纯C语言

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/weixin_40756041/article/details/78354180

俄罗斯方块- 源码文件 - 点击下载

说明:本程序使用DEV即可编译
效果截图:

my-tetris.c

#include <stdio.h>
#include <windows.h>
#include <time.h>

//常量定义区
#define M_X 100//定义地图的最大宽度
#define M_Y 100//定义地图的最大高度

//全局变量定义区
int i,j;//for循环专用变量 
int m[M_X][M_Y];//定义最大地图数组
int X;//使用宽度
int Y;//使用高度 
int Wx;//方块头实时位置
int Wy;//方块头实时位置
int Ox;//方块头实时上一次位置
int Oy;//方块头实时上一次位置
int R[4][2];//方块体实时位置
int T;//方块体实时颜色
int E,C;//方块体实时形状
int ch;//按键信息
int Z;//碰撞标志
int F;//得分
int J;//是否开启数据记录 
clock_t s_t_1, s_t_2;

#include "my-tetris-3.h"
#include "my-tetris-2.h"
#include "my-tetris-1.h"

//程序运行函数 
int run(){
	set_cursor(0);//设置光标,flg=1:显示光标 flg=0:隐藏光标
	hollo();//介绍
	f_sz_m();//地图数组初始化
	f_R();//初始化R数组
	f_d();//初始化data
	f_bl();//变量初始化
	s_gk();//设置使用高度和宽度
	s_j();//设置是否开启数据记录 
	r_gk();//将高度和宽度写入地图 
	r_d();//将地图记录进data
	d_m();//打印地图
	s_m();//游戏说明 
	int a=1;
	srand((unsigned)time(NULL ));// 设置随机种子
	while(1){
		if(f_d_fx()){return 1;}//方块起始开始
		while(1){
			change(2);//更改
			s_t_1=clock();//计时
			while(1){
				set_cocate(0,Y);
				set_color(15,0);
				printf("                                "); 
				ch=0; 
				if(kbhit()){
					switch(ch=getch()){//获取用户按下的按键 
						case 0xE0:switch(ch=getch()){//分析按键 
							case 72:change(1);break;
							case 80:change(2);break;
							case 75:change(3);break;
							case 77:change(4);break;
							default:break;
						}
						break;
						case 32:command(2);break;
						default:break;
					}
				}
				s_t_2=clock();//计时
				if(s_t_2-s_t_1>1000-F/2){change(2);s_t_1=clock();} 
				if(Z){break;}
			}
			if(Z){break;}
		}
		c_h();//检测是否成行 
	}
	return 0;
}

void main(){
	int a;
	while(1){
		if(run()){
			command(2); 
			command(1); 
			printf("游戏结束\n"); 
			printf("重新开始请按1,结束请按0\n");
			if(input_int(0,1)!=1){break;}
		}
	}
}

my-tetris-1.h

//程序运行主文件

//将地图记录进data 
void r_d(){
	if(J){
		FILE *fp;
		int i,j;
		fp=fopen("data.txt","a");
		for(i=0;i<X;i++){
			fprintf(fp,"|");
			for(j=0;j<Y;j++){
				fprintf(fp,"%3d|",m[i][j]);
			}
			fprintf(fp,"\n");
		}	
		fprintf(fp,"\n");
		fclose(fp);
	}
}
//设置是否开启数据记录 
void s_j(){
	printf("是否开启数据记录 0=否 1=是 \n");
	J=input_int(0,1);
}
//设置使用高度和宽度
void s_gk(){
	printf("宽度设置,建议20 ");
	X=input_int(10,100);
	printf("高度设置,建议20 ");
	Y=input_int(15,100);
}
//将高度和宽度写入地图 
void r_gk(){
	for(i=0;i<X;i++){
		for(j=0;j<Y;j++){
			if(i==0||i==X-1||j==Y-1){
				m[i][j]=20;
			} 
		}
	}
}
//打印地图 
void d_m(){
	command(1);
	set_color(15,0);
	for(i=0;i<X;i++){
		for(j=0;j<Y;j++){
			if(m[i][j]==20){
				set_cocate(i,j);
				printf("■");
			}
		}
	}
}
//设置R数组
void s_R(int a,int b,int c,int d,int e,int f,int g,int h){
	R[0][0]=a;R[0][1]=b;
	R[1][0]=c;R[1][1]=d;
	R[2][0]=e;R[2][1]=f;
	R[3][0]=g;R[3][1]=h;
} 
//设置W
void s_W(int a,int b){
	Ox=Wx;Oy=Wy;
	if(a<1){a=1;}
	if(E==1){if(a>X-5){a=X-5;}}
	if(E==2){if(a>X-2){a=X-2;}}
	if(E==3||E==5||E==7||E==9||E==11||E==13||E==15||E==17){if(a>X-4){a=X-4;}}
	if(E==4||E==6||E==8||E==10||E==12||E==14||E==16||E==18||E==19){if(a>X-3){a=X-3;}}
	Wx=a;Wy=b;
} 
//方块设置
/* 
| 1       | 2       | 3       | 4       | 5       | 6       | 7       | 8       | 9       | 10      | 
| ■■■■| ■□□□| ■□□□| ■■□□| ■■■□| □■□□| □□■□| ■□□□| ■■■□| ■■□□| 
| □□□□| ■□□□| ■■■□| ■□□□| □□■□| □■□□| ■■■□| ■□□□| ■□□□| □■□□|
| □□□□| ■□□□| □□□□| ■□□□| □□□□| ■■□□| □□□□| ■■□□| □□□□| □■□□|
| □□□□| ■□□□| □□□□| □□□□| □□□□| □□□□| □□□□| □□□□| □□□□| □□□□|
| 11      | 12      | 13      | 14      | 15      | 16      | 17      | 18      | 19      | 20      |
| □■□□| ■□□□| ■■■□| □■□□| ■■□□| □■□□| □■■□| ■□□□| ■■□□| □□□□|
| ■■■□| ■■□□| □■□□| ■■□□| □■■□| ■■□□| ■■□□| ■■□□| ■■□□| □□□□|
| □□□□| ■□□□| □□□□| □■□□| □□□□| ■□□□| □□□□| □■□□| □□□□| □□□□|
| □□□□| □□□□| □□□□| □□□□| □□□□| □□□□| □□□□| □□□□| □□□□| □□□□|
Wx,Wy   Wx+1,Wy   Wx+2,Wy   Wx+3,Wy
Wx,Wy+1 Wx+1,Wy+1 Wx+2,Wy+1 Wx+3,Wy+1
Wx,Wy+2 Wx+1,Wy+2 Wx+2,Wy+2 Wx+3,Wy+2
Wx,Wy+3 Wx+1,Wy+3 Wx+2,Wy+3 Wx+3,Wy+3
*/
void s_fk(int a){
	switch(a){
		case 1 :s_R(Wx,Wy,  Wx+1,Wy,  Wx+2,Wy,  Wx+3,Wy  );break;
		case 2 :s_R(Wx,Wy,  Wx,Wy+1,  Wx,Wy+2,  Wx,Wy+3  );break;
		case 3 :s_R(Wx,Wy,  Wx,Wy+1,  Wx+1,Wy+1,Wx+2,Wy+1);break;
		case 4 :s_R(Wx,Wy,  Wx+1,Wy,  Wx,Wy+1,  Wx,Wy+2  );break;
		case 5 :s_R(Wx,Wy,  Wx+1,Wy,  Wx+2,Wy,  Wx+2,Wy+1);break;
		case 6 :s_R(Wx+1,Wy,Wx+1,Wy+1,Wx,Wy+2,  Wx+1,Wy+2);break;
		case 7 :s_R(Wx+2,Wy,Wx,Wy+1,  Wx+1,Wy+1,Wx+2,Wy+1);break;
		case 8 :s_R(Wx,Wy,  Wx,Wy+1,  Wx,Wy+2,  Wx+1,Wy+2);break;
		case 9 :s_R(Wx,Wy,  Wx+1,Wy,  Wx+2,Wy,  Wx,Wy+1  );break;
		case 10:s_R(Wx,Wy,  Wx+1,Wy,  Wx+1,Wy+1,Wx+1,Wy+2);break;
		case 11:s_R(Wx+1,Wy,Wx,Wy+1,  Wx+1,Wy+1,Wx+2,Wy+1);break;
		case 12:s_R(Wx,Wy,  Wx,Wy+1,  Wx+1,Wy+1,Wx,Wy+2  );break;
		case 13:s_R(Wx,Wy,  Wx+1,Wy,  Wx+2,Wy,  Wx+1,Wy+1);break;
		case 14:s_R(Wx+1,Wy,Wx,Wy+1,  Wx+1,Wy+1,Wx+1,Wy+2);break;
		case 15:s_R(Wx,Wy,  Wx+1,Wy,  Wx+1,Wy+1,Wx+2,Wy+1);break;
		case 16:s_R(Wx+1,Wy,Wx,Wy+1,  Wx+1,Wy+1,Wx,Wy+2  );break;
		case 17:s_R(Wx+1,Wy,Wx+2,Wy,  Wx,Wy+1,  Wx+1,Wy+1);break;
		case 18:s_R(Wx,Wy,  Wx,Wy+1,  Wx+1,Wy+1,Wx+1,Wy+2);break;
		case 19:s_R(Wx,Wy,  Wx+1,Wy,  Wx,Wy+1,  Wx+1,Wy+1);break;
		default:break;
	} 
}
//将方块位置记录进地图 
void r_fk_t_m(int a){
	for(i=0;i<4;i++){
		if(a){m[R[i][0]][R[i][1]]=E;}
		else{m[R[i][0]][R[i][1]]=0;}
	} 	
} 
//显示方块 1=显示 0清除 
void d_fk(int a){
	if(a){
		if(E==1||E==2){set_color(8,0);}
		if(E==3||E==4||E==5||E==6){set_color(9,0);}
		if(E==7||E==8||E==9||E==10){set_color(10,0);}
		if(E==11||E==12||E==13||E==14){set_color(11,0);}
		if(E==15||E==16){set_color(12,0);}
		if(E==17||E==18){set_color(13,0);}
		if(E==19){set_color(14,0);}
	}
	else{
		set_color(0,0);
	}
	r_fk_t_m(a);//将方块位置记录进地图
	for(i=0;i<4;i++){
		set_cocate(R[i][0],R[i][1]);
		printf("■");
	}
}
//方块起始开始 
int f_d_fx(){
	Z=0;
	E=C;//方块形状设置
	Wx=X+1;Wy=5; //设置位置
	s_fk(C);//方块设置
	d_fk(0);//显示方块
	C=0;
	while(!C){C=rand()%20;}//方块形状设置
	Wx=X+1;Wy=5; //设置位置
	s_fk(C);//方块设置
	if(C==1||C==2){set_color(8,0);}
	if(C==3||C==4||C==5||C==6){set_color(9,0);}
	if(C==7||C==8||C==9||C==10){set_color(10,0);}
	if(C==11||C==12||C==13||C==14){set_color(11,0);}
	if(C==15||C==16){set_color(12,0);}
	if(C==17||C==18){set_color(13,0);}
	if(C==19){set_color(14,0);}
	for(i=0;i<4;i++){
		set_cocate(R[i][0],R[i][1]);
		printf("■");
	}
	set_cocate(X+1,4);
	set_color(15,0);
	printf("下一个方块");
	s_W(X/2-2,0);//设置起始位置 
	s_fk(E);//方块设置
	if(c_pz()){return 1;}
	d_fk(1);//显示方块
	r_d();//将地图记录进data
	usleep(100000);
	d_fk(0);//显示方块
	return 0;
}
//碰撞检测
int c_pz(){
	for(i=0;i<4;i++){
		if(m[R[i][0]][R[i][1]]!=0){return 1;}
	}
	return 0;
}
//方块旋转 
void chang1(){
	switch(E){
		case 1 :E=2;break;
		case 2 :E=1;break;
		case 3 :E=4;break;
		case 4 :E=5;break;
		case 5 :E=6;break;
		case 6 :E=3;break;
		case 7 :E=8;break;
		case 8 :E=9;break;
		case 9 :E=10;break;
		case 10:E=7;break;
		case 11:E=12;break;
		case 12:E=13;break;
		case 13:E=14;break;
		case 14:E=11;break;
		case 15:E=16;break;
		case 16:E=15;break;
		case 17:E=18;break;
		case 18:E=17;break;
		case 19:E=19;break;
		default:break;
	}
}
//方块旋转 
void chang2(){
	switch(E){
		case 2 :E=1;break;
		case 1 :E=2;break;
		case 4 :E=2;break;
		case 5 :E=4;break;
		case 6 :E=5;break;
		case 3 :E=6;break;
		case 8 :E=7;break;
		case 9 :E=8;break;
		case 10:E=9;break;
		case 7:E=10;break;
		case 12:E=11;break;
		case 13:E=12;break;
		case 14:E=13;break;
		case 11:E=14;break;
		case 16:E=15;break;
		case 15:E=16;break;
		case 18:E=17;break;
		case 17:E=18;break;
		case 19:E=19;break;
		default:break;
	}
}
//更改 
void change(int a){
	d_fk(0);//显示方块
	switch(a){
		case 1 :chang1();break;
		case 2 :s_W(Wx,Wy+1);break;
		case 3 :s_W(Wx-1,Wy);break;
		case 4 :s_W(Wx+1,Wy);break;
		default:break;
	}
	s_fk(E);//方块设置
	if(c_pz()){//碰撞检测
		if(a==2){
			Z=1;//碰撞标志
		}
		if(a==1){
			chang2();
			s_W(Wx,Wy);//设置位置
			s_fk(E);//方块设置
		}
		else{
			s_W(Ox,Oy);//设置位置
			s_fk(E);//方块设置
		}
	} 
	d_fk(1);//显示方块
	r_d();//将地图记录进data
}
//检测是否成行 
void c_h(){
	int a;
	int k;
	for(j=1;j<Y-1;j++){
		a=0;
		for(i=1;i<X-1;i++){
			if(m[i][j]!=0){
				a++;
			}
		}
		if(a==X-2){
			for(k=j;k>1;k--){
				for(i=1;i<X-1;i++){
					m[i][k]=0;
					m[i][k]=m[i][k-1];
					if(m[i][k]==1||m[i][k]==2){set_color(8,0);}
					if(m[i][k]==3||m[i][k]==4||m[i][k]==5||m[i][k]==6){set_color(9,0);}
					if(m[i][k]==7||m[i][k]==8||m[i][k]==9||m[i][k]==10){set_color(10,0);}
					if(m[i][k]==11||m[i][k]==12||m[i][k]==13||m[i][k]==14){set_color(11,0);}
					if(m[i][k]==15||m[i][k]==16){set_color(12,0);}
					if(m[i][k]==17||m[i][k]==18){set_color(13,0);}
					if(m[i][k]==19){set_color(14,0);}
					if(m[i][k]==0){set_color(0,0);}
					set_cocate(i,k);
					printf("■");
				}
			}
			F+=X-2;
			set_cocate(X+1,2);
			set_color(12,0);
			printf("分数:%4d",F);
			set_cocate(X+1,3);
			set_color(14,0);
			printf("速度:%4d",1000-F/2);
		}
	}
}
//介绍
void hollo(){
	set_color(12,0);
	printf("########################################\n");
	printf("#Created At:20170906                   #\n");
	printf("#Algorithm Gossip:tetris               #\n");
	printf("#Developer:wunanhui                    #\n");
	printf("#Referenced By:http://www.wunanhui.wang#\n");
	printf("########################################\n");
	set_color(15,0);
	printf("游戏规则\n");
	printf("由小方块组成的不同形状的板块陆续从屏幕上\n");
	printf("方落下来,玩家通过调整板块的位置和方向,\n");
	printf("使它们在屏幕底部拼出完整的一条或几条。这\n");
	printf("些完整的横条会随即消失,给新落下来的板块\n");
	printf("腾出空间,与此同时,玩家得到分数奖励。没\n");
	printf("有被消除掉的方块不断堆积起来,一旦堆到屏\n");
	printf("幕顶端,玩家便告输,游戏结束。\n");
	printf("\n");
}
//游戏说明
void s_m(){
	set_color(15,0);
	set_cocate(X+1,0);
	printf("Designer:wnh");
	set_cocate(X+1,9);
	printf("游戏说明");
	set_cocate(X+1,10);
	printf("↑:旋转");
	set_cocate(X+1,11);
	printf("←:左移");
	set_cocate(X+1,12);
	printf("→:右移");
	set_cocate(X+1,13);
	printf("↓:下移");
	set_cocate(X+1,14);
	printf("空格:暂停");
	set_cocate(X+1,2);
	set_color(12,0);
	printf("分数:%4d",F);
	set_cocate(X+1,3);
	set_color(14,0);
	printf("速度:%4d",1000-F/2);
} 

my-tetris-2.h

//变量初始化头文件

//变量初始化
void f_bl(){
	X=0;//使用宽度
	Y=0;//使用高度 
	Wx=0;//方块头实时位置
	Wy=0;//方块头实时位置
	T=0;//方块体实时颜色
	E=0;//方块体实时形状
	Ox=0;//方块头实时上一次位置
	Oy=0;//方块头实时上一次位置
	Z=0;//碰撞标志 
	s_t_1=s_t_2=0;
	F=0;
	C=1;
	J=0; 
}
//地图数组初始化
void f_sz_m(){
	for(i=0;i<M_X;i++){
		for(j=0;j<M_Y;j++){
			m[i][j]=0;
		}
	}
}
//初始化R数组 
void f_R(){
	for(i=0;i<4;i++){
		for(j=0;j<2;j++){
			R[i][j]=0;
		}
	}	
}
//初始化data 
void f_d(){
	FILE *fp;
	fp=fopen("data.txt","w");
	fclose(fp);
}

my-tetris-3.h

//基础函数头文件 

/*
0 = 黑色       8 = 灰色
1 = 蓝色       9 = 淡蓝色
2 = 绿色       10 = 淡绿色
3 = 浅绿色     11 = 淡浅绿色
4 = 红色       12 = 淡红色
5 = 紫色       13 = 淡紫色
6 = 黄色       14 = 淡黄色
7 = 白色       15 = 亮白色
*/
//设置字符前景色和底色,ForeColor:字色,BackColor:背景色,基本颜色0-7,8-15是亮度加强的基本色 
void set_color(int ForeColor,int BackColor){
    HANDLE hConsole = GetStdHandle((STD_OUTPUT_HANDLE)) ;
    SetConsoleTextAttribute(hConsole,BackColor*16+ForeColor) ;
}
//设置光标,flg=1:显示光标 flg=0:隐藏光标
void set_cursor(int flg){
    HANDLE hOut=GetStdHandle(STD_OUTPUT_HANDLE);
    CONSOLE_CURSOR_INFO cursor_info={100,flg};
    SetConsoleCursorInfo(hOut,&cursor_info);
}
//设置字符显示位置
void set_cocate(int x,int y)
{
	x*=2;//增加 
	HANDLE hOut=GetStdHandle(STD_OUTPUT_HANDLE);
	COORD loc={x,y};
	SetConsoleCursorPosition(hOut,loc);
}
//执行系统命令
void command(int a){
/*
1 = 清屏
2 = 暂停 
*/
switch(a){
	case 1:system("cls");break;
	case 2:set_cocate(0,Y);set_color(15,0);system("pause");break;
	default:break;
	} 
}
//整形数据输入
int input_int(int i,int j){
	int a=-100,k=0;
	printf("请输入 %d~%d 的数值,并按回车确定;\n",i,j);
	while(a>j||a<i){
		if(k!=0){
			printf("输入错误,请重新输入 %d~%d 的数值,并按回车确定;\n",i,j); 
		}
		scanf("%d",&a);
		k++;
	}
	return a;
}

猜你喜欢

转载自blog.csdn.net/weixin_40756041/article/details/78354180