?? ptgame.c
字號:
#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_WriteOneByte(414,(PT_Step>>8)&0xff);
FM24C16_WriteOneByte(415,PT_Step&0xff);
//保存當前所用時間
FM24C16_WriteOneByte(416,(PT_Time>>8)&0xff);
FM24C16_WriteOneByte(417,PT_Time&0xff);
}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_ReadOneByte(414);
PT_Step<<=8;
PT_Step+=FM24C16_ReadOneByte(415);
//讀取當前所用時間
PT_Time=FM24C16_ReadOneByte(416);
PT_Time<<=8;
PT_Time+=FM24C16_ReadOneByte(417);
}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_WriteOneByte(444+level*4,(step>>8)&0xff);
FM24C16_WriteOneByte(445+level*4,step&0xff);
//保存當前所用時間
FM24C16_WriteOneByte(446+level*4,(time>>8)&0xff);
FM24C16_WriteOneByte(447+level*4,time&0xff);
}
//讀取最佳值
//level:等級 0~2 == 3 4 5
// step:步數
// time:用時
//地址區間:444~ 455
void Read_PTG_Best(u8 level,u16 *step,u16 *time)
{
//讀取當前所用步驟
*step=FM24C16_ReadOneByte(444+level*4);
*step<<=8;
*step+=FM24C16_ReadOneByte(445+level*4);
//讀取當前所用時間
*time=FM24C16_ReadOneByte(446+level*4);
*time<<=8;
*time+=FM24C16_ReadOneByte(447+level*4);
}
//對指定列表,得到圖片起始坐標點
//這個函數與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;//按鍵無效
}
//在指定位置開始顯示四個數字
//x,y:開始坐標
//CHECK OK 09/05/30
void Show_4Num(u8 x,u16 y,u16 num)
{
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -