⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ptgame.c

📁 多功能MP3代码
💻 C
📖 第 1 页 / 共 2 页
字号:
#include "COMM.H"
//拼图游戏代码
//支持 3*3 4*4 5*5三个等级,要继续添加也是比较容易的
//基本只要修改图片编号Cur_Table的大小,PT_Size的大小就可以了
//不过要注意不要超出数据类型的范围						    
//正点原子@SCUT
//2009/05/30 
//V1.2												  

//存储在sram里面的 图片起始地址(在SD卡上) 列表
u32 *Pic_Addr=(u32*)iclip;//注意 0:表示预览图片的地址 1~n,表示1~n块图片的地址
u8 Cur_Table[26];//图片编号存储列表	5*5时大小为25+1=26

u8 Xscal;        //倍乘数
//这四个变量需要保存到EEPROM里面
u8 PT_Size=3;    //拼图游戏的难度级别 3、4两个值

u8  PT_New=0; //是否已经在玩?1,没有在玩,必须更新。0,已经在玩,但是未完成,可以不更新。
u16 PT_Step=0;//拼图所用步骤
u16 PT_Time=0;//拼图所用时间	
								   
const u8 *PTGmenu_F1[1]={"拼图游戏"};//第1级父目录目录
const u8 *PTGmenu_S1[4]={"继续","新游戏","最佳排行","游戏设置"};//第1级子目录
const u8 *PTGmenu_S2[3]={"简单","一般","困难"}; //第2级子目录 设置	 

#define PT_BASIC 1 //基本信息
#define PT_TABLE 2 //图表信息	 

//保存当前游戏信息
//地址区间:412~443
void Save_PTG_Info(u8 type)
{			 
	u8 i;
	if(type==PT_BASIC)//保存基本信息
	{										
		FM24C16_WriteOneByte(412,PT_Size);//保存图片大小
		FM24C16_WriteOneByte(413,PT_New); //保存是否已经在玩
		//保存当前所用步骤
		FM24C16_WriteLenByte(414,PT_Step,2);	
		//保存当前所用时间
		FM24C16_WriteLenByte(416,PT_Time,2);
	}else if(type==PT_TABLE)//保存图标信息
	{
		for(i=0;i<26;i++)FM24C16_WriteOneByte(418+i,Cur_Table[i]);//保存当前图表信息	  
	}
}
//读取当前游戏信息
//地址区间:412~443 
void Read_PTG_Info(u8 type)
{			 
	u8 i;
	if(type==PT_BASIC)//读取基本信息
	{										
		PT_Size=FM24C16_ReadOneByte(412);//读取图片大小
		PT_New=FM24C16_ReadOneByte(413); //读取是否已经在玩
		//读取当前所用步骤	    
		PT_Step=FM24C16_ReadLenByte(414,2);	 	   
		//读取当前所用时间
		PT_Time=FM24C16_ReadLenByte(416,2);		   
	}else if(type==PT_TABLE)//保存图标信息
	{
		for(i=0;i<26;i++)Cur_Table[i]=FM24C16_ReadOneByte(418+i);//读取当前图表信息	  
	}
}
//保存最佳值
//level:等级 0~2 
// step:步数
// time:用时
//地址区间:444~	455
void Save_PTG_Best(u8 level,u16 step,u16 time)
{		
	//保存当前所用步数
	FM24C16_WriteLenByte(444+level*4,step,2); 	 		
	//保存当前所用时间
	FM24C16_WriteLenByte(446+level*4,time,2);	   	
}
//读取最佳值
//level:等级 0~2 == 3 4 5 
// step:步数
// time:用时
//地址区间:444~	455
void Read_PTG_Best(u8 level,u16 *step,u16 *time)
{				
	//读取当前所用步骤	
	*step=FM24C16_ReadLenByte(444+level*4,2); 	 
	//读取当前所用时间
	*time=FM24C16_ReadLenByte(446+level*4,2); 			
}

