STM32实现2048游戏(二) 移植到STM32
0赞之前,用c实现了2048,虽然有点小bug,关于这个bug,我的解决方法是,先将数据进行移位,保证非零的数据都在一边,这样,再合并数据就没有之前出现的那个bug了。
移植到SMT32也比较容易的,因为是用c代码写的,所以直接将代码移植过来就好了。然后封装一个函数,接收输入,对二位数组进行操作。封装这个函数,方便main函数调用。另外一个要注意的地方,在产生随机数字的时候,用到了srand(time(0)),在STM32中,是没有time(0)这个函数的。所以在产生随机种子的这个地方要更改下。
在程序中,我是使用数组的值来作为参数,产生随机种子的。而且产生随机数字,不像用上一次那样只用一个函数来实现了,是用4个函数来实现,每个函数使用的不同的数组的值作为参数。
u8 gennew_right()
{
u8 i;
u8 j;
u8 k=0;
srand(pane[2][2]+pane[0][2]+pane[1][3]);
while(1)
{
i=rand()%4;
j=rand()%4;
if(pane[i][j] == 0)
{
pane[i][j] = 2;
break;
}
k++;
if(k>200)
break;
}
return 0;
}
u8 gennew_left()
{
u8 i;
u8 j;
u8 k=0;
srand(pane[1][2]+pane[3][2]+pane[3][3]);
while(1)
{
i=rand()%4;
j=rand()%4;
if(pane[i][j] == 0)
{
pane[i][j] = 2;
break;
}
k++;
if(k>200)
break;
}
return 0;
}
u8 gennew_up()
{
u8 i;
u8 j;
int k=0;
srand(pane[0][1]+pane[1][2]+pane[2][3]);
while(1)
{
i=rand()%4;
j=rand()%4;
if(pane[i][j] == 0)
{
pane[i][j] = 2;
break;
}
k++;
if(k>200)
break;
}
return 0;
}
u8 gennew_down()
{
u8 i;
u8 j;
u8 k=0;
srand(pane[3][2]+pane[3][0]+pane[0][3]);
while(1)
{
i=rand()%4;
j=rand()%4;
if(pane[i][j] == 0)
{
pane[i][j] = 2;
break;
}
k++;
if(k>200)
break;
}
return 0;
}这个也是比较好理解的。对于封装的函数:
u8 game_process(u8 up, u8 down, u8 right, u8 left)
{
if( left )
{
zuoyi(pane[0]);
zuoyi(pane[1]);
zuoyi(pane[2]);
zuoyi(pane[3]);
gennew_left();
return 1;
}
else if( right)
{
youyi(pane[0]);
youyi(pane[1]);
youyi(pane[2]);
youyi(pane[3]);
gennew_right();
return 1;
}
else if( up)
{
shangyi(0);
shangyi(1);
shangyi(2);
shangyi(3);
gennew_up();
return 1;
}
else if( down)
{
xiayi(0);
xiayi(1);
xiayi(2);
xiayi(3);
gennew_down();
return 1;
}
else
{
return 0;
}
}其实就是根据输入的参数,来执行不同的操作,实际上就是改变数组的值。
最后一个关键的就是怎么在TFT上显示游戏画面。之前实现了在TFT上显示一副图片,利用这个,只要在不同的地方显示需要的图片,不就实现2048界面了。
首先是在网上找2048各个数值的图片,然后使用软件将图片的内容转换为数组。那接下来的工作就简单了,将数组的值发送给TFT,就显示画面了。
如下,就是图片数组的一部分。
总的来说,2048界面分为16个部分,每个部分是各个数值的图片。如0对应数值0的图片,64对应数值64的图片。因此要显示界面,就把每个部分的图片显示了,界面就有了。
来回顾下TFT显示数据,TFT显示数据,首先指定显示的窗口大小,再指定起始坐标,然后不断的发显示数据,那么数据就会依次的显示在TFT上了,这就实现了显示图片的效果了。
那么数据从什么地方来,当然就是从之前保存的数组中来了,但是数组是保存了所有图片的数据,所以显示的时候,要指定图片在数组中的起始位置。那么显示一个部分的程序就如下了:
void GUI_Dis2048Picture(u8 x, u16 y, u8 length, u16 high,u16 data)
{
u16 temp=0,tmp=0,num=0;
u32 address=0;
u16 i=data;
switch(i) {
case 0: address = 0; break;
case 2: address = 1680; break;
case 4: address = 1680*2; break;
case 8: address = 1680*3; break;
case 16: address = 1680*4; break;
case 32: address = 1680*5; break;
case 64: address = 1680*6; break;
case 128: address = 1680*7; break;
case 256: address = 1680*8; break;
default: address = 0;
}
LCD_setwindow(x,y,x+length-1,y+high-1);
num=length*high*2;
do
{
//temp=pic[tmp]|( pic[tmp+1]<<8);
temp=gImage[address+tmp+1];
temp=temp<<8;
temp=temp|gImage[address+tmp];
LCD_WR_DATA(temp);//ÖðµãÏÔʾ
tmp+=2;
}while(tmp<num);
}首先通过判断显示的值是什么,得到数组的起始地址。然后根据输入的坐标以及图片的宽度和高度,设定窗口大小以及显示的坐标位置。然后就不断的输入值就好了。
还有一个东西要实现,就是按键的程序,因为要控制游戏,就需要输入,最简单的方式,就是通过按键输入。这部分程序,太简单,就不再说明了。
在主函数中,先判断按键是否输入,然后对输入进行处理,最后再显示界面。核心代码就是以下:
while(1)
{
while(1){
KEY_Scan();
ischange = game_process(up, down, right, left);
left = 0;
right =0;
up =0;
down =0;
if(ischange)
for(i=0; i<4; i++)
for(j=0; j<4; j++)
{
GUI_Dis2048Picture(j*30, i*30, 30, 30,pane[i][j]);
}
ischange=0;
if(isfailure())
{
LCD_Clear(BLACK );//ÇåÆÁ
for(i=0; i<4; i++)
LCD_ShowBigNum4(30,30,0);//ÏÔʾËĸö30*60´óСµÄ×ÖÌå
break;
}
if(iswin())
{
LCD_Clear(BLACK );//ÇåÆÁ
LCD_ShowBigNum4(30,30,2048);//ÏÔʾËĸö30*60´óСµÄ×ÖÌå
break;
}
}
}当然,在程序开头,要定义数组,并赋初值。然后再定义几个全局变量。
u16 pane[4][4] = {2,0,0,0,
0,0,0,0,
0,0,0,0,
0,0,0,0};
u8 up=0,down=0,left=0,right=0;总体来说,在STM32上实现2048不复杂。
以下是游戏的截图。



