2048:大一小白初学程序设计的大作业分享

现在回看有点幼稚,但是还是分享一下,或许有部分对大家有用

程序结构设计与分析

因为游戏可以让用户自定义网格数量所以主要数据(网格内的数据)存在动态内存中,通过全局指针来访问,所以其实并不存在数组,但是可以利用指针指向动态分配的内存达到变长数组的效果,代码注释中也默认用数组来指代动态分配的那一块内存。整个游戏通过把各种功能进行函数化以达到简化主函数的目的。其中得分和游戏网格尺寸也都使用全局变量方便各函数直接调用,避免过度传参降低效率。游戏代码中多次运用do while来防止用户输入非法字符的情况。

如何使用程序:

整个游戏的输入是区分大小写的。

1.打开后首先是欢迎界面huanyin(),输入Y开始游戏,输入Y关闭游戏,输入h查看帮助。如果不输入Y或N会一直在开始界面。

2.如果开始游戏就会进入读档界面ddjm(),读入游戏存档(输入D。如果没有存档会让选择是退出游戏还是开启新一局)  ,开启新一局游戏(输入S),退回欢迎界面(输入R)。

3.如果是开启新一居,用户可以选择网格尺寸SIZExSIZE个,和初始所给数据个数(初始数据是2或4随机);如果是读档,若存档里有错误会选择让退出游戏(输入N)       开启新一局游戏(输入S)。

4.游戏中输入W/A/S/D移动方块,输入h查看游戏帮助,输入q重新开始,输入v存档,输入l读档,输入R退出游戏。游戏中一直会显示得分,合成一个数字,得分就加上这个数字,初始得分是0,存、读档时得分也会存、读入。如果没有空位且上下左右都无法移动就死局了,显示“gameover”,游戏就结束了,会询问是否重新开始还是直接结束。如果合成2048游戏也会结束,但是会显示“恭喜你成功合成了2048!”

主要函数的功能:

1.void screen();

显示每次操作后的屏幕,即打印网格、与每个格子里的数、操作提示和得分等

2.void chushihua(int NANDU); //初始化数组

让重新开局时随机在一些位置生成2或4

我想到2种方法(我的程序里用的是第一种,因为我觉得第一种可能更快更随机一点?):

第一种是把这SIZE*SIZE个数的二维数组当成一维的,即SIZE*SIZE个数,一行一行这样数下去。随机生成几个不一样的数字,即随机挑几个不一样的位置,然后再随机分配2/4给这些位置

第二种是若要选X个位置,就把2/4放在前X个空格里,然后再做一定数量次“洗牌”(洗牌即随机挑2个位置交换)

第二种方法:

void chushihua(int NANDU)//初始化数组

{

srand(time(0));//随机数种子

int flag=1,i,j,x,y,x1,y1;

//先把数组前NANDU个元素随机设置为2/4

for(i=0;i<SIZE_2048&&flag;i++)

{

for(j=0;j<SIZE_2048&&flag;j++)

{

a[i][j]=pow(2,rand()%2+1);

if(i*SIZE_2048+j+1==NANDU)

flag=0;//即生成了NANDU个数后就通过flag跳出这两层循环,用goto也可以

}

}

//洗牌,即做50次交换,使初始数的位置变为任意位置

for(i=0;i<50;i++)

{

x=rand()%SIZE_2048;

y=rand()%SIZE_2048;

do{

x1=rand()%SIZE_2048;

y1=rand()%SIZE_2048;

int temp;

temp=a[x][y];

a[x][y]=a[x1][y1];

a[x1][y1]=temp;

}while(x1==x&&y1==y);

}

}

3.char updateWithInput(int *move); //与用户输入有关的更新

对于用户的输入进行响应

传入了move的地址,若有移动则move就不是0,就会在主函数里运行 updateWithoutInput()

输入WASD就相应上左下右移动,其中上移就是先逆时针转90再左移在顺时针转回来,以此类推下右移的情况。其实我一开始是写好了上移之后稍作修改分别写了下左右,也是可以的

如果输入h就输出帮助

如果输入q就询问是否重新开始,重新开始的话就会返回q,主函数里判断返回值为q就会回到主函数开头的START

如果输入v就直接调用存档函数

如果输入l就询问是否读档,若选择读档,如果没有存档或存档的网格尺寸与当前不同或存档里有非法字符会询问退出游戏还是继续游戏,退出游戏会询问是否存档。只有存档存在且无非法字符还尺寸与当前匹配才会读档成功。

如果输入R就询问是否退出,如果退出就return shuru;即return ‘R’,在主函数中让其退出循环,显示最终得分并询问是否重新开始;如果不退出就goto reinput重新输入

如果输入非法字符就再次提示正确输入字符,并且要求重新输入

  1. void updateWithoutInput();  //自动在空白处冒出新数据2/4

如果有空位就自动在空白处冒出新数据2/4 ,没有空白就不冒出新数据。

5.int gameover(); //游戏结束条件合成了2048或死局

判断游戏有没有结束,有没有合成2048或者是死局。先判断有没有合成2048,如果有2048就return 0结束游戏。如果没有2048再判断有无空位,如果有空位return 1继续游戏。如果没有空位,再判断是否能移动,即一个格子其上下左右(边界格子不是判断上下左右,利用短路原理防止越界)是否有同样的数字,有同样的数字就return 1可以移动,继续游戏。如果没有同样的数字相邻就会return 0结束游戏,达成死局。

6.void zuoyi(int* move);

把整个数组进行2048游戏规则下的左移,如果从最左边的的数开始判断。如果这个数是0则往右找,找到的第一个非0数移到这个位子(这样确保左边不会有空位,所以如果这个数是0时就不用左移了,因为这一步保障了每次循环到的位子的左边没有空位,所以如果这个数不是0无法左移);如果这个数不是0,则往右找,找到的第一个非0数(分皓之前那一步只是确保了左边没有空位,不确保这个数右边没有空位,所以要往右找,直到非0)如果和这个数相等,则合并,即让这个数*2,找到的与这个数相等的数的位置变为0,如果与这个数不相等,则移到这个数相邻的右边,并且找到非0数就可以停止往右找的动作了,否则可能发生“穿墙”。

7.void shunshizhen90();

把整个数组顺时针转90度

  1. void nishizhen90();

把整个数组逆时针转90度

9.void cundang();

把现在的数据存下来,第一行是SIZE,然后换行存数组,每个数间用空格隔开,且都是按数组里的位置存放的,最后一行放得分

10.void dudang();

读取之前的存档,因为只有两个地方需要读档,一是游戏开始时二是游戏中,游戏开始时需要先读取存档中的SIZE_2048的大小,而游戏中要判断SIZE_2048是否匹配,所以每次读档之前都要先读取存档中的SIZE_2048即都要判断是否有存档,所以函数里不需要再次判断了。

先创建相同大小的空间存放存档里读取的数据若遍历一遍都没非法字符再重新读入到游戏的变量里,要不然读到一半发现有非法字符无法回到读档之前的状态继续游戏。

其中非法字符是非数字或者是数字的某些特殊情况:SIZE<=1;数组元素不是0或不大于2048的2 的幂次;defen小于0或是奇数。

还加上了判断如果篡改了存档里的数据数量,即如果SIZE是4,但是后面是5*5的数据的处理。即在判断完有无非法字符后,如果没有非法字符,再加上一个判断文件指针有没有到达结尾(此处“结尾”有一点疑问,在文档最后),如果没有,说明后面还有数,数据量不匹配,所以存档里有错误。

11.void help();

即打印出帮助文档。因为文档较长且用到的地方较多所以单独做成了一个函数

12.char huanyin();

13.char ddjm();

主函数中:

先是欢迎界面

然后是读档界面(可选择读档或者重新开局)

游戏中在while(1)内实现主体游戏运行,先显示屏幕,然后判断是否合成了2048或死局,没有结束游戏的条件就继续获取用户的输入,否则就结束游戏。通过对updateWithInput()函数的返回值判断是否要重新开始或者结束游戏。最后判断如果用户输入没有让任何一个数据发生移动,则不会在新地方出现随机2/4的数据,但如果发生了移动就随机出现2/4(该函数内部已经判断了是否有空位,没有空位就不会出现新数)

代码

其中为了能重新回到初始页面重新开始使用了goto语句,是不太好的,其实可以把整个主函数用一个函数封装起来,如果要重新开始游戏可以在主函数中重新执行这个函数。

#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <windows.h>
#include <time.h> 
#include <math.h>

void screen();
void chushihua(int NANDU); //初始化数组 
char updateWithInput(int *move); //与用户输入有关的更新
void updateWithoutInput();  //自动在空白处冒出新数据2/4 
int gameover(); //游戏结束条件合成了2048或死局 
void zuoyi(int* move);//把数组以2048的规则向左移 
void shunshizhen90();//把数组顺时针转90° 
void nishizhen90();//把数组逆时针转90° 
void cundang();//存档 
int dudang();//读档 
void help(); //帮助 
char huanyin();//欢迎界面 
char ddjm();//读档界面 


int defen=0; 
int *a=NULL; 
int SIZE_2048=0;//先赋值为0,如果读档失败可以判断出来 

int main()
{
	char input,shuru,temp;
	START: ;//START放在把初始化之前 ,否则上一局的数还在里面
	a=NULL; 
	defen=0; 
	int move=0;

	input=huanyin();//欢迎界面
	system("cls");//清屏 
	
	if(input=='N')
	goto END;
	else if(input=='Y')//选择开始游戏,显示读档界面
	temp=ddjm();
	
	if(temp=='N')
	goto END;
	else if(temp=='R')
	goto START;
	
	//temp不是N也不是R就开始游戏 
	while(1)
	{
		screen(); //显示屏幕 
		if(gameover()==0)
		break;
		shuru=updateWithInput(&move);//与用户输入有关的更新
		 if(shuru=='q') 
		{
			system("cls");
			free(a);
			goto START;
		}
		else if(shuru=='R')
			break;
		else if(shuru=='E') 
		goto END;
		if(move!=0)//move是0的话就代表网格上所有方块都没有改变位置,此时不会生成新的数字方块。
		updateWithoutInput();//自动在空白处冒出新数据2/4 
	}
	
	//游戏结束,可能是死局也可能是合成了2048,也可能是输入了R退出游戏 
	printf("\n最终得分%d\n",defen); 	
	do{
		printf("是否要重新开始Y/N\n"); 
		scanf(" %c",&input);
		if(input=='Y')
		{
			system("cls");
			free(a);
			goto START;	
		}
//如果是N就会到达END那一行 
	}while(input!='Y'&&input!='N'); 
	//关闭游戏 
END: ;	 
		printf("再见!"); 
 
	free(a);
	return 0; 
}

void screen()//显示屏幕 
{
	system("cls");
	int i,j;
//绘制网格和画面
			//绘制第一行,2048居中 
			for(i=0;i<SIZE_2048;i++)
			{
				if(i==SIZE_2048/2) 
				{
					if(SIZE_2048%2!=0)
					printf("    ");
					printf("2048");
				}
				printf("     ");		
			} 
			printf("\n");
			//绘制格子 
			for(i=0;i<=SIZE_2048;i++)
			{
				for(j=0;j<SIZE_2048;j++)
				{
					printf("|"); 
					printf("-----"); 
				} 
				printf("|\n") ;
				for(j=0;j<SIZE_2048&&i<SIZE_2048;j++)
				{
					printf("|"); 
					printf("%4d ",*(a+i*SIZE_2048+j)); 
				} 
				if(i<SIZE_2048)
				printf("|\n") ;
     		}
     		printf("请输入W/A/S/D移动方块,输入h查看游戏帮助,输入q重新开始,输入v存档,输入l读档,输入R退出游戏\n\
目前得分%d\n",defen); 
} 

void chushihua(int NANDU)//初始化数组 
{
	srand(time(0));//随机数种子 
	int i,x,y,t,b[SIZE_2048*SIZE_2048]={0};
	for(i=0;i<NANDU;i++)
	{
		do
		{
			t=rand()%((SIZE_2048)*(SIZE_2048));//生成0到SIZE_2048*SIZE_2048-1的数 
		}while(b[t]==1);
		b[t]=1;
		x=t/(SIZE_2048);
		y=t%SIZE_2048;
		*(a+SIZE_2048*x+y)=pow(2,rand()%2+1);
	} 
}

char updateWithInput(int *move)//与用户输入有关的更新
{
	char shuru,restart;
	int turn;
	*move=0;
	printf("请输入:\n"); 
	reinput: ;
	scanf(" %c",&shuru);
	if(shuru=='D')
	{
		for(turn=0;turn<2;turn++)//逆时针180°
			nishizhen90(); 
		zuoyi(move);
		for(turn=0;turn<2;turn++)		//再逆时针180°  
			nishizhen90();				
	}
	else if(shuru=='S')
	{
		shunshizhen90();
		zuoyi(move);
		for(turn=0;turn<3;turn++)//再顺时针270°
			shunshizhen90(); 			
	}
	else if(shuru=='A')
		zuoyi(move);
	else if(shuru=='W')
	{		
		nishizhen90(); 
		zuoyi(move);
		for(turn=0;turn<3;turn++)//再逆时针270° 
			nishizhen90(); 
	}
	else if(shuru=='h')
	{
		help();
		printf("请输入W/A/S/D移动方块,输入h查看游戏帮助,输入q重新开始,输入v存档,输入l读档,输入R退出游戏\n\
重新输入:\n");
	goto reinput;
	}
	else if(shuru=='q') 
	{
		printf("您确定要重新开始吗?Y/N\n");
		RESTART: ;
		scanf(" %c",&restart); 
		if(restart=='N') 
		{
			printf("请输入W/A/S/D移动方块,输入h查看游戏帮助,输入q重新开始,输入v存档,输入l读档,输入R退出游戏\n\
重新输入:\n");
			goto reinput;
		}
		else if(restart=='Y'){}
		else
		{
			printf("\a");
			printf("请输入Y/N\n");
			goto RESTART;
		}
	}
	else if(shuru=='v')
	cundang();
	else if(shuru=='l')
	{	char c;
		do
		{
		printf("确定要读档吗?Y/N\n");			
		scanf(" %c",&c);		
		}while(c!='Y'&&c!='N'); 
		if(c=='Y') 
		{
			char input1,input2;
			int chicun; 
			//判断存档网格尺寸是否匹配 
			FILE *fp=NULL;
			fp=fopen("2048.map", "rb");
			if(fp==NULL)
			{
				printf("未检测到存档,读档失败!\n");
			}
			else
			{
				fscanf(fp,"%d",&chicun);
		 	
				if(chicun==SIZE_2048&&dudang()==1)//由短路特性知,若尺寸不匹配根本不会读档 
				return shuru;
				else//尺寸不匹配 或者 尺寸匹配但是读档时发现存档有错误 
				{
					if(chicun!=SIZE_2048) 
					printf("读档失败,游戏SIZE与存档SIZE不匹配\n");
				}
			} 
			//fp==NULL或 尺寸不匹配 或 尺寸匹配但是读档时发现存档有错误 会进行下面的代码 
				do{
					printf("请选择:\n\
退出游戏(输入N)       继续游戏(输入S)\n");
					scanf(" %c",&input1);
					if(input1=='N')
					{
						do{	
						printf("请问是否要存档?(Y/N)\n");
						scanf(" %c",&input2);
						}while(input2!='Y'&&input2!='N');
						if(input2=='Y')
						cundang();
						return 'E'; 
					}
				}while(input1!='N'&&input1!='S'); 	
			}
		else if(c=='N')
		printf("继续游戏\n"); 
	}
	else if(shuru=='R')
	{
		char r;
		do{	
			printf("确定要退出游戏吗?Y/N\n");
			scanf(" %c",&r);
		}while(r!='Y'&&r!='N');
		if(r=='Y')
		return 'R';
		else 
		{
			printf("请输入W/A/S/D移动方块,输入h查看游戏帮助,输入q重新开始,输入v存档,输入l读档,输入R退出游戏\n\
重新输入:\n");
			goto reinput;
		} 
	}
	else 
	{
		printf("\a请输入W/A/S/D移动方块,输入h查看游戏帮助,输入q重新开始,输入v存档,输入l读档,输入R退出游戏\n\
重新输入:\n");
		goto reinput;
	}
return shuru;
}
 
void updateWithoutInput()//自动在空白处冒出新数据2/4 
{
int x,y,i,j; 
for(i=0;i<SIZE_2048;i++)
{
	for(j=0;j<SIZE_2048;j++)
	{
		if(*(a+SIZE_2048*i+j)==0)//如果有空位 
		{
			do{
				x=rand()%SIZE_2048;
				y=rand()%SIZE_2048;
			}while(*(a+SIZE_2048*x+y)!=0);//速度会不会太慢? 
			*(a+SIZE_2048*x+y)=pow(2,rand()%2+1);
			goto end;
		}
	}	
} 
end: ;
} 

int gameover()//游戏结束条件合成了2048或死局
{
int i,j;
	for(i=0;i<SIZE_2048;i++)
	{
		for(j=0;j<SIZE_2048;j++)
		{
			if(*(a+i*SIZE_2048+j)==2048)
			{
				printf("恭喜你成功合成了2048!"); 
				return 0;
			}
		}
	}
	for(i=0;i<SIZE_2048;i++)
	{
		for(j=0;j<SIZE_2048;j++)
		{
			if(*(a+i*SIZE_2048+j)==0)//有空位 
				return 1;
		}
	}

//没有元素是2048且无空位,判断是否动不了成死局 
	for(i=0;i<SIZE_2048;i++)
	{
		for(j=0;j<SIZE_2048;j++)
		{
			if(i-1>=0&&*(a+i*SIZE_2048+j)==*(a+(i-1)*SIZE_2048+j))
			return 1; 
			if(i+1<SIZE_2048&&*(a+i*SIZE_2048+j)==*(a+(i+1)*SIZE_2048+j))
			return 1;
			if(j-1>=0&&*(a+i*SIZE_2048+j)==*(a+i*SIZE_2048+j-1))
			return 1;
			if(j+1<SIZE_2048&&*(a+i*SIZE_2048+j)==*(a+i*SIZE_2048+j+1))
		 	return 1;
		}
	}
printf("gameover");
return 0;
}
void shunshizhen90()
{
	int b[SIZE_2048][SIZE_2048],i,j;
		for(i=0;i<SIZE_2048;i++)
				{
					for(j=0;j<SIZE_2048;j++)
					b[i][j]=*(a+i*SIZE_2048+j); 
				} 
		for(i=0;i<SIZE_2048;i++)
				{
					for(j=0;j<SIZE_2048;j++)
					*(a+j*SIZE_2048+(SIZE_2048-1-i))=b[i][j]; 
				} 
} 
void nishizhen90()
{
	int b[SIZE_2048][SIZE_2048],i,j;
		for(i=0;i<SIZE_2048;i++)
				{
					for(j=0;j<SIZE_2048;j++)
					b[i][j]=*(a+i*SIZE_2048+j); 
				} 
	for(i=0;i<SIZE_2048;i++)
				{
					for(j=0;j<SIZE_2048;j++)
					*(a+(SIZE_2048-1-j)*SIZE_2048+i)=b[i][j]; 
				} 
} 
void zuoyi(int* move)
{
	int i,j,k;
	for(j=0;j<SIZE_2048-1;j++)
				{
					for(i=0;i<SIZE_2048;i++)
					{
						if(*(a+i*SIZE_2048+j)==0)
						{
							for(k=j+1;k<SIZE_2048;k++)
							{
								if(*(a+i*SIZE_2048+k)!=0)
								{
									*(a+i*SIZE_2048+j)=*(a+i*SIZE_2048+k);
									*(a+i*SIZE_2048+k)=0;
									i--;
									*move=1;
									break;	
								}
							}
						}
						else
						{
							for(k=j+1;k<=SIZE_2048-1;k++)
							{
								if(*(a+i*SIZE_2048+k)!=0)
								{
									if(*(a+i*SIZE_2048+k)==*(a+i*SIZE_2048+j))
									{
										*(a+i*SIZE_2048+j)=*(a+i*SIZE_2048+j)+*(a+i*SIZE_2048+k);
										defen+=*(a+i*SIZE_2048+j);
										*(a+i*SIZE_2048+k)=0;
										*move=1;
									}
									else 
									{	
										if(k!=j+1)
										{	
											*(a+i*SIZE_2048+j+1)=*(a+i*SIZE_2048+k);
											*(a+i*SIZE_2048+k)=0;
											if(j+1!=k) 
											*move=1;
										}
									}
									break;	
								}
							}
						}	
					}	 	
				}
}

void cundang()
{
	int i,j;
	FILE *fp=NULL;
	fp = fopen("2048.map", "wb");
	fprintf(fp, "%d\n", SIZE_2048);
	for(i=0;i<SIZE_2048;i++)
	{
		for(j=0;j<SIZE_2048;j++)
		{
			fprintf(fp, "%d ", *(a+i*SIZE_2048+j));
		}
		fprintf(fp, "\n");
	}
	fprintf(fp, "%d", defen);
	fclose(fp);
	printf("存档成功!按任意键继续\n"); 
	getchar();
	getchar();
}
//SIZE_2048*SIZE_2048*2+SIZE_2048+3
int dudang()
{
	int i,j;
	FILE *fp=NULL,*fp1=NULL;
	
	fp1=fopen("2048.map", "rb");
//	if(fp==NULL)
//	{
//		printf("未检测到存档,读档失败!\n");
//		return 0;
//	}
//因为每次读档之前都要先读取SIZE_2048或者判断存档的SIZE和游戏里的SIZE_2048是否匹配,所以都会判断是否有存档,所以函数里不需要再次判断了 
//	else
//	{
		fscanf(fp1,"%d",&SIZE_2048);
		//先判断是否有非法字符 
		if(SIZE_2048<=1)
			return 0; 
		else//把测试数据都初试设置为负数,如果是字符而不是数字,会读取失败,其中存的值是初始赋值的-1,会检测出错误 
		{
			int defen1=-1;
			int *a1;
			a1=(int *)malloc(sizeof(int)*SIZE_2048*SIZE_2048); 
			for(i=0;i<SIZE_2048;i++)
		 	for(j=0;j<SIZE_2048;j++)
		 	*(a1+i*SIZE_2048+j)=-1;
		 	
			for(i=0;i<SIZE_2048;i++)
		 	for(j=0;j<SIZE_2048;j++)
			 {
		 		fscanf(fp1,"%d",a1+i*SIZE_2048+j);
		 		//if(*(a1+i*SIZE_2048+j)<0||!(fabs(log2(*(a1+i*SIZE_2048+j))-(int)log2(*(a1+i*SIZE_2048+j)))<1e-8)||*(a1+i*SIZE_2048+j)>2048||)//先判断是否是负数,不然Log2会有问题。不是2的幂次或超过2048或负数都不可以 
		 		//上面的方法因为浮点数的误差有可能会出现错误判断 (1e-8) 
				 
				  if(*(a1+i*SIZE_2048+j)!=0)//0是合法的 
			 	{
			 		int temp=2;
					 for(temp=2;temp<=2048;temp+=temp) 
					 {
					 	if(*(a1+i*SIZE_2048+j)==temp)
					 	break;
					 }
					 if(temp>2048)
					 {
		 				free(a1);
				 		return 0; 
					 }
				 } 
			 	
		 	}
		 	fscanf(fp1,"%d",&defen1);
			if(defen1<0||defen%2!=0)
			{
				free(a1);
			return 0; 	
			}
fgetc(fp1);
fgetc(fp1);
//经过尝试,读完这些数后要2个fgetc才能让feof变成true 
			if(!feof(fp1))
			{
				free(a1);
				return 0;
			}
		free(a1);
		}
		fclose(fp1);
//存档中无错误时再读档,防止游戏进行中时读档时存档有问题无法返回原游戏状态:
		fp=fopen("2048.map", "rb"); 
		fscanf(fp,"%d",&SIZE_2048);
		 for(i=0;i<SIZE_2048;i++)
		 for(j=0;j<SIZE_2048;j++)
		 	fscanf(fp,"%d",a+i*SIZE_2048+j);
		fscanf(fp,"%d",&defen);
		fclose(fp);
		printf("读档成功!\n");
		return 1;
//	}
}

void help()
{
printf("╔══════════════════════════════════════════════════════════════════════════════════╗\n"); 
printf("║本游戏通过按键W、S、A、D(均为大写)四个键分别控制滑块上移、下移、左移和右移。    ║\n");
printf("║滑块移动的过程中,如有相邻且相等数字的滑块将会相加,并获得相应的分数。            ║\n");
printf("║当棋盘上的所有位置均有数字,且不能合成,则游戏结束。合成出2048时游戏成功。        ║\n");
printf("║游戏中输入v即为存档但可继续游戏,输入l即为读档,输入R则退出游戏,输入q重新开始。  ║\n");
printf("╚══════════════════════════════════════════════════════════════════════════════════╝\n");
} 
char huanyin()//欢迎界面 
{
	char input;
	printf("欢迎来到2048游戏!\n");
	do{
		printf("请问是否开始游戏?\n"
		"开始请输入Y,关闭游戏请输入N\n"
		"输入h查看游戏帮助\n"); 
		scanf(" %c",&input);
		//游戏帮助 
		if(input=='h')
			help();
	}while(input!='Y'&&input!='N');
	return input;
}

char ddjm()//读档界面 
{	
char input; 
int NANDU=2;
		do
		{	
			printf("游戏开始,请选择:\n"
			"读入游戏存档(输入D)   开启新一局游戏(输入S)  退回欢迎界面(输入R)\n");
			scanf(" %c",&input);
			if(input=='h')
				help();
		}while(input!='D'&&input!='R'&&input!='S');
		system("cls");//清屏 
		
		if(input=='R')
	 	   return input;
		else if(input=='S')
			{
				S: ;
				do{
					printf("请输入游戏尺寸数SIZE(游戏网格数共SIZE*SIZE个,请输入正数):\n"); 
					scanf("%d",&SIZE_2048); 
				} while(SIZE_2048<=0);
				
				a=(int *)malloc(sizeof(int)*SIZE_2048*SIZE_2048); 
				memset(a,0,sizeof(int)*SIZE_2048*SIZE_2048);//问题:为什么没有string.h也能用?
				
				printf("请输入游戏难度(游戏难度即为初使出现的数据值的个数,初始数据为随机出现的2或4)\n"); 
				do
				{
					printf("难度只能大于等于2并且小于等于%d:\n",SIZE_2048*SIZE_2048);
					scanf("%d",&NANDU); 
				}while(NANDU>SIZE_2048*SIZE_2048||NANDU<2);
				
				chushihua(NANDU);//初始化数组 
				
			}
			else if(input=='D')
			{
				FILE *fp=NULL;
				fp=fopen("2048.map", "rb");
				if(fp==NULL)
				{
					printf("未检测到存档,读档失败!\n");
					do{
						printf("请选择:\n\
退出游戏(输入N)       开启新一局游戏(输入S)\n");
						scanf(" %c",&input);
						if(input=='N')
							return 'N'; 
						else if(input=='S') 
						goto S;
						}while(input!='N'&&input!='S');
				}
				else
				{
					fscanf(fp,"%d",&SIZE_2048);
					fclose(fp); 
					if(SIZE_2048<=1)
					{
						printf("存档中有错误,读档失败!\n");
						do{
							printf("请选择:\n\
退出游戏(输入N)       开启新一局游戏(输入S)\n");
							scanf(" %c",&input);
							if(input=='N')
								return 'N'; 
							else if(input=='S') 
							goto S;
						}while(input!='N'&&input!='S');
					}
					else{
							a=(int *)malloc(sizeof(int)*SIZE_2048*SIZE_2048); 
							memset(a,0,sizeof(int)*SIZE_2048*SIZE_2048);
							if(dudang()==0)
							{
							printf("存档中有错误,读档失败!\n");
							do{
									printf("请选择:\n\
退出游戏(输入N)       开启新一局游戏(输入S)\n");
									scanf(" %c",&input);
									if(input=='N')
										return 'N'; 
									else if(input=='S') 
									goto S;
								}while(input!='N'&&input!='S');
							}
						} 
				} 
			
			}
				
return 'Y';//除了return ‘N’/‘R’,就是‘Y’
} 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值