2408 c++ 小游戏

编译环境 : arm-linux-gcc

#include <sys/mman.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <linux/input.h>
#include <pthread.h>
#include <signal.h>

int *plcd = NULL;

// statu 表示选择的是 理科版,文科版,经典版
int statu = 0;

// flag 用来标识"返回"键是否被点击
int flag = 0;
pthread_t pid;


// 初始化矩形数字
 int matrix[4][4] =
 {
    0, 0, 0, 0,
    0, 0, 0, 0,
    0, 0, 0, 2,
    0, 4, 0, 2,
 };

 // 随机矩阵
int s[] = 
{
    2,4,2,2,2
};

 //临时数组,用来保存matrix 的值
 int ck[4][4] =
 {
    0, 0, 0, 0,
    0, 0, 0, 0,
    0, 0, 0, 0,
    0, 0, 0, 0,
 };

//枚举类型 表示手指滑动方向
enum finger_move
{
    MOVE_LEFT = 1,
    MOVE_RIGHT,
    MOVE_UP,
    MOVE_DOWN,
};

// 音乐文件名 
char *bgm_name[] =
{
    "1.mp3",
    "2.mp3",
    "NULL",
};

// 文科版文件名
char *bmp_name_3[]={
    NULL,
    "one.bmp",
    "two.bmp",
    "three.bmp",
    "four.bmp",
    "five.bmp",
    "six.bmp",
    "seven.bmp",
    "egiht.bmp",
    NULL,
};

// 经典版文件名
char *bmp_name_1[] =
{
    NULL,
    "digit_2.bmp",
    "digit_4.bmp",
    "digit_8.bmp",
    "digit_16.bmp",
    "digit_32.bmp",
    "digit_64.bmp",
    "digit_128.bmp",
    "digit_256.bmp",
    "digit_512.bmp",
    "digit_1024.bmp",
    "digit_2048.bmp",
    "digit_4096.bmp",
    NULL,
};

//理科版文件名
char *bmp_name_2[]=
{
    NULL,
    "2.bmp",
    "4.bmp",
    "8.bmp",
    "16.bmp",
    "32.bmp",
    "64.bmp",
    "128.bmp",
    "256.bmp",
    "512.bmp",
    "1024.bmp",
    "2048.bmp",
    "4096.bmp",
    NULL,
};


    /*  
        功能:@得到相应数字的文件名
    */
char *get_file_name_by_digit(int num)
{
    int index = 0;

    switch (num)
    {
        case 2:
            index = 1;
            break;
        case 4:
            index = 2;
            break;
        case 8:
            index = 3;
            break;
        case 16:
            index = 4;
            break;
        case 32:
            index = 5;
            break;
        case 64:
            index = 6;
            break;
        case 128:
            index = 7;
            break;
        case 256:
            index = 8;
            break;
        case 512:
            index = 9;
            break;
        case 1024:
            index = 10;
            break;
        case 2048:
            index = 11;
            break;
        case 4096:
            index = 12;
            break;
        case 8192:
            index = 13;
            break;
        case 16384:
            index = 14;
            break;
        case 32768:
            index = 15;
            break;
        case 65536:
            index = 16;
            break;
        default:
            index = 0;
            break;
    }
      // printf("%d   \n",statu);
       if(statu== 1)
       {
            return bmp_name_1[index];
       }

       else if(statu == 2)
       {
             return  bmp_name_3[index];
       }
       else if (statu == 3)
       {
           return bmp_name_2[index];
       }
}


void lcd_draw_point(int x, int y, int color)
{
    *(plcd + y*800 + x) = color;
}


    /*
         功能:画出一大矩阵 
         @(x0,y0) 为起点坐标
         @(w,h) 为宽和高
    */
void lcd_draw_rect(int x0, int y0, int w, int h, int color)
{
    int x, y;
    for (y = y0; y < y0 + h; y++)
    {
        for (x = x0; x < x0 + w; x++)
            lcd_draw_point(x, y, color);
    }
}

    /*
        功能:画出一个bmp图片的内容
        @(x0,y0) 为起点坐标
        @(w,h) 为宽和高

    */
void lcd_draw_bmp(const char *file_name, int x0, int y0,int w,int h)
{
    int fd;
    fd = open(file_name, O_RDONLY);
    if (fd < 0)
    {
        perror("open file error: ");
        return ;
    }

    //跳过 前边54个字节,这54个字节是用来存储bmp图片的相关信息的
    lseek(fd, 54, SEEK_SET);

    //从第55个字节开始,读取bmp图片的像素数组
    char buf[800*480*3];
    read(fd, buf, 800*480*3);//因为这个bmp图片是24位色
    close(fd);

    int color, x, y, i = 0;
    unsigned char r, g, b;
    for (y = 0; y < h; y++)
    {
        for (x = 0; x < w; x++)
        {
            b = buf[i++];
            g = buf[i++];
            r = buf[i++];
            color = (r << 16) | (g << 8) | b;

            lcd_draw_point(x + x0, h-1-y+y0, color);
        }
    }
}

/*
  @功能:从顶点坐标为(x0, y0)的位置开始 画一个num*num的矩阵,每一个矩形的大小为pice_size*pice_size,

*/
void lcd_draw_matrix(int x0, int y0, int num, int pice_size, int blank,int color)
{
    int i, j;
    int x, y;

    for (j = 0; j < num; j++)
    {
        y = y0 + (pice_size + blank)*j;
        //画一行,这一行有4个矩形
        for (i = 0; i < num; i++)
        {
            x = x0 + (pice_size + blank)*i;

            if (matrix[j][i] == 0)
                lcd_draw_rect(x, y, pice_size, pice_size, color);
            else
                lcd_draw_bmp(get_file_name_by_digit(matrix[j][i]), x, y,100,100);
        }
    }
}

 /*
     功能:@判断手指的移动方向 以及 是否按下返回键
 */
int get_finger_move_direction()
{
    int fd, ret;

    int x1=-1, y1= -1;

    int x2, y2;

    struct input_event ev;

    fd = open("/dev/event0", O_RDWR);
    if (fd < 0)
    {
        perror("open event0 error: ");
        return ;
    }

    int count = 0;
    while (1)
    {
        ret = read(fd, &ev, sizeof(struct input_event));
        if (ret != sizeof(ev))
        {
            continue;
        }

        if ((ev.type == EV_ABS) && (ev.code == ABS_X))
        {
            if (x1 == -1)
                x1 = ev.value;
            else
                x2 = ev.value;
        }

        if ((ev.type == EV_ABS) && (ev.code == ABS_Y))
        {
            if (y1 == -1)
                y1 = ev.value;
            else
                y2 = ev.value;
        }

        if ((ev.type == EV_ABS) && (ev.code == ABS_PRESSURE) && (ev.value == 0)) //手指弹起 手指离开了触摸屏
        {
            if(x1 > 550 && x1 < 750 && y1> 50 && y1< 150)   //返回键
            {
                flag = 1;
                printf("%d %d\n",x2,y2);
                return -1;

            }

            int delta_x = abs(x2 - x1);
            int delta_y = abs(y2 - y1);

            if (delta_x > 2*delta_y)
            {
                if (x2 > x1)
                {
                    printf("right\n");
                    close(fd);
                    return MOVE_RIGHT; //向右
                }
                else if (x2 < x1)
                {
                    printf("left\n");
                    close(fd);
                    return MOVE_LEFT; //向左
                }
            }
            else if (delta_x < 2*delta_y)
            {
                if (y2 < y1)
                {
                    printf("down\n");
                    close(fd);
                    return MOVE_UP; //向上
                }
                else if (y2 > y1)
                {
                    printf("up\n");
                    close(fd);
                    return MOVE_DOWN; //向下
                }
            }
            else //该手势不能识别 再来一次
            {
                x1 = -1;
                y1 = -1;
            }
        }
    }
}


    /*
        功能:@判断初始界面中被点击的选项
    */
int get_finger_touch_area()
{
    int fd, ret;

    int x2, y2;

    struct input_event ev;

    fd = open("/dev/event0", O_RDWR);
    if (fd < 0)
    {
        perror("open event0 error: ");
        return ;
    }

    int count = 0;
    while (1)
    {
        ret = read(fd, &ev, sizeof(struct input_event));
        if (ret != sizeof(ev))
        {
            continue;
        }

        if ((ev.type == EV_ABS) && (ev.code == ABS_X))
        {
                x2 = ev.value;
        }

        if ((ev.type == EV_ABS) && (ev.code == ABS_Y))
        {
                y2 = ev.value;
        }


        if ((ev.type == EV_ABS) && (ev.code == ABS_PRESSURE) && (ev.value == 0)) //手指弹起 手指离开了触摸屏
        {

            if( statu==0 && x2>600 && x2<800 && y2>27 && y2<=177)    // 经典版
            {
                close(fd);
                return 1;
            }
            else if(statu == 0 && x2>600 && x2<800 && y2>178 && y2<=327)   //理科版
            {
                close(fd);
                return 2;
            }   
            else if(statu == 0 && x2>600 && x2<800 && y2>328 && y2<=479) //文科版
            {
                close(fd);
                return 3;
            }
        }
    }
}


void handle_left()
{
    int i,j,k,z;
    for(i = 0;i < 4;i++)
    {
        for(j = 0;j < 4;j++)
        {
            if(matrix[i][j] == 0) continue;

            for(z = j+1;z < 4;z++)
            {
                if(matrix[i][j] == matrix[i][z])
                {
                    matrix[i][j] = matrix[i][j]*2;
                    matrix[i][z] = 0;
                    break;
                }
                if(matrix[i][z] != 0)
                {
                  break;
                }
            }
        }
    }   

    for(i = 0;i < 4;i++)
    {
        k = 0;
        for(j = 0;j < 4;j++)
        {
            if(matrix[i][j]!= 0)
            {
                 matrix[i][k] = matrix[i][j];
                 if(j != k) matrix[i][j] = 0;
                 k++;
            }
        }
    }
}


void hand_right()
{   
    int i,j,k,z;
    for(i = 0;i < 4;i++)
    {
        for(j = 3;j >= 0;j--)
        {
            if(matrix[i][j] == 0) continue;

            for(z= j-1;z >= 0;z--)
            {
                if(matrix[i][j] == matrix[i][z])
                {
                    matrix[i][j] = matrix[i][j]*2;
                    matrix[i][z] = 0;
                    break;
                }
                if(matrix[i][z] != 0)
                {
                  break;
                }
            }
        }
    }

    for(i = 0;i < 4;i++)
    {
        k = 3;
        for(j = 3;j >= 0;j--)
        {
            if(matrix[i][j] != 0)
            {
                 matrix[i][k] = matrix[i][j];
                 if(j != k) matrix[i][j] = 0;
                 k--;
            }
        }
    }
}


void hand_up()
{
    int i,j,k,z;
    for(i = 0;i < 4;i++)
    {
        for(j = 0;j < 4;j++)
        {
            if(matrix[j][i] == 0) continue;

            for(z = j+1;z < 4;z++)
            {
                if(matrix[j][i] == matrix[z][i])
                {
                    matrix[j][i] = matrix[j][i]*2;
                    matrix[z][i] = 0;
                    break;
                }
                if(matrix[z][i] != 0)
                {
                  break;
                }
            }
        }
    }

    for(i = 0;i < 4;i++)
    {
        k = 0;
        for(j = 0;j < 4;j++)
        {
            if(matrix[j][i] != 0)
            {
                 matrix[k][i] = matrix[j][i];
                 if(j != k) matrix[j][i] = 0;
                 k++;
            }
        }
    }
}