//对指定列表,得到图片起始坐标点
//这个函数与LCD显示有关
//table:固定区域值 0~PT_Size*PT_Size
//xpos :x坐标值
//ypos :y坐标值	
//CHECK OK 09/05/30			 
void Get_Ps_Addr(u8 table,u8 *xpos,u8 *ypos)
{
	u8 x,y;						 
	for(y=0;y<PT_Size;y++)
	{
		for(x=0;x<PT_Size;x++)
		{
			if(table==y*PT_Size+x)
			{
				*xpos=Xscal*x+5;
				*ypos=Xscal*y+5;
				return;
			}
		}
	}
	if(table==PT_Size*PT_Size)//第PT_Size*PT_Size格的起始地址
	{
		*xpos=Xscal*(PT_Size-1)+5;
		*ypos=Xscal*PT_Size+5;
	}
}
/////////////////////////////////////////////////////////////////////
//检查拼图游戏获胜的算法
//返回值:0,没成功;1,成功了
//支持从3*3~15*15的棋盘大小
//CHECK OK 09/05/30
u8 PT_Win_Chk(void)
{
	u8 t;
	u8 size;
	size=PT_Size*PT_Size; 
	for(t=0;t<size;t++){if(Cur_Table[t]!=t)break;}    
	if(t==size)return 1;
	return 0;
}
//初始化(生成随机位置)	 
//带检测拼图能否完成的算法
//CHECK OK 09/05/30
void PT_Map_Init(void)
{		 
	u8 size;		 
	u8 i,t,a, b;	 
	u8 d=1;
	signed char w,h;	 
	size=PT_Size*PT_Size;	 								  
	srand(RTC->CNTL);//得到种子	   
	for(i=0;i<size;i++)Cur_Table[i]=i;	  
	Cur_Table[size]=size-1;  //最后一个图片,必须放在原位,否则游戏无法完成 
	// 初始化(生成随机位置)	 	   
	i=0;
	while(i++<size||d==0)// 交换至少单位数量次
	{
		do 	
		{										  
			a = rand()%(size);			   
			b = rand()%(size);
		}while(a==b);   
		t=Cur_Table[a];
		Cur_Table[a]=Cur_Table[b];
		Cur_Table[b]=t;
		// 计算距离,必须要模为1有解
		if(Cur_Table[a]==(size-1)|| Cur_Table[b]==(size-1))
		{
			w=a%PT_Size-b%PT_Size+1;
			h=a/PT_Size-b/PT_Size;
			w=w<0?-w:w;
			h=h<0?-h:h;
			d=(d+w+h)%2;
		}else d=!d;	 
	}	 
	for(i=0;i<size;i++)
	{
		if(Cur_Table[i]==size-1){Cur_Table[i]=size;break;}	   
	}
}

//装载游戏图片
//支持从3*3~15*15的棋盘大小
//CHECK OK 09/05/30
void Load_Game_PIC(void) 
{
	FileInfoStruct TempPic;//部分图片的临时存放空间	    
	u8 t;
	u8 temp;
	u8 tempx,tempy; 
	u8 size;
	size=PT_Size*PT_Size;   									  
	TempPic.F_StartCluster=Pic_Addr[0];//加载预览图片		   
	TempPic.F_Type=T_BMP;//指定为BMP图片
	AI_LoadPicFile(&TempPic,3,242,79,318);//装载预览图片 
	//加载	  
	for(t=0;t<size+1;t++)
	{
		temp=Cur_Table[t];
		Get_Ps_Addr(t,&tempx,&tempy);   
		if(temp==size)//空格所在区域,填充灰色	
		{
		 	TFT_Fill(tempx,tempy,tempx+Xscal-2,tempy+Xscal-2,LGRAY);	 
		}else
		{
			TempPic.F_StartCluster=Pic_Addr[temp+1];//图片地址		   
			AI_LoadPicFile(&TempPic,tempx,tempy,tempx+Xscal-1,tempy+Xscal-1);	 
		}
	}	 
}
//sour:按键所按的固定编号
//dest:空格所在的固定编号
//空格一定是在dest区里面
//CHECK OK 09/05/30
void Move_Pic(u8 sour,u8 dest)
{
	FileInfoStruct PicPart;//部分图片的临时存放空间	    
	u8 pic_real_addr;
	u8 tempx,tempy;			 

	pic_real_addr=Cur_Table[sour]+1;//得到图片的编号地址 
	PicPart.F_StartCluster=Pic_Addr[pic_real_addr];
	PicPart.F_Type=T_BMP;//指定为BMP图片	
	//清空sour区的图片,就是把空格移到这个区
	Get_Ps_Addr(sour,&tempx,&tempy);//得到源坐标   
	TFT_Fill(tempx,tempy,tempx+Xscal-2,tempy+Xscal-2,LGRAY);											    	 
	//把sour区的图片部分显示到dest区
	Get_Ps_Addr(dest,&tempx,&tempy);//得到目标坐标
	AI_LoadPicFile(&PicPart,tempx,tempy,tempx+Xscal-1,tempy+Xscal-1);												 
	Cur_Table[dest]=Cur_Table[sour];//把sour区的图片编号赋给dest区
	Cur_Table[sour]=PT_Size*PT_Size;//空格在sour区了,调换完成 	
}   
	    
