最近写的拼图游戏

#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <time.h>

#define SIZE 4 
#define SWAP(x,y,t)  ((t)=(x),(x)=(y),(y)=(t))

int *total_choice=NULL;
int step=0;


void display(int board[][SIZE]);           //展示棋盘的函数
int is_valid(int board[][SIZE],int choice);                  //判断玩家选择是否有效的函数
void move(int board[][SIZE],int choice);					   //移动数字的函数
int is_complete(int board[][SIZE]);                          //判断拼图是否完成的函数
void initial(int board[][SIZE]);                            //初始化棋盘
void turn_left(int board[][SIZE]);								//电脑左移
void turn_right(int board[][SIZE]);								//电脑右移
void turn_up(int board[][SIZE]);								//电脑上移
void turn_down(int board[][SIZE]);                              //电脑下移

void main()
{
	int board[SIZE][SIZE]={                      //The board
					{1,2,3,4},			  //Initial values are reference numbers
					{5,6,7,8},			  //used to select a vacant square for
					{9,10,11,12},         //a turn
					{13,14,15,0}
							};
	char again=0;
	int choice=0;
	int i=0;
	long now=0;
	int step=0;
	printf("欢迎你来到简单的拼图游戏\n");
	printf("选择相应的数字,该数字会移到空格处\n");
	printf("如果不能移动该数字,将显示出来,并让玩家重新选择数字移动\n");
	printf("Good luck!Press Enter to start.\n");
	scanf("%c",&again);

	total_choice=(int*)malloc(15*sizeof(int));

	initial(board);
	display(board);
	getchar();
	for(i=0;i<15;i++)
	{
		move(board,total_choice[15-i-1]);
		display(board);
		now=clock();
		for(;clock()-now<CLOCKS_PER_SEC;);
		system("cls");
	}
	
	do
	{
		for(;;)
		{
			display(board);
			printf("请输入你要移动的数字:  ");
			scanf("%d",&choice);
			if(is_valid(board,choice))                          //如果移动有效则移动该数字并显示结果
			{
				move(board,choice);
				display(board);
				system("cls");									//清屏
			}
			else												//如果移动无效,则显示为无效移动
				printf("无效的移动\n");
			if(is_complete(board)&&is_valid(board,choice))
			{
				display(board);
				printf("Good job!\n");
				printf("Mission completed!\n");
				break;
			}
		}
		printf("你想再玩一次吗?(y or n)  ");
		scanf(" %c",&again);
	}while(tolower(again)=='y');
}

void display(int board[][SIZE])
{
	int row=0;                                  //Row index
	int col=0;                                  //Column index

	for(row=0;row<SIZE;row++)
	{
		printf("  +");
		for(col=0;col<SIZE;col++)
			printf("----+");
		printf("\n");
		for(col=0;col<SIZE;col++)
		printf("  |%2d%s",board[row][col],board[row][col]?"":"\b ");   //展示棋盘上的数字,当数字为0时,显示为空白
		printf("  |\n");											   
	}
	
	printf("  +");
	for(col=0;col<SIZE;col++)
		printf("----+");							//Display the bottom line
	printf("\n");								//Display the end of bottom line
}

int is_valid(int board[][SIZE],int choice)
{
	int row=0;
	int col=0;
	int rowdelta=0;                            //Row increment around a square
	int coldelta=0;							   //Column increment around a square
	int flag=0;                                //跳出循环标记
	for(row=0;row<SIZE;row++)                  //获取玩家选择数字的位置
	{
		for(col=0;col<SIZE;col++)
		{
			if(board[row][col]==choice)
			{
				flag=1;
				break;
			}
		}
		if(flag==1)
			break;
	}
	for(rowdelta=-1;rowdelta<=1;rowdelta++)
	{
		for(coldelta=-1;coldelta<=1;coldelta++)
		{//不能检查越界位置,choice所在位置,以及与choice成对角线的位置
			if(row+rowdelta>=SIZE||row+rowdelta<0||
				col+coldelta>=SIZE||col+coldelta<0||
				rowdelta==coldelta||board[row+rowdelta][col+coldelta])
				continue;

			if(board[row+rowdelta][col+coldelta]==0)    //空白就在choice旁边,则为有效choice
				return 1;
		}
	}
	return 0;
}

void move(int board[][SIZE],int choice)
{
	int choice_row=0;                                  //存储choice的row
	int choice_col=0;								   //存储choice的col
	int zero_row=0;                                    //存储0的row
	int zero_col=0;									   //存储0的col
	int temp=0;
	int flag=0;                                        //循环跳出标记
	if(!is_valid(board,choice))
		return;
	for(choice_row=0;choice_row<SIZE;choice_row++)	  //获取choice的row,col
	{
		for(choice_col=0;choice_col<SIZE;choice_col++)
		{
			if(board[choice_row][choice_col]==choice)
			{
				flag=1;
				break;
			}
		}
		if(flag==1)
		{
			flag=0;
			break;
		}
	}
	
	for(zero_row=0;zero_row<SIZE;zero_row++)	  //获取zero的row,col
	{
		for(zero_col=0;zero_col<SIZE;zero_col++)
		{
			if(board[zero_row][zero_col]==0)
			{
				flag=1;
				break;
			}
		}
		if(flag==1)
			break;
	}

	SWAP(board[choice_row][choice_col],board[zero_row][zero_col],temp);    //交换数字
}

int is_complete(int board[][SIZE])
{
	int row=0;
	int col=0;
	int temp[SIZE][SIZE]={                   //用于检查拼图是否拼好而定义的原始拼图   
					{1,2,3,4},			  
					{5,6,7,8},			  
					{9,10,11,12},         
					{13,14,15,0}
							};

	for(row=0;row<SIZE;row++)
	{
		for(col=0;col<SIZE;col++)
		{
			if(board[row][col]!=temp[row][col])
				return 0;
		}
	}
	return 1;
}

void initial(int board[][SIZE])                     //问题就出在这里,初始化后的局面很简单
{
	int row=0;
	int col=0;
	int flag=0;                   //跳出循环的标记
	int on_left[2]={-1,0};  //往左上角偏移              
	int on_right[2]={-1,0};  //往右上角偏移
	int up=0;       //向上偏移次数
	int left=0;	 //向左偏移次数
	int right=0;	 //向右偏移次数
	int rowdelta=0;
	int coldelta=0;
	int i=0;                      //循环变量
	int j=0;

	while(board[0][0]==1)
	{
		
		for(;;)
		{

			srand(time(NULL));
			rowdelta=on_left[rand()%2];
			if(rowdelta==0)
			{
				coldelta=-1;
				turn_left(board);
				left++;
			}
			else
			{
				coldelta=0;
				turn_up(board);
				up++;
			}
			if(left==2)
			{//如果向左移了2次,则应该向上移3-turn_up
				for(i=0;i<3-up;i++)
				{
					turn_up(board);
				}
				//再次向左移一次
				turn_left(board);
				break;
			}
			
		
			if(up==2)
			{//如果向上移了2次,则应该向左移3-turn_left
				for(j=0;j<3-left;j++)
				{
					turn_left(board);
				}

				//再次向上移一次
				turn_up(board);
				break;
			}	
		}
	}


	for(i=0;i<3;i++)								//向下移动三步
	{
		turn_down(board);
	}

	up=0;                                          //初始化turn_up

	for(;;)												//向右上角移动
	{							

		srand(time(NULL));
		rowdelta=on_right[rand()%2];
		if(rowdelta==0)
		{
			coldelta=1;
			turn_right(board);
			right++;
		}
		else
		{
			coldelta=0;
			turn_up(board);
			up++;
		}
		if(right==2)
		{//如果向右移了2次,则应该向上移3-turn_up
			for(i=0;i<3-up;i++)
			{
				turn_up(board);
			}
			//再右移动一次
			turn_right(board);
			break;
		}
		if(up==2)
		{//如果向上移了2次,则应该向右移3-turn_right
			for(j=0;j<3-right;j++)
			{
				turn_right(board);
			}

			//再次上移
			turn_up(board);
			break;
		}	
	}


	printf("Step=%d\n",step);
}

void turn_left(int board[][SIZE])
{
	int row=0;
	int col=0;
	int flag=0;

	//获取0的坐标
	for(row=0;row<SIZE;row++)	  
	{
		for(col=0;col<SIZE;col++)
		{
			if(board[row][col]==0)
			{
				flag=1;
				break;
			}
		}
		if(flag==1)
		{
			flag=0;
			break;
		}
	}
	total_choice[step++]=board[row][col-1];
	move(board,board[row][col-1]);	
}

void turn_right(int board[][SIZE])
{
	int row=0;
	int col=0;
	int flag=0;

	//获取0的坐标
	for(row=0;row<SIZE;row++)	  
	{
		for(col=0;col<SIZE;col++)
		{
			if(board[row][col]==0)
			{
				flag=1;
				break;
			}
		}
		if(flag==1)
		{
			flag=0;
			break;
		}
	}
	total_choice[step++]=board[row][col+1];
	move(board,board[row][col+1]);	
}

void turn_up(int board[][SIZE])
{
	int row=0;
	int col=0;
	int flag=0;

	//获取0的坐标
	for(row=0;row<SIZE;row++)	  
	{
		for(col=0;col<SIZE;col++)
		{
			if(board[row][col]==0)
			{
				flag=1;
				break;
			}
		}
		if(flag==1)
		{
			flag=0;
			break;
		}
	}
	total_choice[step++]=board[row-1][col];
	move(board,board[row-1][col]);	
}

void turn_down(int board[][SIZE])
{
	int row=0;
	int col=0;
	int flag=0;

	//获取0的坐标
	for(row=0;row<SIZE;row++)	  
	{
		for(col=0;col<SIZE;col++)
		{
			if(board[row][col]==0)
			{
				flag=1;
				break;
			}
		}
		if(flag==1)
		{
			flag=0;
			break;
		}
	}
	total_choice[step++]=board[row+1][col];
	move(board,board[row+1][col]);	
}

我最近写了个拼图游戏是4*4的方格,只要
1 2 3 4 
5 6 7 8
9 10 11 12
13 14 15 0
  数字与上面一一对应,就拼图成功了(0用空格显示出来,只有它可以移动,比如现在只能是12和15与0交换位置
来实现数字的移动)
  我已经完成了数字移动功能,但关于如何初始化拼图数字(就是随机打乱数字的顺序)没有很好的办法
我想实现当玩家不能完成拼图,由电脑帮助移动数字,并能将过程显示出来
  所以我打算由电脑随机移动数字(移动步数不能太多),并把这些数字记录下来,以便于后面让电脑还原原图
我想过很多办法来初始化拼图,但效果都不理想,初始化的图不够乱,以至于玩家一下子就能拼出图形
  我也实现过让初始化数字很乱的方法,就是在while(图形四个角不是原来的数字)的循环下,让电脑随机移动
生成的拼图确实够乱,但是耗时比较长,一般循环了10000000步左右,这肯定不现实,即便初始化的拼图很乱,
但让电脑还原并显示出来,肯定不现实,玩家也不会有那么多耐心

 

问题就是拼图的初始化不成功,生成的拼图很简单,由于代码还没完全完成,所以生成拼图后按回车就自动还原了

现在修改过了,基本上能玩了

#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>

#define SIZE 4 
#define SWAP(x,y,t)  ((t)=(x),(x)=(y),(y)=(t))

int *total_choice=NULL;
int step=0;


void display(int board[][SIZE]);           //展示棋盘的函数
int is_valid(int board[][SIZE],int choice);                  //判断玩家选择是否有效的函数
void move(int board[][SIZE],int choice);					   //移动数字的函数
int is_complete(int board[][SIZE]);                          //判断拼图是否完成的函数
void initial(int board[][SIZE]);                            //初始化棋盘
void turn_left(int board[][SIZE]);								//电脑左移
void turn_right(int board[][SIZE]);								//电脑右移
void turn_up(int board[][SIZE]);								//电脑上移
void turn_down(int board[][SIZE]);                              //电脑下移

void main()
{
	int board[SIZE][SIZE]={                      //The board
					{1,2,3,4},			  //Initial values are reference numbers
					{5,6,7,8},			  //used to select a vacant square for
					{9,10,11,12},         //a turn
					{13,14,15,0}
							};
	char again=0;
	int choice=0;
	int i=0;
	int j=0;
	long now=0;
	int step=36;
	char temp[4];
	int capacity=100;
	int *temp_choice=NULL;
	int temp_step=0;
	int count=0;
	printf("欢迎你来到简单的拼图游戏\n");
	printf("选择相应的数字,该数字会移到空格处\n");
	printf("如果不能移动该数字,将显示出来,并让玩家重新选择数字移动\n");
	printf("如果玩家实在拼不出原图,可以输入密码god,由电脑帮你还原\n");
	printf("Good luck!Press Enter to start.\n");
	scanf("%c",&again);

	total_choice=(int*)malloc(capacity*sizeof(int));
	if(total_choice==NULL)
	{
		printf("Out of memory!\n");
		abort();
	}

	
	do
	{
		count=0;
		for(i=0;i<SIZE;i++)
		{
			for(j=0;j<SIZE;j++)
				board[i][j]=++count;
		}
		board[3][3]=0;
		total_choice=(int*)malloc(capacity*sizeof(int));                   //为total_choice分配空间
		if(total_choice==NULL)
		{
			printf("Out of memory!\n");
			abort();
		}

		initial(board);

		for(;;)
		{
			if(step==capacity)
			{
				temp_step=step;
				capacity+=50;
				temp_choice=(int *)malloc(capacity*sizeof(int));
				if(total_choice==NULL)
				{
					printf("Out of memory!\n");
					exit(1);
				}
				for(i=0;i<temp_step;i++)
					temp_choice[temp_step]=total_choice[temp_step];
				free(total_choice);
				total_choice=temp_choice;
				temp_choice=NULL;
			}
			display(board);
			printf("请输入你要移动的数字:  ");
			gets(temp);
			if(strcmp(temp,"god")==0)
			{
				for(i=0;i<step;i++)
				{
					move(board,total_choice[step-i-1]);
					display(board);
					now=clock();
					for(;clock()-now<CLOCKS_PER_SEC;);
					system("cls");
				}
				free(total_choice);
				total_choice=NULL;
				break;
			}
			else
			{
				choice=atoi(temp);
			}
			
			if(is_valid(board,choice))                          //如果移动有效则移动该数字并显示结果
			{
				move(board,choice);
				total_choice[step++]=choice;
				display(board);
				system("cls");									//清屏
			}
			else												//如果移动无效,则显示为无效移动
				printf("无效的移动\n");
			if(is_complete(board)&&is_valid(board,choice))
			{
				display(board);
				printf("Good job!\n");
				printf("Mission completed!\n");
				free(total_choice);
				total_choice=NULL;
				break;
			}
		}
		printf("你想再玩一次吗?(y or n)  ");
		scanf(" %c",&again);
		fflush(stdin);
	}while(tolower(again)=='y');
}

void display(int board[][SIZE])
{
	int row=0;                                  //Row index
	int col=0;                                  //Column index

	for(row=0;row<SIZE;row++)
	{
		printf("  +");
		for(col=0;col<SIZE;col++)
			printf("----+");
		printf("\n");
		for(col=0;col<SIZE;col++)
		printf("  |%2d%s",board[row][col],board[row][col]?"":"\b ");   //展示棋盘上的数字,当数字为0时,显示为空白
		printf("  |\n");											   
	}
	
	printf("  +");
	for(col=0;col<SIZE;col++)
		printf("----+");							//Display the bottom line
	printf("\n");								//Display the end of bottom line
}

int is_valid(int board[][SIZE],int choice)
{
	int row=0;
	int col=0;
	int rowdelta=0;                            //Row increment around a square
	int coldelta=0;							   //Column increment around a square
	int flag=0;                                //跳出循环标记
	for(row=0;row<SIZE;row++)                  //获取玩家选择数字的位置
	{
		for(col=0;col<SIZE;col++)
		{
			if(board[row][col]==choice)
			{
				flag=1;
				break;
			}
		}
		if(flag==1)
			break;
	}
	for(rowdelta=-1;rowdelta<=1;rowdelta++)
	{
		for(coldelta=-1;coldelta<=1;coldelta++)
		{//不能检查越界位置,choice所在位置,以及与choice成对角线的位置
			if(row+rowdelta>=SIZE||row+rowdelta<0||
				col+coldelta>=SIZE||col+coldelta<0||
				rowdelta==coldelta||board[row+rowdelta][col+coldelta]||rowdelta==-coldelta)
				continue;

			if(board[row+rowdelta][col+coldelta]==0)    //空白就在choice旁边,则为有效choice
				return 1;
		}
	}
	return 0;
}

void move(int board[][SIZE],int choice)
{
	int choice_row=0;                                  //存储choice的row
	int choice_col=0;								   //存储choice的col
	int zero_row=0;                                    //存储0的row
	int zero_col=0;									   //存储0的col
	int temp=0;
	int flag=0;                                        //循环跳出标记
	if(!is_valid(board,choice))
		return;
	for(choice_row=0;choice_row<SIZE;choice_row++)	  //获取choice的row,col
	{
		for(choice_col=0;choice_col<SIZE;choice_col++)
		{
			if(board[choice_row][choice_col]==choice)
			{
				flag=1;
				break;
			}
		}
		if(flag==1)
		{
			flag=0;
			break;
		}
	}
	
	for(zero_row=0;zero_row<SIZE;zero_row++)	  //获取zero的row,col
	{
		for(zero_col=0;zero_col<SIZE;zero_col++)
		{
			if(board[zero_row][zero_col]==0)
			{
				flag=1;
				break;
			}
		}
		if(flag==1)
			break;
	}

	SWAP(board[choice_row][choice_col],board[zero_row][zero_col],temp);    //交换数字
}

int is_complete(int board[][SIZE])
{
	int row=0;
	int col=0;
	int temp[SIZE][SIZE]={                   //用于检查拼图是否拼好而定义的原始拼图   
					{1,2,3,4},			  
					{5,6,7,8},			  
					{9,10,11,12},         
					{13,14,15,0}
							};

	for(row=0;row<SIZE;row++)
	{
		for(col=0;col<SIZE;col++)
		{
			if(board[row][col]!=temp[row][col])
				return 0;
		}
	}
	return 1;
}

void initial(int board[][SIZE])                     //问题就出在这里,初始化后的局面很简单
{
	int row=0;
	int col=0;
	int flag=0;                   //跳出循环的标记
	int on_left[2]={-1,0};  //往左上角偏移              
	int on_right[2]={-1,0};  //往右上角偏移
	int up=0;       //向上偏移次数
	int left=0;	 //向左偏移次数
	int right=0;	 //向右偏移次数
	int rowdelta=0;
	int coldelta=0;
	int i=0;                      //循环变量
	int j=0;

	srand(time(NULL));
	step=0;

	while(board[0][0]==1)
	{
		
		for(;;)
		{
			rowdelta=on_left[rand()%2];
			if(rowdelta==0)
			{
				coldelta=-1;
				turn_left(board);
				left++;
			}
			else
			{
				coldelta=0;
				turn_up(board);
				up++;
			}
			if(left==2)
			{//如果向左移了2次,则应该向上移3-turn_up
				for(i=0;i<3-up;i++)
				{
					turn_up(board);
				}
				//再次向左移一次
				turn_left(board);
				break;
			}
			
		
			if(up==2)
			{//如果向上移了2次,则应该向左移3-turn_left
				for(j=0;j<3-left;j++)
				{
					turn_left(board);
				}

				//再次向上移一次
				turn_up(board);
				break;
			}	
		}
	}


	for(i=0;i<3;i++)								//向下移动三步
	{
		turn_down(board);
	}

	up=0;                                          //初始化turn_up

	for(;;)												//向右上角移动
	{							
		rowdelta=on_right[rand()%2];
		if(rowdelta==0)
		{
			coldelta=1;
			turn_right(board);
			right++;
		}
		else
		{
			coldelta=0;
			turn_up(board);
			up++;
		}
		if(right==2)
		{//如果向右移了2次,则应该向上移3-turn_up
			for(i=0;i<3-up;i++)
			{
				turn_up(board);
			}
			//再右移动一次
			turn_right(board);
			break;
		}
		if(up==2)
		{//如果向上移了2次,则应该向右移3-turn_right
			for(j=0;j<3-right;j++)
			{
				turn_right(board);
			}

			//再次上移
			turn_up(board);
			break;
		}	
	}

	for(i=0;i<3;i++)								//向下移动3步
	{
		turn_down(board);
	}
	for(i=0;i<2;i++)								//向左移动2步
	{
		turn_left(board);
	}
	for(i=0;i<3;i++)								//向上移动3步
	{
		turn_up(board);
	}
	for(i=0;i<2;i++)								//向右移动2步
	{
		turn_right(board);
	}
	for(i=0;i<3;i++)								//向下移动3步
	{
		turn_down(board);
	}
	turn_left(board);								//向左移动1步
	for(i=0;i<3;i++)								//向上移动三步
	{
		turn_up(board);
	}
	turn_right(board);								//向右移动1步
	for(i=0;i<3;i++)								//向下移动三步
	{
		turn_down(board);
	}

}

void turn_left(int board[][SIZE])
{
	int row=0;
	int col=0;
	int flag=0;

	//获取0的坐标
	for(row=0;row<SIZE;row++)	  
	{
		for(col=0;col<SIZE;col++)
		{
			if(board[row][col]==0)
			{
				flag=1;
				break;
			}
		}
		if(flag==1)
		{
			flag=0;
			break;
		}
	}
	total_choice[step++]=board[row][col-1];
	move(board,board[row][col-1]);	
}

void turn_right(int board[][SIZE])
{
	int row=0;
	int col=0;
	int flag=0;

	//获取0的坐标
	for(row=0;row<SIZE;row++)	  
	{
		for(col=0;col<SIZE;col++)
		{
			if(board[row][col]==0)
			{
				flag=1;
				break;
			}
		}
		if(flag==1)
		{
			flag=0;
			break;
		}
	}
	total_choice[step++]=board[row][col+1];
	move(board,board[row][col+1]);	
}

void turn_up(int board[][SIZE])
{
	int row=0;
	int col=0;
	int flag=0;

	//获取0的坐标
	for(row=0;row<SIZE;row++)	  
	{
		for(col=0;col<SIZE;col++)
		{
			if(board[row][col]==0)
			{
				flag=1;
				break;
			}
		}
		if(flag==1)
		{
			flag=0;
			break;
		}
	}
	total_choice[step++]=board[row-1][col];
	move(board,board[row-1][col]);	
}

void turn_down(int board[][SIZE])
{
	int row=0;
	int col=0;
	int flag=0;

	//获取0的坐标
	for(row=0;row<SIZE;row++)	  
	{
		for(col=0;col<SIZE;col++)
		{
			if(board[row][col]==0)
			{
				flag=1;
				break;
			}
		}
		if(flag==1)
		{
			flag=0;
			break;
		}
	}
	total_choice[step++]=board[row+1][col];
	move(board,board[row+1][col]);	
}

运行效果如下:

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值