void hand_down()
{
    int i,j,k,z;
    for(i = 0;i < 4;i++)
    {
        for(j = 3;j >= 0;j--)
        {
            if(matrix[j][i] == 0) continue;

            for(z = j-1;z >= 0;z--)
            {
                if(matrix[j][i] == matrix[z][i])
                {
                    matrix[j][i] = matrix[j][i]*2;
                    matrix[z][i] = 0;
                    break;
                }
                if(matrix[z][i] != 0)
                {
                  break;
                }
            }
        }
    }

    for(i = 0;i < 4;i++)
    {
        k = 3;
        for(j = 3;j >= 0;j--)
        {
            if(matrix[j][i]!= 0)
            {
                 matrix[k][i] = matrix[j][i];
                 if(j != k) matrix[j][i] = 0;
                 k--;
            }
        }
    }

}



/*
   曾加随机数
*/
void add_number()
{
    int t,k,x,y,sum=0;

    t = rand()%4;
    k = rand()%5;
    x,y,sum=0;

    for(x = t;;)
     {
        for(y = 0;y < 4;y++)
        {
            sum++;
           if(matrix[x][y] == 0)
           {
              matrix[x][y] = s[k];
              sum = 16;
              break;
           }
        }
        x++;
        x %= 4;
        if(sum > 15) break;
    }
    lcd_draw_matrix(50, 10, 4, 100, 20, 0x00EDEDED);
}


int game_over_judge()  
{
    int i,j;
    for(i = 0;i < 4;i++)
    {
        for(j = 0;j < 4;j++)
        {
            if(matrix[i][j] == 0)
            {
                return -1;
            }
            if(j-1 > 0 && matrix[i][j] == matrix[i][j-1]) 
            {
                return -1;
            }
            if(j+1 < 4 && matrix[i][j] == matrix[i][j+1]) 
            {
                return -1;
            }
            if(i-1 > 0 && matrix[i][j] == matrix[i-1][j]) 
            {
                return -1;
            }
            if(i+1 < 4 && matrix[i][j] == matrix[i+1][j]) 
            {
                return -1;
            }
        }
    }
    return 1;
}

/*
  功能:@初始化statu,并画出整个界面;
*/
void start()
{
    int i,j;

    statu = 0;

    while(1)
    {
      lcd_draw_bmp("jm.bmp",0,0,400,479); 
      lcd_draw_bmp("lk.bmp",400,0,400,150);
      lcd_draw_bmp("wk.bmp",400,151,400,150);
      lcd_draw_bmp("jd.bmp",400,302,400,150);

      statu = get_finger_touch_area();

      if(statu == 1||statu == 2 || statu == 3) 
      {
          lcd_draw_rect(0, 0 , 800, 480, 0x0086B7DF);
          lcd_draw_matrix(50, 10, 4, 100, 20, 0x00EDEDED);

          //printf("start() at the end\n");
          break;
      }
    }

    for(i = 0;i < 4;i++)
    {
        for(j = 0;j < 4;j++)
            matrix[i][j] = 0;
    }

    matrix[3][1] = 4;
    matrix[3][3] = matrix[2][3] =2;

    lcd_draw_bmp("back.bmp", 550, 350 , 200, 100);
}



/*
   功能:@找出最大分数,并画出。
*/
void max_grand()
{
    int k = 0,i,j;

    for(i = 0;i < 4;i++)
    {
        for(j = 0;j < 4;j++)
        {
            if(matrix[i][j] > k )
                k = matrix[i][j];
        }
    }

    lcd_draw_bmp(get_file_name_by_digit(k), 550,  200, 100, 100);

    for(i = 0;i < 1e6;i++);
}

/*
   功能:@在需要的时候返回大初始界面
*/
void back_to_start()
{
    if(flag)
    {
        lcd_draw_rect(0, 0 , 800, 480, 0x0086B7DF);
        start();
    }
}


void  copy_matrix()
{
    int i,j;

    for(i=0;i<4;i++)
    {
        for(j=0;j<4;j++)
        {
            ck[i][j] = matrix[i][j];
        }
    }
}

int check_change()
{
    int i,j;

    for(i = 0;i <  4;i++)
    {
        for(j = 0;j < 4;j++)
        {
            if(matrix[i][j] != ck[i][j])
                return 1;
        }
    }
    return 0;
}


void game_play()
{
    int move = 0,t,check;

    while (1)
    {
        move = get_finger_move_direction();

        if(move == -1) back_to_start(); 

        lcd_draw_matrix(50, 10, 4, 100, 20, 0x00EDEDED);

        copy_matrix();

        switch (move)
        {
            case MOVE_LEFT:
                handle_left();
                break;
            case MOVE_RIGHT:
                hand_right();
                break;
            case MOVE_DOWN:
                 hand_up();
                break; 
            case MOVE_UP:
                hand_down();
                break;
            default:
                break;
        }

        max_grand();

        t = game_over_judge();

        //游戏结束清屏,返回主界面 
        if(t > 0)
        {
            lcd_draw_rect(0, 0 , 800, 480, 0x0086B7DF);
            start();
            break;
        }

        lcd_draw_matrix(50, 10, 4, 100, 20, 0x00EDEDED);

        //int check;
        if(check_change())
        {
             //printf("%d\n",check);
             add_number();
        }
    }
}

// 音乐线程
void *music_play(void *arg)
{
    int i = 0;
    char name[10];
    char cmd[64];

    while (1)
    {
        i = 0;
        while (strcmp(bgm_name[i], "NULL") != 0)
        {
            //初始化一个字符串
            memset(name, 0, sizeof(name));
            //字符串的拷贝
            strcpy(name, bgm_name[i]);

            memset(cmd, 0, sizeof(cmd));
            sprintf(cmd, "madplay %s", name);

            system(cmd);

            i++;
        }
    }
}

void bgm_play()
{
    pthread_create(&pid, NULL, music_play,NULL);    
}

void sig_handler(int num)
{
    printf("sig_handler...\n");
    pthread_cancel(pid);

    exit(0);
}


int main(int argc, char *argv[])
{
    srand(time(NULL));

    int fd; //framebuffer

    fd = open("/dev/fb0", O_RDWR);
    if (fd < 0)
    {
        perror("open file error: ");
        return 0;
    }

    plcd = mmap(NULL, 800*480*4,PROT_READ | PROT_WRITE,MAP_SHARED,fd,0);

    if (plcd == MAP_FAILED)
    {
        perror("mmap error :");
        return 0;
    }

    //初始清屏
    lcd_draw_rect(0, 0 , 800, 480, 0x0086B7DF);

    //播放音乐
    bgm_play();
    signal(SIGINT, sig_handler);

    //初始界面
    start();

    srand(time(NULL));

    while(1)
    {
       game_play();
    }

    phread_join(pid);

    munmap(plcd, 800*480*4);

    //关闭设备
    close(fd);

    return 0;
}

额,第一次写这么长的代码,过程中收获了不少,但也感觉到自己犯了很多错误,是时候做一波总结了!

(1) 写在思考前。不急着下手,额,现在经验告诉我在编写前没有认真思考,往往都是错的(对本学渣而言,大神请靠边),往往花大量的功夫的重调代码。

(2) 缺少必要的注释。 个人觉得注释影响代码的美观,所以在编程过程中,很少注。特别是函数参数都没注释,调用的时候,总得再看看,关键还容易出错。额,不好的地方,需改。

(3) 变量命名还是不太规范。对于某个函数的局部时,因为采用随便命名,可能到后期过程中从新看代码的时候就不太好看,这个时候花了可能要花不少功夫重新看代码。

(4) 代码的美观性。考虑必要的逻辑空行,和空格。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值