//返回值:PT_Size*PT_Size+1,不需要移动
//0~PT_Size*PT_Size 需要移动,与key交换
//拼图游戏的核心算法		   
//支持从3*3~15*15的棋盘大小
//CHECK OK 09/05/30
u8 Need_Move(u8 key)
{
	u8 temp;
	u8 size;
	u8 i;
	size=PT_Size*PT_Size;	  
	if(Cur_Table[key]==size)return size+1;//点中了空格,不移动
	else 
	{
		///////////////////////////////////判断是不是需要减PT_Size	 
		if(key>=PT_Size)//判断减PT_Size(3,4,5...)
		{
			if(key==size)temp=size-1;//按中了最后一个 9,对于这个按键,-1相当于其他按键-size
			else temp=key-PT_Size;
			if(Cur_Table[temp]==size)return temp;//空格与此次按键值相邻,返回空格所在地址
		}	
		///////////////////////////////////判断是不是需要加PT_Size     
		if(key<(size-PT_Size))//判断加PT_Size
		{
			temp=key+PT_Size;
			if(Cur_Table[temp]==size)return temp;//空格与此次按键值相邻,返回空格所在地址
		}    
		///////////////////////////////////判断是不是需要减1 
		for(i=0;i<PT_Size;i++)//边际处理,3:0,3,6;4:0,4,8,12;5:0,5,10,15,20....这些数值不需要减1
		{
			if(key==PT_Size*i)break;
		}
		if(i==PT_Size)//需要减1的
		{
			temp=key-1;			    
			if(Cur_Table[temp]==size)return temp;//空格与此次按键值相邻,返回空格所在地址
		}	 
		///////////////////////////////////判断是不是需要加1
		for(i=0;i<PT_Size;i++)//边际处理
		{
			if((key+1)==PT_Size*i)break;
		}
		if(i==PT_Size)//需要加1的
		{
			temp=key+1;//判断+1		 
		    if(temp==(size+1))return size+1;//不需要移动  
			if(Cur_Table[temp]==size)return temp;//空格与此次按键值相邻,返回空格所在地址
		}	 
		return size+1;//不需要移动
	}
}
/////////////////////////////////////////////////////////////////////
//拼图游戏的按键值获取函数
//返回按键值 
//CHECK OK 09/05/30
u8 PTGame_Key_To_Num(void)
{
	u8 t,ytemp;
	if(Is_In_Area(100,300,133,316))return 0XFF;//选择了退出按键,退出模式		 
	for(t=0;t<PT_Size;t++)//返回常规按键
	{	  		   	
		for(ytemp=0;ytemp<PT_Size;ytemp++)
		if(Is_In_Area(5+Xscal*t,5+Xscal*ytemp,5+Xscal*(t+1),5+Xscal*(ytemp+1)))return t+ytemp*PT_Size+1;
	}    
	if(PT_Size==3&&Is_In_Area(159,236,236,313))return 10;
	else if(PT_Size==4&&Is_In_Area(179,237,237,314))return 17;
	else if(PT_Size==5&&Is_In_Area(188,234,234,280))return 26;
	return 0;//按键无效
} 				    
//显示数据
//显示步骤和时间
//CHECK OK 09/05/30
void PTGame_Show_Msg(void)
{

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -