先叠几层甲:

该项目中很多功能和函数的实现方法肯定有更简单更优化的,本文章里的方法属于比较笨的那种,仅供新手初学者以及博主自己参考,文章中提供的代码及源文件难免会有疏忽、bug,仅供参考、学习、交流;除了正常的讨论问题、建议外,还请各位大佬键盘之下给我留点面子qaq

关于屏幕的显示和触控、图片的显示,可以参考之前的文章:关于GEC6818屏幕的驱动方法显示屏、触摸屏 本文章默认已经成功驱动屏幕。

源码和图片素材会放到文章末尾,仅供参考。

2048算是一个很经典的小游戏了,逻辑简单,开发难度易上手,因此很适合作为熟悉Linux文件IO操作的例子。

我们先不写代码,先在ps里绘制好界面还有其他图片素材(


因为GEC6818的屏幕分辨率为480*800,因此将画布大小限制在该分辨率下进行编辑
PS中可以方便的查看鼠标所在位置的坐标,要事先记下每个按键的坐标位置、判定范围以留备用
至于PS怎么用那就不在本文讲解范围内了(

游戏界面

欢迎界面(

2048方块,以及分数的数字

文字也可以通过使用字符取模软件显示在屏幕上,但我认为不如直接显示图片简单效果好,因此这里就不做说明。

工程文件结构:

2048_imgs(用于存放图片素材)、main.c(主函数)、lcd.c(屏幕控制相关函数)、ts.c(触摸屏相关函数)、func.c(2048游戏相关函数)、chardata.c(用于存放各图片文件的路径等字符串,以及位置坐标等)
至于build.sh,里面是编译命令,也可以写Makefile,不过我觉得小工程用不上所以就没写,看自己习惯就好了~

路径、坐标参考(chardata.c):

int st_blocks[16]={0};//定义一个数组用于存储16个格子的状态
//定义三种事件响应的状态,默认为0(不响应)
int st_warn=0;//弹窗了吗?
int st_over=0;//游戏寄了吗?
int st_pause=0;//游戏暂停了吗?
int st_start=1;//欢迎页面是不是还没显示?
//定义文件路径
char *homebg="2048_imgs/home.bmp";//home界面
char *mainbg="2048_imgs/main.bmp";//主界面
char *warn_rest_img="2048_imgs/warn_rest.bmp";//询问弹窗
char *warn_over_img="2048_imgs/warn_over.bmp";//游戏结束弹窗
char *warn_pause_img="2048_imgs/pause.bmp";//游戏暂停弹窗
//2,4,8,16,32,64,128,256,512,1024,2048的图片
char *a2_img="2048_imgs/2.bmp";
char *a4_img="2048_imgs/4.bmp";
char *a8_img="2048_imgs/8.bmp";
char *a16_img="2048_imgs/16.bmp";
char *a32_img="2048_imgs/32.bmp";
char *a64_img="2048_imgs/64.bmp";
char *a128_img="2048_imgs/128.bmp";
char *a256_img="2048_imgs/256.bmp";
char *a512_img="2048_imgs/512.bmp";
char *a1024_img="2048_imgs/1024.bmp";
char *a2048_img="2048_imgs/2048.bmp";
//得分的0-9字符
char *s0="2048_imgs/n0.bmp";
char *s1="2048_imgs/n1.bmp";
char *s2="2048_imgs/n2.bmp";
char *s3="2048_imgs/n3.bmp";
char *s4="2048_imgs/n4.bmp";
char *s5="2048_imgs/n5.bmp";
char *s6="2048_imgs/n6.bmp";
char *s7="2048_imgs/n7.bmp";
char *s8="2048_imgs/n8.bmp";
char *s9="2048_imgs/n9.bmp";
//定义16*16每个格子的坐标值
int a1x=382,a1y=56;
int a2x=482,a2y=56;
int a3x=582,a3y=56;
int a4x=682,a4y=56;
int a5x=382,a5y=156;
int a6x=482,a6y=156;
int a7x=582,a7y=156;
int a8x=682,a8y=156;
int a9x=382,a9y=256;
int a10x=482,a10y=256;
int a11x=582,a11y=256;
int a12x=682,a12y=256;
int a13x=382,a13y=356;
int a14x=482,a14y=356;
int a15x=582,a15y=356;
int a16x=682,a16y=356;
//定义5位得分的字符位置
int num0x=230,num0y=28;
int num1x=199,num1y=28;
int num2x=168,num2y=28;
int num3x=137,num3y=28;
int num4x=106,num4y=28;
//定义弹窗的位置
int warninfo_x=155;
int warninfo_y=108;
//定义按键的触摸判定范围
int main_rest_minx=14;//主界面的重新开始按钮
int main_rest_maxx=332;
int main_rest_miny=520;
int main_rest_maxy=595;
int warn_yes_minx=247;//重新开始弹窗yes按钮
int warn_yes_maxx=456;
int warn_yes_miny=367;
int warn_yes_maxy=443;
int warn_no_minx=570;//重新开始弹窗no按钮
int warn_no_maxx=778;
int warn_no_miny=367;
int warn_no_maxy=443;
int over_rest_minx=353;//游戏结束弹窗的重新开始按钮
int over_rest_maxx=671;
int over_rest_miny=362;
int over_rest_maxy=438;
int pause_button_minx=90;//暂停按钮
int pause_button_maxx=275;
int pause_button_miny=257;
int pause_button_maxy=443;
int pause_conti_minx=353;//游戏暂停弹窗的继续按钮
int pause_conti_maxx=671;
int pause_conti_miny=362;
int pause_conti_maxy=438;

使用一维数组(这里是st)用于存储4*4格子内的数字状态,当然用二维数组也更直观,这里按照个人习惯来就好。

以下函数具体请看注释,咱基本都写清楚了,如有疑问可在评论区讨论~(代码存在复制粘贴偷懒的情况,如果看到int a[1]之类的奇怪操作请不要奇怪,按照你的想法来就好~)

随机生成2和4以及随机位置:

void rand_sum(int *a1,int *a2)//随机生成2个2或4的随机数用于生成方块
{
    int a[2]/*用于保存2个产生的随机数*/, i;
    srand((unsigned int)time(NULL));//设置当前时间为种子
    for (i = 0; i < 2; i++){
        a[i] = rand()%2+1;//产生1~2的随机数
    }
    //传出生成的随机数2 4
    if(a[0]==1)*a1=2;
    else *a1=4;
    if(a[1]==1)*a2=2;
    else *a2=4;
    printf("num:%d %d\n",*a1,*a2);
    return;
}
void rand_time(int *a1)//随机生成1个1-2的随机数(用于随机第一次生成一个数字块还是两个数字块)
{
    int a[1]/*用于保存1个产生的随机数*/, i;
    srand((unsigned int)time(NULL));//设置当前时间为种子
    for (i = 0; i < 1; i++){
        a[i] = rand()%2+1;//产生1~2的随机数
    }
    //传出生成的随机数
    *a1=a[0];
    printf("time:%d\n",*a1);
    return;
}
void rand_sum_loc(int *a1)//随机生成1个位置
{
    int p=0,q=0;
    for(int x=0;x<16;x++)
    {
        if(st_blocks[x]==0)
        p++;
    }
    int m[p];//存储了空位的位置
    for(int x=0,y=0;x<16;x++)
    {
        if(st_blocks[x]==0)
        {
            m[y]=x;
            y++;
        }
    }
    int a[1]/*用于保存1个产生的随机数*/,i;
    srand((unsigned int)time(NULL));//设置当前时间为种子
    for (i = 0; i < 1; ++i)
    {
        a[i] = rand()%p+1;//产生1~p的随机数
    }
    printf("r=%d\n",a[0]);
    //传出生成的随机位置
    *a1=m[a[0]-1];
    return;
}

根据st数组内容打印方块:

void print_img_blocks(int num,int loc)//打印方块到格子中
{
    int cx,cy;
    switch(loc)
    {
        case 0:{cx=a1x;cy=a1y;}break;
        case 1:{cx=a2x;cy=a2y;}break;
        case 2:{cx=a3x;cy=a3y;}break;
        case 3:{cx=a4x;cy=a4y;}break;
        case 4:{cx=a5x;cy=a5y;}break;
        case 5:{cx=a6x;cy=a6y;}break;
        case 6:{cx=a7x;cy=a7y;}break;
        case 7:{cx=a8x;cy=a8y;}break;
        case 8:{cx=a9x;cy=a9y;}break;
        case 9:{cx=a10x;cy=a10y;}break;
        case 10:{cx=a11x;cy=a11y;}break;
        case 11:{cx=a12x;cy=a12y;}break;
        case 12:{cx=a13x;cy=a13y;}break;
        case 13:{cx=a14x;cy=a14y;}break;
        case 14:{cx=a15x;cy=a15y;}break;
        case 15:{cx=a16x;cy=a16y;}break;
    }
    switch(num)
    {   
        case 0:break;
        case 2:load_img(a2_img,cx,cy);break;
        case 4:load_img(a4_img,cx,cy);break;
        case 8:load_img(a8_img,cx,cy);break;
        case 16:load_img(a16_img,cx,cy);break;
        case 32:load_img(a32_img,cx,cy);break;
        case 64:load_img(a64_img,cx,cy);break;
        case 128:load_img(a128_img,cx,cy);break;
        case 256:load_img(a256_img,cx,cy);break;
        case 512:load_img(a512_img,cx,cy);break; 
        case 1024:load_img(a1024_img,cx,cy);break;
        case 2048:load_img(a2048_img,cx,cy);break;
    }
}
void load_st()//根据st数组中的状态还原打印格子中的数
{
    for(int i=0;i<16;i++)
    {
        print_img_blocks(st_blocks[i],i);
    }
}
void st_reset()//清空状态数组
{
    for(int i=0;i<16;i++)
    {
        st_blocks[i]=0;
    }
}
int st_isfull()//判断格子是否已满,是返回1,否返回0
{
    int st=1;
    for(int i=0;i<16;i++)
    {
        if(st_blocks[i]==0)
        {
            st=0;
        }
    }
    return st;
}

这段也没有什么可说的……就是根据数组里的内容照着把数字的图片显示到对应的位置上……以及判断还有没有地方qwq

这里我设定游戏开始时生成1-2个方块,可能是2也可能是4,游戏进行中的时候每次滑动只会生成一个方块,2或4,因此:

void first_rand_block()//第一次随机生成
{
    int a,b,loc,time;
    int rac[2]={0};//随机生成的方块的值
    rand_sum(&a,&b);//随机2个2或4
    rac[0]=a;rac[1]=b;
    rand_time(&time);//随机生成次数(1次或2次)
    for(int i=0;i<time;i++)
    {
        rand_sum_loc(&loc);//随机一个位置
        printf("loc:%d\n",loc);
        st_blocks[loc]=rac[i];
    }
    load_st();
}
void gamein_rand_block()//游戏中随机生成
{
    int a,b,loc;
    rand_sum(&a,&b);//随机2个2或4
    rand_sum_loc(&loc);//随机一个位置
    printf("loc:%d\n",loc);
    st_blocks[loc]=a;
    load_st();
}

滑动后根据方向移动方块:

逻辑很简单,顺着方向贴贴就好了(

void move_blocks(int z)//方块移动
{
    if(z==1)//up
    {
        for(int i=0;i<4;i++)
        {
            for(int j=4;j<16;j++)
            {
                if(st_blocks[j]!=0 && st_blocks[j-4]==0)//如果上面是空的
                {
                    st_blocks[j-4]=st_blocks[j];
                    st_blocks[j]=0;
                }
            }
        }
    }
    if(z==2)//down
    {
        for(int i=0;i<4;i++)
        {
            for(int j=0;j<12;j++)
            {
                if(st_blocks[j]!=0 && st_blocks[j+4]==0)//如果下面是空的
                {
                    st_blocks[j+4]=st_blocks[j];
                    st_blocks[j]=0;
                }
            }
        }
    }
    if(z==3)//left
    {
        for(int i=0;i<4;i++)
        {
            for(int j=0;j<16;j++)
            {
                if((j!=0 && j!=4 && j!=8 && j!=12) && st_blocks[j]!=0 && st_blocks[j-1]==0)//如果左面是空的
                {
                    st_blocks[j-1]=st_blocks[j];
                    st_blocks[j]=0;
                }
            }
        }
    }
    if(z==4)//right
    {
        for(int i=0;i<4;i++)
        {
            for(int j=0;j<16;j++)
            {
                if((j!=3 && j!=7 && j!=11 && j!=15) && st_blocks[j]!=0 && st_blocks[j+1]==0)//如果右面是空的
                {
                    st_blocks[j+1]=st_blocks[j];
                    st_blocks[j]=0;
                }
            }
        }
    }
    printf("move:\n\
%d %d %d %d\n\
%d %d %d %d\n\
%d %d %d %d\n\
%d %d %d %d\n\
",st_blocks[0],st_blocks[1],st_blocks[2],st_blocks[3],st_blocks[4],st_blocks[5],st_blocks[6],st_blocks[7]\
,st_blocks[8],st_blocks[9],st_blocks[10],st_blocks[11],st_blocks[12],st_blocks[13],st_blocks[14],st_blocks[15]);
}

方块合并:

这里的逻辑是按照方向,检测前面的方块是不是一样的数,如果是相加,并且如果相加后的方块前方还有相同的(和相加之后的方块相同)也不进行合并。

void plus_blocks(int z)//方块相加
{
    if(z==1)//up
    {
        int sta[16]={0};
        for(int i=15;i>=0;i--)
        {
            if(st_blocks[i]!=0 && i>=12 && i<16)//在最后一行
            {
                if(st_blocks[i]==st_blocks[i-4])//匹配上个
                {
                    score+=st_blocks[i];
                    st_blocks[i-4]=(st_blocks[i]+st_blocks[i-4]);
                    st_blocks[i]=0;
                    sta[i-4]=1;
                }
                else if(st_blocks[i]==st_blocks[i-8]&&st_blocks[i-4]==0 && sta[i]==0)//匹配上上个并且中间没东西
                {
                    score+=st_blocks[i];
                    st_blocks[i-8]=(st_blocks[i]+st_blocks[i-8]);
                    st_blocks[i]=0;
                    sta[i-4]=1;
                }
                else if(st_blocks[i]==st_blocks[i-12]&&st_blocks[i-4]==0 && st_blocks[i-8]==0 && sta[i]==0)//匹配上上上个并且中间没东西
                {
                    score+=st_blocks[i];
                    st_blocks[i-12]=(st_blocks[i]+st_blocks[i-12]);
                    st_blocks[i]=0;
                    sta[i-4]=1;
                }
            }
            else if(st_blocks[i]!=0 && i>=8 && i<12)//在第三行
            {
                if(st_blocks[i]==st_blocks[i-4] && sta[i]==0)//匹配上个
                {
                    score+=st_blocks[i];
                    st_blocks[i-4]=(st_blocks[i]+st_blocks[i-4]);
                    st_blocks[i]=0;
                    sta[i-4]=1;
                }
                else if(st_blocks[i]==st_blocks[i-8]&&st_blocks[i-4]==0 && sta[i]==0)//匹配上上个并且中间没东西
                {
                    score+=st_blocks[i];
                    st_blocks[i-8]=(st_blocks[i]+st_blocks[i-8]);
                    st_blocks[i]=0;
                    sta[i-4]=1;
                }
            }
            else if(st_blocks[i]!=0 && i>=4 && i<8)//在第二行
            {
                if(st_blocks[i]==st_blocks[i-4] && sta[i]==0)
                {
                    score+=st_blocks[i];
                    st_blocks[i-4]=(st_blocks[i]+st_blocks[i-4]);
                    st_blocks[i]=0;
                    sta[i-4]=1;
                }
            }
        }
    }
    if(z==2)//down
    {
        int sta[16]={0};
        for(int i=0;i<12;i++)
        {
            if(st_blocks[i]!=0 && i>=0 && i<4)//在第一行
            {
                if(st_blocks[i]==st_blocks[i+4])//匹配下个
                {
                    score+=st_blocks[i];
                    st_blocks[i+4]=(st_blocks[i]+st_blocks[i+4]);
                    st_blocks[i]=0;
                    sta[i+4]=1;
                }
                else if(st_blocks[i]==st_blocks[i+8]&&st_blocks[i+4]==0 && sta[i]==0)//匹配下下个并且中间没东西
                {
                    score+=st_blocks[i];
                    st_blocks[i+8]=(st_blocks[i]+st_blocks[i+8]);
                    st_blocks[i]=0;
                    sta[i+4]=1;
                }
                else if(st_blocks[i]==st_blocks[i+12]&&st_blocks[i+4]==0 && st_blocks[i+8]==0 && sta[i]==0)//匹配下下下个并且中间没东西
                {
                    score+=st_blocks[i];
                    st_blocks[i+12]=(st_blocks[i]+st_blocks[i+12]);
                    st_blocks[i]=0;
                    sta[i+4]=1;
                }
            }
            else if(st_blocks[i]!=0 && i>=4 && i<8)//在第二行
            {
                if(st_blocks[i]==st_blocks[i+4] && sta[i]==0)//匹配下个
                {
                    score+=st_blocks[i];
                    st_blocks[i+4]=(st_blocks[i]+st_blocks[i+4]);
                    st_blocks[i]=0;
                    sta[i+4]=1;
                }
                else if(st_blocks[i]==st_blocks[i+8]&&st_blocks[i+4]==0 && sta[i]==0)//匹配下下个并且中间没东西
                {
                    score+=st_blocks[i];
                    st_blocks[i+8]=(st_blocks[i]+st_blocks[i+8]);
                    st_blocks[i]=0;
                    sta[i+4]=1;
                }
            }
            else if(st_blocks[i]!=0 && i>=8 && i<12)//在第三行
            {
                if(st_blocks[i]==st_blocks[i+4] && sta[i]==0)
                {
                    score+=st_blocks[i];
                    st_blocks[i+4]=(st_blocks[i]+st_blocks[i+4]);
                    st_blocks[i]=0;
                    sta[i+4]=1;
                }
            }
        }
    }
    if(z==3)//left
    {
        int sta[16]={0};
        for(int i=15;i>=0;i--)
        {
            if(st_blocks[i]!=0&&(i!=0 && i!=4 && i!=8 && i!=12)&&(i==3||i==7||i==11||i==15))//在第4列
            {
                if(st_blocks[i]==st_blocks[i-1])//匹配左1个
                {
                    score+=st_blocks[i];
                    st_blocks[i-1]=(st_blocks[i]+st_blocks[i-1]);
                    st_blocks[i]=0;
                    sta[i-1]=1;
                }
                else if(sta[i]==0 && st_blocks[i-1]==0 && st_blocks[i]==st_blocks[i-2])//匹配左左1个并且中间没东西
                {
                    score+=st_blocks[i];
                    st_blocks[i-2]=(st_blocks[i]+st_blocks[i-2]);
                    st_blocks[i]=0;
                    sta[i-1]=1;
                }
                else if(sta[i]==0 && st_blocks[i-1]==0 && st_blocks[i-2]==0 && st_blocks[i]==st_blocks[i-3])//匹配左左左1个并且中间没东西
                {
                    score+=st_blocks[i];
                    st_blocks[i-3]=(st_blocks[i]+st_blocks[i-3]);
                    st_blocks[i]=0;
                    sta[i-1]=1;
                }
            }
            else if(st_blocks[i]!=0&&(i!=0 && i!=4 && i!=8 && i!=12)&&(i==2||i==6||i==10||i==14))//在第3列
            {
                if(sta[i]==0 && st_blocks[i]==st_blocks[i-1])//匹配左1个
                {
                    score+=st_blocks[i];
                    st_blocks[i-1]=(st_blocks[i]+st_blocks[i-1]);
                    st_blocks[i]=0;
                    sta[i-1]=1;
                }
                else if(sta[i]==0 && st_blocks[i-1]==0 && st_blocks[i]==st_blocks[i-2])//匹配左左1个并且中间没东西
                {
                    score+=st_blocks[i];
                    st_blocks[i-2]=(st_blocks[i]+st_blocks[i-2]);
                    st_blocks[i]=0;
                    sta[i-1]=1;
                }
            }
            else if(st_blocks[i]!=0&&(i!=0 && i!=4 && i!=8 && i!=12)&&(i==1||i==5||i==9||i==13))//在第二列
            {
                if(sta[i]==0 && st_blocks[i]==st_blocks[i-1])//匹配左1个
                {
                    score+=st_blocks[i];
                    st_blocks[i-1]=(st_blocks[i]+st_blocks[i-1]);
                    st_blocks[i]=0;
                    sta[i-1]=1;
                }
            }
        }
    }
    if(z==4)//right
    {
        int sta[16]={0};
        for(int i=0;i<16;i++)
        {
            if(st_blocks[i]!=0&&(i!=3 && i!=7 && i!=11 && i!=15)&&(i==0||i==4||i==8||i==12))//在第1列
            {
                if(st_blocks[i]==st_blocks[i+1])//匹配右1个
                {
                    score+=st_blocks[i];
                    st_blocks[i+1]=(st_blocks[i]+st_blocks[i+1]);
                    st_blocks[i]=0;
                    sta[i+1]=1;
                }
                else if(sta[i]==0 && st_blocks[i+1]==0 && st_blocks[i]==st_blocks[i+2])//匹配右右1个并且中间没东西
                {
                    score+=st_blocks[i];
                    st_blocks[i+2]=(st_blocks[i]+st_blocks[i+2]);
                    st_blocks[i]=0;
                    sta[i+1]=1;
                }
                else if(sta[i]==0 && st_blocks[i+1]==0 && st_blocks[i+2]==0 && st_blocks[i]==st_blocks[i+3])//匹配右右右1个并且中间没东西
                {
                    score+=st_blocks[i];
                    st_blocks[i+3]=(st_blocks[i]+st_blocks[i+3]);
                    st_blocks[i]=0;
                    sta[i+1]=1;
                }
            }
            else if(st_blocks[i]!=0&&(i!=3 && i!=7 && i!=11 && i!=15)&&(i==1||i==5||i==9||i==13))//在第2列
            {
                if(sta[i]==0 && st_blocks[i]==st_blocks[i+1])//匹配右1个
                {
                    score+=st_blocks[i];
                    st_blocks[i+1]=(st_blocks[i]+st_blocks[i+1]);
                    st_blocks[i]=0;
                    sta[i+1]=1;
                }
                else if(sta[i]==0 && st_blocks[i+1]==0 && st_blocks[i]==st_blocks[i+2])//匹配左左1个并且中间没东西
                {
                    score+=st_blocks[i];
                    st_blocks[i+2]=(st_blocks[i]+st_blocks[i+2]);
                    st_blocks[i]=0;
                    sta[i+1]=1;
                }
            }
            else if(st_blocks[i]!=0&&(i!=3 && i!=7 && i!=11 && i!=15)&&(i==2||i==6||i==10||i==14))//在第3列
            {
                if(sta[i]==0 && st_blocks[i]==st_blocks[i+1])//匹配右1个
                {
                    score+=st_blocks[i];
                    st_blocks[i+1]=(st_blocks[i]+st_blocks[i+1]);
                    st_blocks[i]=0;
                    sta[i+1]=1;
                }
            }
        }
    }
    printf("%d %d %d %d\n\
%d %d %d %d\n\
%d %d %d %d\n\
%d %d %d %d\n\
",st_blocks[0],st_blocks[1],st_blocks[2],st_blocks[3],st_blocks[4],st_blocks[5],st_blocks[6],st_blocks[7]\
,st_blocks[8],st_blocks[9],st_blocks[10],st_blocks[11],st_blocks[12],st_blocks[13],st_blocks[14],st_blocks[15]);
}

打印分数:

取余获取分数的每一位,然后打印到屏幕上

void print_score()//打印得分
{
    printf("%d\n",score);
    if(score>=99999)return;
    int a[5]={0};
    a[0]=score%10;
    a[1]=(score/10)%10;
    a[2]=(score/100)%10;
    a[3]=(score/1000)%10;
    a[4]=(score/10000)%10;
    char *num_cha=NULL;
    int loc_x,loc_y;
    for(int i=0;i<5;i++)
    {
        switch(a[i])
        {
            case 0:num_cha=s0;break;
            case 1:num_cha=s1;break;
            case 2:num_cha=s2;break;
            case 3:num_cha=s3;break;
            case 4:num_cha=s4;break;
            case 5:num_cha=s5;break;
            case 6:num_cha=s6;break;
            case 7:num_cha=s7;break;
            case 8:num_cha=s8;break;
            case 9:num_cha=s9;break;
        }
        switch(i)
        {
            case 0:{loc_x=num0x;loc_y=num0y;}break;
            case 1:{loc_x=num1x;loc_y=num1y;}break;
            case 2:{loc_x=num2x;loc_y=num2y;}break;
            case 3:{loc_x=num3x;loc_y=num3y;}break;
            case 4:{loc_x=num4x;loc_y=num4y;}break;
        }
        load_img(num_cha,loc_x,loc_y);
    }
    
}

判定游戏是否无法继续:

遍历每个方块看看周围有没有可以合并的方块

int game_isover()//判定游戏是否无法继续
{
    if(!(st_isfull()))return 1;//如果格子还没满就直接滚
    int isover=0;
    for(int i=0;i<16;i++)
    {
        if(i==0||i==3||i==12||i==15)//四角
        {
            if(i==0 && (st_blocks[i]==st_blocks[i+1]||st_blocks[i]==st_blocks[i+4]))
            isover=1;
            else if(i==3 && (st_blocks[i]==st_blocks[i-1]||st_blocks[i]==st_blocks[i+4]))
            isover=1;
            else if(i==12 && (st_blocks[i]==st_blocks[i+1]||st_blocks[i]==st_blocks[i-4]))
            isover=1;
            else if(i==15 && (st_blocks[i]==st_blocks[i-1]||st_blocks[i]==st_blocks[i-4]))
            isover=1;
        }
        else if(i==1||i==2||i==4||i==8||i==7||i==11||i==13||i==14)//在四边
        {
            if((i==1||i==2) && (st_blocks[i]==st_blocks[i-1]||st_blocks[i]==st_blocks[i+1]||st_blocks[i]==st_blocks[i+4]))
            isover=1;
            else if((i==4||i==8) && (st_blocks[i]==st_blocks[i-4]||st_blocks[i]==st_blocks[i+4]||st_blocks[i]==st_blocks[i+1]))
            isover=1;
            if((i==7||i==11) && (st_blocks[i]==st_blocks[i-4]||st_blocks[i]==st_blocks[i+4]||st_blocks[i]==st_blocks[i-1]))
            isover=1;
            if((i==13||i==14) && (st_blocks[i]==st_blocks[i-1]||st_blocks[i]==st_blocks[i+1]||st_blocks[i]==st_blocks[i-4]))
            isover=1;
        }
        else if(i==5||i==6||i==9||i==10)//在中间
        {
            if(st_blocks[i]==st_blocks[i-4]||st_blocks[i]==st_blocks[i+4]||st_blocks[i]==st_blocks[i-1]||st_blocks[i]==st_blocks[i+1])
            isover=1;
        }
    }
    return isover;
}

滑动时调用以上函数:

int scr_num_con(int z)//根据滑动方向执行不同的操作
{
        //合并移动数字方块
        plus_blocks(z);
        move_blocks(z);
        //再随机生成一个
        if(!(st_isfull()))
        {
            gamein_rand_block();//随机生成方块
            load_img(mainbg,0,0);//加载主界面
            load_st();//打印方块
            print_score();//打印得分
            return 1;
        }
}

游戏开始时的初始化:

void game_start()
{
    score=0;
    lcd_clear(0x00ffffff);//清屏
    load_img(mainbg,0,0);//加载主界面
    print_score();//打印得分
    st_reset();//清空状态数组
    first_rand_block();//初始化格子,生成最开始的1个或2个数字
}

检测触摸操作:

判断坐标是否落在按钮的范围内即可

void touch_scan()
{
    while(1)
    {
        if(!(game_isover()))//判断游戏是否结束
        {
            load_img(warn_over_img,warninfo_x,warninfo_y);//游戏结束弹窗
            st_over=1;//游戏结束,不响应弹窗以外的触摸
        }
        int z=get_touchscreen_index(&x,&y);//扫描触摸屏状态
        if(x>0 && x<50*1.28 && y>0 && y<50*1.28)//点击屏幕左上角时退出游戏
        {
            exit(-1);
        }
        if(st_warn==0 && st_over==0 && st_pause==0 && x>=main_rest_minx && x<main_rest_maxx &&\
        y>=main_rest_miny && y<main_rest_maxy)//点击主界面的重新开始
        {
            load_img(warn_rest_img,warninfo_x,warninfo_y);//弹窗询问
            st_warn=1;//弹窗,不响应弹窗以外触摸
        }
        if(st_warn==1 && x>=warn_yes_minx && x<warn_yes_maxx &&\
        y>=warn_yes_miny && y<warn_yes_maxy)//如果点击弹窗内的确定
        {
            st_warn=0;
            return;
            //重新开始游戏
        }
        if(st_warn==1 && x>=warn_no_minx && x<warn_no_maxx &&\
        y>=warn_no_miny && y<warn_no_maxy)//如果点击弹窗内的取消
        {
            st_warn=0;
            load_img(mainbg,0,0);//加载主界面
            load_st();//根据st数组中的状态还原打印格子中的数
            print_score();//打印得分
            //继续游戏
        }
        if(st_warn==0 && st_over==0 && st_pause==0 && x>=pause_button_minx && x<pause_button_maxx &&\
        y>=pause_button_miny && y<pause_button_maxy)//点击主界面的暂停
        {
            load_img(warn_pause_img,warninfo_x,warninfo_y);
            st_pause=1;//弹窗,不响应弹窗以外触摸
        }
        if(st_pause==1 && x>=pause_conti_minx && x<pause_conti_maxx && y>=pause_conti_miny &&\
        y<pause_conti_maxy)//如果点击暂停弹窗内的继续
        {
            st_pause=0;
            load_img(mainbg,0,0);//加载主界面
            load_st();//根据st数组中的状态还原打印格子中的数
            print_score();//打印得分
            //继续游戏
        }
        if(st_warn==0 && st_over==0 && st_pause==0 && z!=-1)//滑动
        {
            scr_num_con(z);
        }
        if(st_over==1 && x>=over_rest_minx && x<over_rest_maxx && y>=over_rest_miny &&\
        y<over_rest_maxy)//如果点击游戏结束弹窗内的按钮
        {
            st_over=0;
            return;
            //重新开始游戏
        }
    }
}

主函数:

int main()
{
    int fd=lcd_init();//初始化显示屏
    lcd_clear(0x00ffffff);//清屏
    load_img(homebg,0,0);//加载欢迎界面
    while(1)
    {
        int z=get_touchscreen_index(&x,&y);
        if(st_start==1 && z==-1)//还在欢迎界面时点击屏幕开始游戏
            {
                st_start=0;
            }
        while(st_start==0)
        {
            game_start();
            touch_scan();
        }
    }
    lcd_uninit(fd);
}

好了,这就是游戏的所有核心代码啦,编译后传到开发板运行试试看~

欢迎界面

游戏界面

游戏寄力(悲

游戏暂停

重新开始

那么本项目就到这里啦,下面放出源码和图片素材!

点击下载