7.基于粤嵌gec6818开发板的小游戏----五子棋,2048游戏,扫雷,飞机大战,钢琴游戏,刮刮乐,打地鼠等等

有的游戏代码很多,只展示关键代码,需要源码私我即可!

1.五子棋

在这里插入图片描述
关键代码:

#include<stdio.h>
#include<unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include "bmp.h"
#include "ts.h"
#include "wuziqi.h"

extern int wu_point[17][17];



void Go_point(int *XP,int *YP,int *mark_who)   //落棋函数
{
		int x2=(int)((*XP)*800.0/1024.0+0.5);//计算 触摸屏 坐标(1034*600) 改为(800*480)
		int y2=(int)((*YP)*480.0/600.0+0.5);

		//int x2=*XP;
		//int y2=*YP;
		
		int x2_p=(x2-60)/30+1;//坐标对于棋盘的X
		if((x2-60)%30>15)
		{
			x2_p=x2_p+1;
		}
		int y2_p=(y2-30)/30+1;//坐标对于棋盘的Y
		if((y2-30)%30>15)
		{
			x2_p=x2_p+1;
		}
		
		if(wu_point[x2_p][y2_p]==0 && *mark_who==1 && x2_p<17 && y2_p<17)//若([x2_p],[y2_p])没有棋子,则下棋
		{
			wu_point[x2_p][y2_p]=1;
			yuan((x2_p-1)*30+60,(y2_p-1)*30+30,10,0x000000);//黑棋下棋结束
			printf("black_X: %d  balck_Y: %d\n",x2_p,y2_p);
			*mark_who=2;
		}

		else if(wu_point[x2_p][y2_p]==0 && *mark_who==2 && x2_p<17 && y2_p<17)//若([x2_p],[y2_p])没有棋子,则下棋
		{
			wu_point[x2_p][y2_p]=2;
			yuan((x2_p-1)*30+60,(y2_p-1)*30+30,10,0xFFFFFF);//白棋下棋结束
			printf("white_X: %d  white_Y: %d\n",x2_p,y2_p);
			*mark_who=1;
		}
		*XP=x2_p;//把棋子在数组中对应的位置给XP,YP传出去
		*YP=y2_p;
		

}


	int  panduan(int x,int y)     //判断是否胜利
	{
	    int temp;//保存下棋方的颜色
	    int count=1;//统计个数,针对的同一线
	    int i=1;//走一格
	    int j=1;//和i同时用来代表走斜的
	    int whoWin=0;//1代表黑方,2代表白方
	    temp=wu_point[x][y];
	    //水平的左边
	    while(temp==wu_point[x-i][y]&&x>=5&&x<17&&y>=1&&y<17&&count<5)
	    {
	        i++;
	        count++;
	        if(count==5)//首先count是5才能来判断谁赢了,不然连资格都没有
	        {
	            if(temp==1)
	                whoWin=1;

	            else
	                whoWin=2;
	        }
	    }
	    //水平的右边
	    i=1;
		count=1;//清理掉之前的数据
	   while(temp==wu_point[x+i][y]&&x>0&&x<13&&y>0&&y<17&&count<5)
	    {
	        i++;
	        count++;
	        if(count==5)//首先count是5才能来判断谁赢了,不然连资格都没有
	        {
	            if(temp==1)
	                whoWin=1;

	            else
	                whoWin=2;
	        }
	    }

	   //解决垂直的方向
	   //垂直上方
	   i=1;
	   count=1;//清理掉之前的数据
	   while(temp==wu_point[x][y-i]&&x>0&&x<17&&y>4&&y<17&&count<5)
	    {
	        i++;
	        count++;
	        if(count==5)//首先count是5才能来判断谁赢了,不然连资格都没有
	        {
	            if(temp==1)
	                whoWin=1;

	            else
	                whoWin=2;
	        }
	    }
	   //垂直下方
	   i=1;
	   while(temp==wu_point[x][y+i]&&x>0&&x<17&&y>0&&y<13&&count<5)
	    {
	        i++;
	        count++;
	        if(count==5)//首先count是5才能来判断谁赢了,不然连资格都没有
	        {
	            if(temp==1)
	                whoWin=1;

	            else
	                whoWin=2;
	        }
	    }
	   //解决左上的斜线  
	     i=1;
	     j=1;
	     count=1;
	   while(temp==wu_point[x-i][y-j]&&x>4&&x<17&&y>4&&y<17&&count<5)
	    {
	        i++;
	        j++;
	        count++;
	        if(count==5)//首先count是5才能来判断谁赢了,不然连资格都没有
	        {
	            if(temp==1)
	                whoWin=1;

	            else
	                whoWin=2;
	        }
	    }
	   //解决右下的斜线  
	     i=1;
	     j=1;
		 count=1;
	   while(temp==wu_point[x+i][y+j]&&x>0&&x<13&&y>0&&y<13&&count<5)
	    {
	        i++;
	        j++;
	        count++;
	        if(count==5)//首先count是5才能来判断谁赢了,不然连资格都没有
	        {
	            if(temp==1)
	                whoWin=1;

	            else
	                whoWin=2;
	        }
	    }
	   //解决右上的斜线  
	     i=1;
	     j=1;
	     count=1;
	   while(temp==wu_point[x+i][y-j]&&x>0&&x<13&&y>4&&y<17&&count<5)
	    {
	        i++;
	        j++;
	        count++;
	        if(count==5)//首先count是5才能来判断谁赢了,不然连资格都没有
	        {
	            if(temp==1)
	                whoWin=1;

	            else
	                whoWin=2;
	        }
	    }
	   //解决左下的斜线  
	     i=1;
	     j=1;
		 count=1;
	   while(temp==wu_point[x-i][y+j]&&x>4&&x<17&&y>0&&y<13&&count<5)
	    {
	        i++;
	        j++;
	        count++;
	        if(count==5)//首先count是5才能来判断谁赢了,不然连资格都没有
	        {
	            if(temp==1)
	                whoWin=1;

	            else
	                whoWin=2;
	        }
	    }
	    return whoWin;
}



void star_game(int fd_s,int *XP,int *YP) //开始游戏
{
	chessboard();//画棋盘
	
	int mark_who=1;//谁的回合,1——黑 2——白
	int win_who=0;//谁赢 1-黑胜 2-白胜
	//int wu_point[15][15];//构建棋盘点,0-无		  1-黑	2-白
	for(int i=0;i<17;i++)
	{
		for(int j=0;j<17;j++)
		{
			
			if(i==0 ||i==16 ||j==0 ||j==16)
			{
				wu_point[i][j]=3;
			}
			else
			{
				wu_point[i][j]=0;
			}

		}

	}

	while(1)
	{	
		   
		int a1=get_touch(fd_s,XP,YP);
		Go_point(XP,YP,&mark_who);
		win_who= panduan(*XP,*YP);//接受判断结果
		if(win_who==1)
		{
			printf("BLACK  WIN!!!\n");
			sleep(3);
			break;
			return;

		}
		if(win_who==2)
		{
			printf("WHITE  WIN!!!\n");
			break;
			return;
		}
			
						
	}


}

2.2048游戏

在这里插入图片描述
在这里插入图片描述
关键代码:

#include "yueqian.h"
//小游戏:2048
//硬件:粤嵌ARM开发板
//arm-linux-gcc 2048.c yueqian.c -std=gnu99
short map[4][4]={0};
//游戏函数
void refresh_screen();//刷新整个屏幕
void join_numbers(char direction);//数字整合
void add_number();//产生随机数字
void show_pic(int number,int x,int y);//将单个图片放到目标位置
int touch_x;int touch_y;

int main(){
    init_board();
    add_number();add_number();
    refresh_screen();
    while(1){
		char direction=get_coordinates_and_direction(&touch_x,&touch_y);
		if(direction!=NOT_MOVED) join_numbers(direction);
		else if(touch_x>=COLUMN-100 && touch_y>=ROW-50) {
			system("./ui");
			pthread_exit(NULL);
		}
    }
	uninit_board();
}

void join_numbers(char direction){
    char is_moved=0;//如果画面无改变,就不产生新的数字
    switch(direction){
    case UP:
        for(int i=0;i<4;i++){//列,从左到右判断
            //数字排序
            int zero_point=99;//寻找空块,压缩空间
            for(int j=0;j<4;j++){//行
                //printf("行=%d,zero_point=%d\n",j,zero_point);
                if(map[j][i]==0 && zero_point>j){
                    zero_point=j;
                    //printf("!!行=%d,zero_point=%d\n",j,zero_point);
                }else{
                    if(zero_point!=99 && map[j][i]!=0){
                        map[zero_point][i]=map[j][i];
                        map[j][i]=0;
                        zero_point++;
                        is_moved=1;
                    }
                }
            }
            //数字相加
            for(int j=0;j<3;j++){
                if(map[j][i]==map[j+1][i] && map[j][i]!=0){
                    map[j][i]*=2;
                    map[j+1][i]=0;
                    j++;
                    is_moved=1;
                }
            }
            //数字排序(第二次,代码同第一次)
            zero_point=99;
            for(int j=0;j<4;j++){
                if(map[j][i]==0 && zero_point>j){
                    zero_point=j;
                }else{
                    if(zero_point!=99 && map[j][i]!=0){
                        map[zero_point][i]=map[j][i];
                        map[j][i]=0;
                        zero_point++;
                        is_moved=1;
                    }
                }
            }
        }
        break;
    case DOWN:
        for(int i=0;i<4;i++){//列,从左到右判断
            //数字排序
            int zero_point=-99;
            for(int j=3;j>=0;j--){
                if(map[j][i]==0 && zero_point<j){
                    zero_point=j;
                }else{
                    if(zero_point!=-99 && map[j][i]!=0){
                        map[zero_point][i]=map[j][i];
                        map[j][i]=0;
                        zero_point--;
                        is_moved=1;
                    }
                }
            }
            //数字相加
            for(int j=3;j>0;j--){
                if(map[j][i]==map[j-1][i] && map[j][i]!=0){
                    map[j][i]*=2;
                    map[j-1][i]=0;
                    j++;
                    is_moved=1;
                }
            }
            //数字排序(第二次,代码同第一次)
            zero_point=-99;
            for(int j=3;j>=0;j--){
                if(map[j][i]==0 && zero_point<j){
                    zero_point=j;
                }else{
                    if(zero_point!=-99 && map[j][i]!=0){
                        map[zero_point][i]=map[j][i];
                        map[j][i]=0;
                        zero_point--;
                        is_moved=1;
                    }
                }
            }
        }
        break;
    case LEFT:
        for(int j=0;j<4;j++){//行,从上到下判断
            //数字排序
            int zero_point=99;
            for(int i=0;i<4;i++){
                if(map[j][i]==0 && zero_point>i){
                    zero_point=i;
                }else{
                    if(zero_point!=99 && map[j][i]!=0){
                        map[j][zero_point]=map[j][i];
                        map[j][i]=0;
                        zero_point++;
                        is_moved=1;
                    }
                }
            }
            //数字相加
            for(int i=0;i<3;i++){
                if(map[j][i]==map[j][i+1] && map[j][i]!=0){
                    map[j][i]*=2;
                    map[j][i+1]=0;
                    i++;
                    is_moved=1;
                }
            }
            //数字排序(第二次,代码同第一次)
            zero_point=99;
            for(int i=0;i<4;i++){
                if(map[j][i]==0 && zero_point>i){
                    zero_point=i;
                }else{
                    if(zero_point!=99 && map[j][i]!=0){
                        map[j][zero_point]=map[j][i];
                        map[j][i]=0;
                        zero_point++;
                        is_moved=1;
                    }
                }
            }
        }
        break;
    case RIGHT:
        for(int j=0;j<4;j++){//行,从上到下判断
            //数字排序
            int zero_point=-99;
            for(int i=3;i>=0;i--){
                if(map[j][i]==0 && zero_point<i){
                    zero_point=i;
                }else{
                    if(zero_point!=-99 && map[j][i]!=0){
                        map[j][zero_point]=map[j][i];
                        map[j][i]=0;
                        zero_point--;
                        is_moved=1;
                    }
                }
            }
            //数字相加
            for(int i=3;i>0;i--){
                if(map[j][i]==map[j][i-1] && map[j][i]!=0){
                    map[j][i]*=2;
                    map[j][i-1]=0;
                    i++;
                    is_moved=1;
                }
            }
            //数字排序(第二次,代码同第一次)
            zero_point=-99;
            for(int i=3;i>=0;i--){
                if(map[j][i]==0 && zero_point<i){
                    zero_point=i;
                }else{
                    if(zero_point!=-99 && map[j][i]!=0){
                        map[j][zero_point]=map[j][i];
                        map[j][i]=0;
                        zero_point--;
                        is_moved=1;
                    }
                }
            }
        }
        break;
    }
    //判断有没有2048出现,如果有,赢了
    for(int i=0;i<4;i++){
        for(int j=0;j<4;j++){
            if(map[i][j]==2048){
                printf("赢了赢了赢了赢了赢了赢了赢了赢了\n");
                //放图,结束游戏
                refresh_screen();
                show_pic_generic("./2048_res/win.bmp",160,0);
				sleep(3);
				system("./ui");
                pthread_exit(NULL);
				
            }
        }
    }
    //如果画面有变化
    if(is_moved==1){
        //产生随机数字
        add_number();
        //刷新屏幕
        refresh_screen();
    }else{//判断是不是输了
        char is_lost=1;
        for(int i=0;i<4;i++){//判断行能否相加
            for(int j=0;j<3;j++){
                if(map[i][j]==map[i][j+1]){
                    is_lost=0;
                    break;
                }
            }
            if(is_lost==0) break;
        }
        if(is_lost==1){
            for(int j=0;j<4;j++){//判断列能否相加
                for(int i=0;i<3;i++){
                    if(map[i][j]==map[i+1][j]){
                        is_lost=0;
                        break;
                    }
                }
                if(is_lost==0) break;
            }
        }
        if(is_lost==1){//输了
            printf("输了输了输了输了输了输了输了输了\n");
            //放图,结束游戏
            refresh_screen();
            show_pic_generic("./2048_res/lost.bmp",213,0);
			sleep(3);
			system("./ui");
            pthread_exit(NULL);
			
        }
        
    }
}

void add_number(){
    char not_ok=1;
    while(not_ok){
        int x=rand()%4;
        int y=rand()%4;
        if(map[y][x]==0){//此方法当棋盘很大时效率会很低,但4x4效果还行
            map[y][x]=(rand()%2+1)*2;
            not_ok=0;
        }
    }
}

void refresh_screen(){
    for(int i=0;i<4;i++){//行
        for(int j=0;j<4;j++){//列
            show_pic(map[j][i],i*COLUMN/4,j*ROW/4);//显示出来的行列与打印出来的相反,故这里把数组里的i与j对调
            printf("%d\t",map[i][j]);
        }
        printf("\n");
    }
	show_pic_generic("./2048_res/exit.bmp",COLUMN-100,ROW-50);
}

void show_pic(int number,int offset_x,int offset_y){
    char img_path[20];
    sprintf(img_path, "./2048_res/%d.bmp", number);//数字转字符串
	show_pic_generic(img_path,offset_x,offset_y);
}

3.扫雷游戏
在这里插入图片描述
关键代码:

#include<stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <linux/input.h>
#include"lcd.h"
#include"mine.h"
#include"bmp.h"


char* path_arrow = "../res/return.bmp";

int mine_num = 10;
int clicked_num = 0;
int margin_UD = 40;
int margin_LR = 200;
int m[mine_height + 2][mine_width + 2];     // 0未打开,1地雷,2已打开

// 颜色
int c_bg = 0xFFFFFF;
int c_number[8] = {0XFFFFFF,0X00FF00,0X0000FF,0XFFA500,0XFF69B4,0XFFFF00,0XFF0000,0X800080};
int c_unopen = 0xC0C0C0;
int c_open = 0xFFF5EE;
int c_win_bg = 0XFF0000;
int c_win_font = 0X00FF00;
int c_failed_bg = 0X0000F0;
int c_failed_font = 0X000000;


//数值1-8
int num_width = 16;
int num_height = 21;
int padding_UD = 6;
int padding_LR = 4; 

unsigned char mine_number[8][16*21/8] = {
{0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x0E,0x00,0x1E,0x00,0x7E,0x00,0x7E,0x00,
0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,
0x0E,0x00,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x7F,0x80,0x7B,0xC0,0xE1,0xC0,0x41,0xC0,
0x03,0xC0,0x03,0x80,0x07,0x80,0x0F,0x00,0x0E,0x00,0x1C,0x00,0x38,0x00,0x78,0x00,
0xFF,0xC0,0xFF,0xC0,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x3F,0x80,0x73,0xC0,0xF1,0xC0,0x61,0xC0,
0x03,0x80,0x0F,0x80,0x1F,0x80,0x03,0xC0,0x01,0xC0,0x41,0xC0,0xE1,0xC0,0x73,0xC0,
0x7F,0x80,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x80,0x07,0x80,0x07,0x80,0x0F,0x80,0x1F,0x80,
0x1F,0x80,0x3B,0x80,0x73,0x80,0x73,0x80,0xE3,0x80,0xFF,0xE0,0xFF,0xE0,0x03,0x80,
0x03,0x80,0x03,0x80,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x80,0x7F,0xC0,0x7F,0x80,0x70,0x00,0x70,0x00,
0x7F,0x00,0xFF,0x80,0xE3,0xC0,0x01,0xC0,0x01,0xC0,0x41,0xC0,0xE3,0xC0,0xF7,0x80,
0x7F,0x80,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x0F,0x00,0x0E,0x00,0x1C,0x00,0x3C,0x00,
0x3F,0x00,0x7F,0x80,0x7B,0xC0,0xF1,0xE0,0xE1,0xE0,0xE1,0xE0,0xF1,0xE0,0x73,0xC0,
0x7F,0x80,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xC0,0xFF,0xC0,0x7F,0xC0,0x03,0xC0,0x03,0x80,
0x07,0x00,0x07,0x00,0x0F,0x00,0x0E,0x00,0x0E,0x00,0x1C,0x00,0x1C,0x00,0x1C,0x00,
0x3C,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x7F,0x80,0x73,0xC0,0xE1,0xC0,0xE1,0xC0,
0x73,0x80,0x7F,0x80,0x7F,0x80,0xF3,0xC0,0xE1,0xC0,0xE1,0xC0,0xE1,0xC0,0xF3,0xC0,
0x7F,0x80,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00}
};

unsigned char mine_win_fonts[4][40*35/8] = {
/*--  文字:  你  --*/
/*--  幼圆26;  此字体下对应的点阵为:宽x高=36x35   --*/
/*--  宽度不是8的倍数,现调整为:宽度x高度=40x35  --*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x82,0x00,0x00,0x00,0x03,
0x87,0x00,0x00,0x00,0x03,0x87,0x00,0x00,0x00,0x03,0x8F,0x00,0x00,0x00,0x03,0x8E,
0x00,0x00,0x00,0x07,0x8F,0xFF,0xFF,0x80,0x07,0x1F,0xFF,0xFF,0x80,0x07,0x1C,0x0E,
0x03,0xC0,0x07,0x1C,0x0E,0x03,0xC0,0x0F,0x3C,0x0E,0x03,0x80,0x0F,0x38,0x0E,0x03,
0x80,0x0F,0x70,0x0E,0x07,0x80,0x1F,0xF0,0x0E,0x07,0x00,0x1F,0x60,0x0E,0x00,0x00,
0x3F,0x03,0x8E,0x3C,0x00,0x3F,0x03,0x8E,0x1C,0x00,0x7F,0x07,0x0E,0x1C,0x00,0xFF,
0x07,0x0E,0x1E,0x00,0x6F,0x07,0x0E,0x0E,0x00,0x0F,0x0F,0x0E,0x0E,0x00,0x0F,0x0E,
0x0E,0x0F,0x00,0x0F,0x1E,0x0E,0x07,0x00,0x0F,0x1C,0x0E,0x07,0x00,0x0F,0x1C,0x0E,
0x07,0x80,0x0F,0x38,0x0E,0x03,0x80,0x0F,0x38,0x0E,0x03,0x80,0x0F,0x70,0x0E,0x03,
0x80,0x0F,0xF0,0x0E,0x03,0x80,0x0F,0xE0,0x0E,0x03,0xC0,0x0F,0x00,0x0E,0x01,0x80,
0x0F,0x03,0xFE,0x00,0x00,0x0F,0x01,0xFC,0x00,0x00,0x06,0x00,0x78,0x00,0x00},

/*--  文字:  赢  --*/
/*--  幼圆26;  此字体下对应的点阵为:宽x高=36x35   --*/
/*--  宽度不是8的倍数,现调整为:宽度x高度=40x35  --*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xC0,0x00,0x00,0x00,
0x01,0xC0,0x00,0x00,0x00,0x01,0xE0,0x00,0x00,0x7F,0xFF,0xFF,0xFF,0x80,0x7F,0xFF,
0xFF,0xFF,0x80,0x07,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x07,0xFF,0xFF,
0xFE,0x00,0x03,0xFF,0xFF,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xFF,0xFF,0xFC,
0x00,0x0F,0xFF,0xFF,0xFC,0x00,0x0E,0x00,0x00,0x1C,0x00,0x0E,0x00,0x00,0x1C,0x00,
0x0F,0xFF,0xFF,0xFC,0x00,0x07,0xFF,0xFF,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,
0xC7,0xF1,0xFC,0x00,0x3F,0xEF,0xFB,0xFE,0x00,0x38,0xFE,0x3F,0x9E,0x00,0x38,0xFD,
0xBF,0x8E,0x00,0x3F,0xFD,0xFF,0xEE,0x00,0x3F,0xFD,0xFF,0xFE,0x00,0x38,0xFD,0xFF,
0xFE,0x00,0x38,0xFD,0xFF,0xFE,0x00,0x3F,0xFF,0xFF,0xFF,0xC0,0x3F,0xFF,0xBF,0xFF,
0xC0,0x38,0xEF,0xF3,0xFF,0xC0,0x38,0xE7,0xF3,0xFF,0xC0,0x78,0xE7,0x7F,0xBF,0xC0,
0x70,0xEF,0x3F,0x0F,0xC0,0x77,0xFE,0x3F,0x0F,0xC0,0xF7,0xDC,0x0E,0x07,0x80},

/*--  文字:  了  --*/
/*--  幼圆26;  此字体下对应的点阵为:宽x高=36x35   --*/
/*--  宽度不是8的倍数,现调整为:宽度x高度=40x35  --*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,
0xFF,0xFF,0xFC,0x00,0x1F,0xFF,0xFF,0xFF,0x00,0x0F,0xFF,0xFF,0xFF,0x00,0x00,0x00,
0x00,0x1E,0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x03,
0xE0,0x00,0x00,0x00,0x07,0xC0,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x00,0x7E,0x00,
0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x00,0xE0,0x00,0x00,0x00,0x01,0xE0,0x00,0x00,
0x00,0x00,0xF0,0x00,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0x00,0x3C,0x00,0x00,0x00,
0x00,0x1C,0x00,0x00,0x00,0x00,0x0E,0x00,0x00,0x00,0x00,0x0E,0x00,0x00,0x00,0x00,
0x0F,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x07,
0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x07,0x00,
0x00,0x00,0x00,0x0F,0x00,0x00,0x00,0x00,0x0E,0x00,0x00,0x00,0x78,0x3E,0x00,0x00,
0x00,0x7F,0xFC,0x00,0x00,0x00,0x3F,0xF0,0x00,0x00,0x00,0x07,0xC0,0x00,0x00},

/*--  文字:  !  --*/
/*--  幼圆26;  此字体下对应的点阵为:宽x高=36x35   --*/
/*--  宽度不是8的倍数,现调整为:宽度x高度=40x35  --*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0x01,0xF8,0x00,0x00,0x00,0x01,0xF8,0x00,
0x00,0x00,0x01,0xF8,0x00,0x00,0x00,0x01,0xF8,0x00,0x00,0x00,0x01,0xF8,0x00,0x00,
0x00,0x01,0xF0,0x00,0x00,0x00,0x01,0xF0,0x00,0x00,0x00,0x00,0xF0,0x00,0x00,0x00,
0x00,0xF0,0x00,0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0x00,
0xF0,0x00,0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0x00,0xE0,
0x00,0x00,0x00,0x00,0xE0,0x00,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0x01,0xF0,0x00,0x00,
0x00,0x01,0xF8,0x00,0x00,0x00,0x01,0xF0,0x00,0x00,0x00,0x00,0xF0,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}
};

unsigned char mine_failed_fonts[4][40*35/8] = {
/*--  文字:  点  --*/
/*--  幼圆26;  此字体下对应的点阵为:宽x高=36x35   --*/
/*--  宽度不是8的倍数,现调整为:宽度x高度=40x35  --*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x80,0x00,0x00,0x00,
0x03,0x80,0x00,0x00,0x00,0x03,0x80,0x00,0x00,0x00,0x03,0x80,0x00,0x00,0x00,0x03,
0xFF,0xFF,0x80,0x00,0x03,0xFF,0xFF,0x80,0x00,0x03,0xFF,0xFF,0x00,0x00,0x03,0x80,
0x00,0x00,0x00,0x03,0x80,0x00,0x00,0x00,0x03,0x80,0x00,0x00,0x07,0xFF,0xFF,0xF8,
0x00,0x0F,0xFF,0xFF,0xFC,0x00,0x0F,0xFF,0xFF,0xFC,0x00,0x0E,0x00,0x00,0x1C,0x00,
0x0E,0x00,0x00,0x1C,0x00,0x0E,0x00,0x00,0x1C,0x00,0x0E,0x00,0x00,0x1C,0x00,0x0E,
0x00,0x00,0x1C,0x00,0x0E,0x00,0x00,0x1C,0x00,0x0E,0x00,0x00,0x1C,0x00,0x0E,0x00,
0x00,0x1C,0x00,0x0F,0xFF,0xFF,0xFC,0x00,0x07,0xFF,0xFF,0xF8,0x00,0x00,0x00,0x00,
0x00,0x00,0x07,0x1C,0x0E,0x1C,0x00,0x07,0x1E,0x0E,0x1E,0x00,0x0E,0x0E,0x0E,0x0F,
0x00,0x0E,0x0E,0x0F,0x07,0x00,0x1E,0x0E,0x07,0x07,0x80,0x1C,0x0E,0x07,0x03,0x80,
0x38,0x0E,0x07,0x03,0xC0,0x78,0x0E,0x07,0x01,0xC0,0x70,0x0E,0x03,0x01,0xC0},

/*--  文字:  到  --*/
/*--  幼圆26;  此字体下对应的点阵为:宽x高=36x35   --*/
/*--  宽度不是8的倍数,现调整为:宽度x高度=40x35  --*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x3F,
0xFF,0xFC,0x03,0x80,0x7F,0xFF,0xFE,0x83,0x80,0x3F,0xFF,0xFF,0xC3,0x80,0x00,0xE0,
0x03,0xC3,0x80,0x01,0xE3,0x83,0xC3,0x80,0x01,0xC3,0x83,0xC3,0x80,0x03,0xC3,0xC3,
0xC3,0x80,0x03,0x81,0xC3,0xC3,0x80,0x07,0x81,0xE3,0xC3,0x80,0x07,0x00,0xE3,0xC3,
0x80,0x0E,0x1F,0xF3,0xC3,0x80,0x1F,0xFF,0xF3,0xC3,0x80,0x1F,0xFF,0x7B,0xC3,0x80,
0x00,0x38,0x3B,0xC3,0x80,0x00,0x38,0x3B,0xC3,0x80,0x00,0x38,0x03,0xC3,0x80,0x00,
0x38,0x03,0xC3,0x80,0x00,0x38,0x03,0xC3,0x80,0x00,0x38,0x03,0xC3,0x80,0x3F,0xFF,
0xFB,0xC3,0x80,0x3F,0xFF,0xFB,0xC3,0x80,0x00,0x38,0x03,0xC3,0x80,0x00,0x38,0x03,
0xC3,0x80,0x00,0x38,0x03,0xC3,0x80,0x00,0x38,0x01,0xC3,0x80,0x00,0x38,0x00,0x03,
0x80,0x00,0x38,0x00,0x03,0x80,0x00,0x38,0x1C,0x03,0x80,0x00,0x3F,0xFE,0x03,0x80,
0x3F,0xFF,0xFC,0xF7,0x80,0xFF,0xFC,0x00,0xFF,0x80,0x78,0x00,0x00,0x7F,0x00},

/*--  文字:  雷  --*/
/*--  幼圆26;  此字体下对应的点阵为:宽x高=36x35   --*/
/*--  宽度不是8的倍数,现调整为:宽度x高度=40x35  --*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,
0xFF,0xFF,0xFE,0x00,0x1F,0xFF,0xFF,0xFE,0x00,0x00,0x00,0xE0,0x00,0x00,0x00,0x00,
0xE0,0x00,0x00,0x3F,0xFF,0xFF,0xFF,0x80,0x7F,0xFF,0xFF,0xFF,0xC0,0x70,0x00,0xE0,
0x01,0xC0,0x70,0x00,0xE0,0x01,0xC0,0x7F,0xFE,0xFF,0xFD,0xC0,0x7F,0xFE,0xFF,0xFF,
0xC0,0x70,0x00,0xE0,0x03,0x80,0x70,0x00,0xE0,0x07,0x80,0x70,0x00,0xE0,0x03,0x00,
0x0F,0xFF,0xFF,0xFE,0x00,0x0F,0xFF,0xFF,0xFE,0x00,0x00,0x00,0xE0,0x00,0x00,0x03,
0xFF,0xFF,0xF0,0x00,0x0F,0xFF,0xFF,0xFE,0x00,0x1F,0xFF,0xFF,0xFE,0x00,0x1C,0x00,
0xE0,0x0E,0x00,0x1C,0x00,0xE0,0x0E,0x00,0x1C,0x00,0xE0,0x0E,0x00,0x1F,0xFF,0xFF,
0xFE,0x00,0x1F,0xFF,0xFF,0xFE,0x00,0x1F,0xFF,0xFF,0xFE,0x00,0x1C,0x00,0xE0,0x0E,
0x00,0x1C,0x00,0xE0,0x0E,0x00,0x1C,0x00,0xE0,0x0E,0x00,0x1C,0x00,0xE0,0x0E,0x00,
0x1F,0xFF,0xFF,0xFE,0x00,0x0F,0xFF,0xFF,0xFE,0x00,0x06,0x00,0x00,0x10,0x00},

/*--  文字:  了  --*/
/*--  幼圆26;  此字体下对应的点阵为:宽x高=36x35   --*/
/*--  宽度不是8的倍数,现调整为:宽度x高度=40x35  --*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,
0xFF,0xFF,0xFC,0x00,0x1F,0xFF,0xFF,0xFF,0x00,0x0F,0xFF,0xFF,0xFF,0x00,0x00,0x00,
0x00,0x1E,0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x03,
0xE0,0x00,0x00,0x00,0x07,0xC0,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x00,0x7E,0x00,
0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x00,0xE0,0x00,0x00,0x00,0x01,0xE0,0x00,0x00,
0x00,0x00,0xF0,0x00,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0x00,0x3C,0x00,0x00,0x00,
0x00,0x1C,0x00,0x00,0x00,0x00,0x0E,0x00,0x00,0x00,0x00,0x0E,0x00,0x00,0x00,0x00,
0x0F,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x07,
0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x07,0x00,
0x00,0x00,0x00,0x0F,0x00,0x00,0x00,0x00,0x0E,0x00,0x00,0x00,0x78,0x3E,0x00,0x00,
0x00,0x7F,0xFC,0x00,0x00,0x00,0x3F,0xF0,0x00,0x00,0x00,0x07,0xC0,0x00,0x00}
};



void mine_draw_gezi(int mx, int my, int color)
{
    printf("gezi1\n");
    printf("mx: %d my: %d\n", mx, my);
    int x = (mx-1)*per_len + margin_LR;
    int y = (my-1)*per_len + margin_UD; 
    printf("x: %d y: %d\n", x, y);
    lcd_draw_clear(x, y, x + per_len - 2, y + per_len - 2, color);
}

void mine_draw_font(int mx, int my, int number)
{
    int x = (mx-1)*per_len + margin_LR + padding_LR;
    int y = (my-1)*per_len + margin_UD + padding_UD;
    printf("%d %d\n", x, y);
    lcd_draw_one_word(x, y, c_number[number - 1], num_width, num_height, mine_number[number - 1]);
}

// 初始化扫雷区域
void mine_init() 
{
    clicked_num = 0;
    lcd_draw_clear(0, 0, 800, 480, c_bg);
    srand((unsigned) time(NULL)); // 根据当前时间设置随机数种子
    int i, j;
    int count = 0; // 已放置的地雷数量
    // 先将所有位置初始化为0
    for (i = 0; i < mine_height + 2; ++i) 
    {
        for (j = 0; j < mine_width + 2; ++j) 
        {
            m[i][j] = 0;
            if(i!=0 && j!=0 && i!=mine_height+1 && j!=mine_width+1)
            {
                mine_draw_gezi(i, j, c_unopen);
            }
            else
            {
                m[i][j] = 2;
            }
        }
    }
    // 随机放置地雷
    while (count < mine_num) {
        i = rand() % mine_height + 1;
        j = rand() % mine_width + 1;
        if (m[i][j] == 0) 
        {
            m[i][j] = 1; // 标记该位置为地雷
            count++;     // 已放置的地雷数量加1
        }
    }
}

// 计算指定位置周围地雷数量
int mine_count_around(int mx, int my) 
{
    int count = 0;
    int i, j;
    for (i = mx - 1; i <= mx + 1; ++i) {
        for (j = my - 1; j <= my + 1; ++j) {
            if (m[i][j] == 1) 
            {
                count++;
            }
        }
    }
    return count;
}

// 翻开指定位置
void mine_click(int mx, int my) 
{
    printf("mine1\n");
    if (m[mx][my] == 1) { // 如果该位置是地雷,则游戏结束
        mine_failed();
        return;
    }

    printf("mine2\n");
    if (m[mx][my] == 2) { // 如果该位置已经翻开,则直接返回
        return;
    }

    printf("mine3\n");
    m[mx][my] = 2; // 标记该位置为已翻开
    clicked_num ++;
    mine_draw_gezi(mx, my, c_open); // 绘制已经翻开的方块
    printf("mine4\n");
    int n = mine_count_around(mx, my);
    if (n == 0) { // 如果周围没有地雷,则递归翻开周围的位置
        int i, j;
        for (i = mx - 1; i <= mx + 1; ++i) {
            for (j = my - 1; j <= my + 1; ++j) {
                printf("i: %d, j: %d", i, j);
                mine_click(i, j);
            }
        }
    }
    else
    {
        printf("mine5\n");
        mine_draw_font(mx, my, n);
    }
}


// 处理玩家点击事件
void player_click(int x, int y) 
{
    int mx = (x - margin_LR) / per_len + 1;
    int my = (y - margin_UD) / per_len + 1;
    
    if ((mx < 1) || (mx > 8) || (my < 1) || (my > 8)) { // 如果输入的位置不合法
        return;
    }

    if (m[mx][my] == 2) { // 如果选择了已经翻开的位置
        return;
    }

    mine_click(mx, my); // 翻开该位置5
    
    if (clicked_num == mine_width * mine_height - mine_num) { // 如果所有非地雷位置都已翻开,则游戏胜利
        mine_win();
    }
}

// 游戏成功
void mine_win() 
{
    lcd_draw_clear(610, 50, 790, 250, c_win_bg);
    lcd_draw_word(620, 137, c_win_font, 4, 40, 35, mine_win_fonts);
    printf("游戏成功!\n");
}

// 游戏失败
void mine_failed() 
{
    lcd_draw_clear(610, 50, 790, 250, c_failed_bg);
    lcd_draw_word(620, 137, c_failed_font, 4, 40, 35, mine_failed_fonts);
    printf("游戏失败!\n");
}

void mine_start()
{
    mine_init();

    /*图片的信息*/
    unsigned char* data;
    int width;
    int height;
    int pix_bit;
    
    int bmpfd = bmp_open_file(path_arrow);
    bmp_get_pic_message(bmpfd, &data, &width, &height, &pix_bit);
    bmp_colse_file(bmpfd);
    // 绘制箭头
    showPic_append(data, height, width, pix_bit);

    int event_fd = 0;
	ssize_t rsize = 0;
	struct input_event ev;//用来保存从输入设备中获取到的的输入事件
	event_fd =open("/dev/input/event0",O_RDWR);
	if (-1 == event_fd)
	{
		perror("open event0 error");
	}
	
    int xi = 0, x_down = 0;
    int yi = 0, y_down = 0;
	while(1)
	{
		rsize = read(event_fd, &ev, sizeof(ev));
		if (rsize == sizeof(ev))    //读到了输入事件
		{
            //printf("0x%2x 0x%2x %d\n", ev.type, ev.code, ev.value);
            if (ev.type == 0X03)
            {
                // 1022*600
                if (ev.code == 0X00)
                {
                    //printf("x: %d   %d\n", ev.value, ev.value*8/12);
                    xi = ev.value * 800 / 1020;              
                }
                else if (ev.code == 0X01)
                {   
                    //printf("y: %d   %d\n", ev.value, ev.value*8/12);
                    yi = ev.value * 480 / 600;
                }
            }
            if (ev.code == 0x14a)
            {
                if (ev.value == 1)
                {
                    x_down = xi;
                    y_down = yi;
                }
                else if (ev.value == 0)
                {
                    printf("xi: %d x_down: %d yi: %d y_down: %d\n", xi, x_down, yi, y_down);
                    if (xi < 80 && yi < 60)
                    {
                        break;
                    }
                    if ((xi > x_down - 5) && (xi < x_down + 5) && (yi > y_down - 5) && (yi < y_down +5))
                    {
                        player_click(xi, yi);
                    }
                }
                
            }
        }
	}
    free(data);
}

4.飞机大战

在这里插入图片描述

关键代码:

#include "planemove.h"
#include "event.h"
#include "bmp.h"

int indexs = 0;
char *score[4]={"./1.bmp","./2.bmp","./3.bmp","./4.bmp"};

extern int x_read;
extern int y_read;


void* enemyplane()//敌机在一固定区域随机出现
{
	int i;
	//extern int index;
	int num = 0;
	int x;
	srandom(time(NULL));
	for(num = 0; num < 4; num++)
	{
		enemyplane_Y = random() % 301;
		enemyplane_X = random() % 257;
		
		
		for(i = 0; i< 200; i++)
		{
			x=enemyplane_X + 5*i;
			show_bmp("./gamePage_800x480_bg.bmp",0,0);
			close_bmp();
			show_bmp("./plane_60x60_enemy.bmp",enemyplane_X + 5*i,enemyplane_Y);
			close_bmp();
			show_bmp("./jiguang_730x28.bmp",plane_x-730,plane_y+14);//激光炮
			close_bmp();
			show_bmp("./plane_57x57_hero.bmp",plane_x,plane_y);
			close_bmp();
			show_bmp(score[indexs],0,410);
			close_bmp();
			if(enemyplane_Y>=plane_y-10 && enemyplane_Y<=plane_y+10)//当我方飞机击中敌机,敌机就消失
			{
				show_bmp("./gamePage_800x480_bg.bmp",0,0);
				close_bmp();
				show_bmp("./jiguang_730x28.bmp",plane_x-730,plane_y+14);//激光
				close_bmp();
				show_bmp("./plane_57x57_hero.bmp",plane_x,plane_y);
				close_bmp();
				indexs++;
				sleep(0.5);
				break;
				
			}
			if(x>730)//敌机超过我方飞机区域就游戏结束
			{
				show_bmp("./gameover.bmp",160,0);
				close_bmp();
				return 0;
			}
			
		}
		
		sleep(1);
	}	
}



void planemove()//我方飞机
{
    plane_x=730;
    //pthread_t th;
	pthread_t th1;
	int i=0;
    //pthread_create(&th,NULL,bullet,NULL);
	pthread_create(&th1,NULL,enemyplane,NULL);
    while (1)
	{
		open_event();
        plane_y=y_read*480/600;
		show_bmp("./gamePage_800x480_bg.bmp",0,0);
		close_bmp();
		show_bmp("./jiguang_730x28.bmp",plane_x-730,plane_y+14);//激光
		close_bmp();
		show_bmp("./plane_57x57_hero.bmp",plane_x,plane_y);
		close_bmp();	

		
		close_event();
		
	}
	
}

5.钢琴游戏

在这里插入图片描述

关键代码:

#include "ts.h"
#include "bmp.h"
#include <pthread.h>
#include <unistd.h>
#include "audio.h"
#include "scorenum.h"
#define ON 1
#define OFF 0
char keyON[][50] = {KEY1ON, KEY2ON, KEY3ON, KEY4ON, KEY5ON, KEY6ON, KEY7ON};
char keyOFF[][50] = {KEY1OFF, KEY2OFF, KEY3OFF, KEY4OFF, KEY5OFF, KEY6OFF, KEY7OFF};
int white[2][12], black[2][11], line[12], key[7]; //1.按键范围,2.按键是否被按
char *FB;
int lcd;
struct fb_var_screeninfo vinfo;
pthread_t tid;
pthread_t touchid;				 //触摸多线程
pthread_t gameid;				 //游戏多线程
pthread_t playid;				 //游戏内单个键多线程
struct coordinate coor, oldcoor; //按键x,y
bool released = false;

char *init_lcd(struct fb_var_screeninfo *vinfo)
{
	lcd = open("/dev/fb0", O_RDWR);

	bzero(vinfo, sizeof(struct fb_var_screeninfo));
	ioctl(lcd, FBIOGET_VSCREENINFO, vinfo);

	FB = mmap(NULL, vinfo->xres * vinfo->yres * 4,
			  PROT_READ | PROT_WRITE,
			  MAP_SHARED, lcd, 0);
	return FB;
}

void init_frame()
{

	// 显示背景
	bmp2lcd(BACKGROUND, FB, &vinfo, 0, 0);
	// 显示标题栏
	bmp2lcd(BAR, FB, &vinfo, 0, 0);
	// 显示琴键
	int i, j;
	for (i = 0; i < 12; i++)
	{
		line[i] = 65 * i + 42;
		bmp2lcd(GAMELINE, FB, &vinfo, line[i], 0);

		white[0][i] = 65 * i + 10;
		white[1][i] = OFF;
		bmp2lcd(KEYOFF, FB, &vinfo, white[0][i], 47);
		if (i > 0)
		{
			j = i - 1;
			if (j == 2 || j == 5 || j == 9)
			{
				continue;
			}
			black[0][j] = 65 * j + 53;
			black[1][j] = OFF;
			bmp2lcd(KEYBLACKOFF, FB, &vinfo, black[0][i - 1], 47);
		}
	}
	// 显示音乐按键
	// bmp2lcd(KEY1, FB, &vinfo, 10, 430);
	// bmp2lcd(KEY2, FB, &vinfo, 100, 430);
	// bmp2lcd(KEY3, FB, &vinfo, 190, 430);
	// bmp2lcd(KEY4, FB, &vinfo, 280, 430);
	int len = sizeof(keyOFF) / sizeof(keyOFF[0]);
	printf("keynum==%d\n", len);
	for (i = 0; i < len; i++)
	{
		key[i] = 10 + i * 85;
		bmp2lcd(keyOFF[i], FB, &vinfo, key[i], 430);
	}
	// 显示停止按键
	bmp2lcd(KEYSTOP, FB, &vinfo, 720, 430);
}
void delay(float time)
{
	usleep(time * 1000);
}

// 点击了在琴键之外区域
bool out_of_range(struct coordinate *coor, struct coordinate *oldcoor)
{
	if (oldcoor->x == coor->x && oldcoor->y == coor->y && released == false)
	{
		// coor->x = 0;
		// coor->y = 0;
		return true;
	}
	if (coor->x < 10 || coor->x > 790)
	{
		return true;
	}
	return false;
}

bool in_of_range(int x1, int x2, int y1, int y2)
{
	if (coor.y > y1 && coor.y < y2 && coor.x > x1 && coor.x < x2)
	{
		return true;
	}
	return false;
}
void usage(const char *prog)
{
	printf("\nwelcome you you you\nUsage: %s volume[0-3]\n", prog);
}
//白色单个按键处理
void key_white(bool key, int pos)
{
	printf("key is %d\n pos is %d \n", key, pos);
	if (pos == 0 || pos == 3 || pos == 6 || pos == 10)
	{
		if (key)
		{
			bmp2lcd(KEYON, FB, &vinfo, white[0][pos], 47);
		}
		else
		{
			bmp2lcd(KEYOFF, FB, &vinfo, white[0][pos], 47);
		}
		bmp2lcd(KEYBLACKOFF, FB, &vinfo, black[0][pos], 47);
	}
	else if (pos == 2 || pos == 5 || pos == 9 || pos == 11)
	{
		if (key)
		{
			bmp2lcd(KEYON, FB, &vinfo, white[0][pos], 47);
		}
		else
		{
			bmp2lcd(KEYOFF, FB, &vinfo, white[0][pos], 47);
		}
		bmp2lcd(KEYBLACKOFF, FB, &vinfo, black[0][pos - 1], 47);
	}
	else
	{
		if (key)
		{
			bmp2lcd(KEYONC, FB, &vinfo, white[0][pos], 47);
		}
		else
		{
			bmp2lcd(KEYOFFC, FB, &vinfo, white[0][pos], 47);
		}
		bmp2lcd(KEYBLACKOFF, FB, &vinfo, black[0][pos], 47);
	}
}

//选择黑或白键
void key_white_black(bool keyon, bool is_white, int pos)
{
	printf("keyon is %d\n is_white is %d\n pos is %d \n", keyon, is_white, pos);

	if (is_white)
	{
		key_white(keyon, pos);
	}
	else
	{
		if (keyon)
		{
			if (pos == 2 || pos == 5 || pos == 9)
			{
				return;
			}
			bmp2lcd(KEYBLACKON, FB, &vinfo, black[0][pos], 47);
		}
		else
		{
			if (pos == 2 || pos == 5 || pos == 9)
			{
				return;
			}
			bmp2lcd(KEYBLACKOFF, FB, &vinfo, black[0][pos], 47);
		}
	}
}

//黑白键处理
bool piano_change(bool is_white, int new_pos, int old_pos, bool touch)
{
	int num = 0;
	printf("is_white is %d\tnew_pos is %d\told_pos is %d \treleased is %d\t touch is %d\n", is_white, new_pos, old_pos, released, touch);
	if (released)
	{
		key_white_black(false, is_white, new_pos);
		touch = true;
		released = false;
		return touch;
	}
	if (new_pos != old_pos || touch)
	{
		//更新琴键状态
		key_white_black(true, is_white, new_pos);
		if (!touch)
			key_white_black(false, is_white, old_pos);
		else
			touch = false;
		// 使用madplay播放琴音
		if (is_white)
		{
			pthread_create(&tid, NULL, play_note, (void *)(new_pos));
		}
		else
		{
			if (new_pos == 2 || new_pos == 5 || new_pos == 9)
			{
				return touch;
			}
			if (new_pos > 2)
				num++;
			if (new_pos > 5)
				num++;
			if (new_pos > 9)
				num++;
			printf("playnotes is %d\n", new_pos - num + 12);
			pthread_create(&tid, NULL, play_note, (void *)(new_pos - num + 20));
		}
	}
	return touch;
}

//歌曲播放
void music_score(int m[])
{
	int i;
	int len = m[0]; //歌曲长度
	printf("len is %d\n", len);

	for (i = 1; i < len; i += 2)
	{ //歌曲结尾退出

		if (m[i] == 0)
		{
			break;
		}
		//歌曲分段
		if (m[i] <= 0)
		{
			delay(m[i + 1]);
			continue;
		}
		printf("music is %d\n", m[i]);
		key_white(true, m[i] - 1);
		pthread_create(&tid, NULL, play_note, (void *)(m[i] - 1));

		delay(m[i + 1] * 0.9);
		key_white(false, m[i] - 1);
		delay(m[i + 1] * 0.1);
		if (in_of_range(720, 800, 430, 480))
		{
			printf("exit\n");
			break;
		}
	}
}
void *get_touch_xy(void *n)
{
	while (1)
	{
		// 等待手指触碰琴键
		wait4touch(&coor, &released);
	}
}

int main(int argc, char **argv)
{
usage(argv[0]);
if (argc == 2)
{
	switch (atoi(argv[1]))
	{
	case 0:
		vol = -105;
		break;
	case 1:
		vol = -45;
		break;
	case 2:
		vol = -15;
		break;
	case 3:
		vol = 10;
		break;
	}
}
else
{
	vol = -45;
}
// 准备LCD
FB = init_lcd(&vinfo);
bzero(FB, vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8);
//初始化界面
init_frame();
// 准备触摸屏
Init_Ts();
//设置线程分离属性
// pthread_attr_init(NULL);
// pthread_attr_setdetachstate(NULL, PTHREAD_CREATE_DETACHED);
int wnew_pos = 0, wold_pos = 0, bnew_pos = 0, bold_pos = 0;
bool w_touch = true, b_touch = true;
int len;
bool use_touch = false;
pthread_create(&touchid, NULL, get_touch_xy, NULL);
while (1)
{
	delay(10); //防止太快导致coor没写入就读取
	// printf("x=%d  y=%d \n", coor.x, coor.y);
	if (out_of_range(&coor, &oldcoor))
		continue;
	oldcoor.x = coor.x;
	oldcoor.y = coor.y;
	//黑色键部分
	if (coor.y > 47 && coor.y < 47)
	{
		bold_pos = bnew_pos;
		bnew_pos = (coor.x - 50) / 65;
		printf("black x=%d  y=%d wnew_pos=%d\n", coor.x, coor.y, bnew_pos);
		if (bnew_pos > 10)
		{
			continue;
		}

		b_touch = piano_change(false, bnew_pos, bold_pos, b_touch);
		use_touch = true;
		continue;
	}
	//白色键部分
	if (coor.y > 47 && coor.y < 280)
	{
		wold_pos = wnew_pos;
		wnew_pos = (coor.x - 10) / 65;
		printf("white x=%d  y=%d wnew_pos=%d\n", coor.x, coor.y, wnew_pos);
		if (wnew_pos > 11)
		{
			wnew_pos = 11;
		}

		w_touch = piano_change(true, wnew_pos, wold_pos, w_touch);
		use_touch = true;
		continue;
	}
	//歌曲部分
	if (coor.y > 430 && coor.y < 480)
	{
		printf("music x=%d  y=%d \n", coor.x, coor.y);

		//歌曲选择
		int i;
		for (i = 0; i < 7; i++)
		{
			if (coor.x > 10 + i * 90 && coor.x < 90 + i * 90)
			{
				len = sizeof(musicnum[i]) / sizeof(musicnum[i][0]);
				musicnum[i][0] = len;
				bmp2lcd(keyON[i], FB, &vinfo, key[i], 430);
				music_score(musicnum[i]);
				bmp2lcd(keyOFF[i], FB, &vinfo, key[i], 430);
				break;
			}
		}
		coor.x = 0;
		coor.y = 0;
		released = false;
		continue;
	}
	//黑白键超出范围重置按键
	if (coor.y > 0 && coor.y < 47 && use_touch)
		bmp2lcd(KEYBLACKOFF, FB, &vinfo, black[0][bold_pos], 47);
	if (coor.y > 320 && coor.y < 430 && use_touch)
		key_white(false, wold_pos);
	use_touch = false;

	if (in_of_range(0, 50, 0, 50))  
	{
		printf("exit piano\n");
		break;
	}
}
	//结束和卸载程序
	UnInit_Ts();
	//撤销映射
	munmap(FB,			   //映射后的地址,通过mmap返回的值
		   800 * 480 * 4); //映射的大小
	close(lcd);
	pthread_exit(NULL);
	pthread_join(tid, NULL);
	pthread_join(gameid, NULL);
	pthread_join(playid, NULL);
	exit(0);
	return 0;
}

6.刮刮乐游戏

源代码:

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <linux/input.h>
#include <stdbool.h>

#define FBDEV "/dev/fb0"             // Framebuffer设备文件路径
#define EVENT_DEV "/dev/input/event0"// 输入设备文件路径
#define IMAGE_PATH "/path/to/image.bmp"// 图片路径

#define SCREEN_WIDTH 800            // 屏幕宽度
#define SCREEN_HEIGHT 480           // 屏幕高度

#define SCRATCH_PERCENTAGE 0.5      // 刮开比例

struct fb_var_screeninfo vinfo;     // 变量屏幕信息
struct fb_fix_screeninfo finfo;     // 固定屏幕信息
char *fbp = 0;                      // Framebuffer指针
int fbfd = 0;                       // Framebuffer设备文件描述符

bool running = true;                // 游戏运行状态

// 判断两个像素是否相同
bool pixel_equal(char *p1, char *p2) {
    return p1[0] == p2[0] && p1[1] == p2[1] && p1[2] == p2[2];
}

// 判断两个像素是否相邻
bool pixel_nearby(char *p1, char *p2, int dist) {
    int dr = p1[0] - p2[0];
    int dg = p1[1] - p2[1];
    int db = p1[2] - p2[2];
    return dr * dr + dg * dg + db * db < dist * dist;
}

// 判断一个像素是否在刮开的区域内
bool pixel_inside_scratch(char *p, char *p_scratch, int scratch_size) {
    return pixel_nearby(p, p_scratch, scratch_size) || pixel_nearby(p, p_scratch + 3, scratch_size) ||
           pixel_nearby(p, p_scratch + 3 * scratch_size, scratch_size) || pixel_nearby(p, p_scratch + 3 * scratch_size + 3, scratch_size);
}

// 判断一个像素是否在屏幕上
bool pixel_inside_screen(int x, int y) {
    return x >= 0 && x < vinfo.xres && y >= 0 && y < vinfo.yres;
}

// 判断一个像素是否已经被刮开了
bool pixel_scratched(char *p, char *p_scratch) {
    return pixel_equal(p, p_scratch) || pixel_equal(p, p_scratch + 3) || pixel_equal(p, p_scratch + 3 * SCREEN_WIDTH) ||
           pixel_equal(p, p_scratch + 3 * SCREEN_WIDTH + 3);
}

// 更新刮开的比例
void update_scratch_percentage(char *p_scratch, int scratch_size, float *percentage) {
    int num_scratched = 0;
    for (int y = 0; y < SCREEN_HEIGHT; y += 10) {
        for (int x = 0; x < SCREEN_WIDTH; x += 10) {
            char *p = fbp + (y * vinfo.xres + x) * 4;
            if (pixel_inside_scratch(p, p_scratch, scratch_size) && !pixel_scratched(p, p_scratch)) {
                num_scratched++;
            }
        }
    }
    *percentage = (float)num_scratched / ((float)SCREEN_WIDTH * SCREEN_HEIGHT / 100.0 * SCRATCH_PERCENTAGE);
}

// 绘制刮开的区域
void draw_scratch(char *p_scratch, int scratch_size) {
    for (int y = 0; y < SCREEN_HEIGHT; y++) {
        for (int x = 0; x < SCREEN_WIDTH; x++) {
            char *p = fbp + (y * vinfo.xres + x) * 4;
            if (pixel_inside_scratch(p, p_scratch, scratch_size)) {
                p[0] = 0;
                p[1] = 0;
                p[2] = 0;
                p[3] = 0;
            }
        }
    }
}

// 加载bmp图片
void load_image(char *image_path, char **image_data, int *image_width, int *image_height) {
    int image_fd = open(image_path, O_RDONLY);
    if (image_fd < 0){
		perror("Failed to open image file");
		exit(EXIT_FAILURE);
}
// 读取bmp文件头
unsigned char bmp_header[54];
ssize_t n_read = read(image_fd, bmp_header, 54);
if (n_read < 0) {
    perror("Failed to read BMP header");
    close(image_fd);
    exit(EXIT_FAILURE);
}

// 判断是否为bmp文件
if (bmp_header[0] != 'B' || bmp_header[1] != 'M') {
    fprintf(stderr, "File %s is not a BMP file", image_path);
    close(image_fd);
    exit(EXIT_FAILURE);
}

// 读取图片宽度和高度
*image_width = *(int*)&bmp_header[0x12];
*image_height = *(int*)&bmp_header[0x16];

// 计算像素数据大小
int pixel_data_size = (*image_width) * (*image_height) * 3;

// 分配像素数据内存
*image_data = (char*)malloc(pixel_data_size);
if (*image_data == NULL) {
    perror("Failed to allocate memory for image data");
    close(image_fd);
    exit(EXIT_FAILURE);
}

// 读取像素数据
n_read = read(image_fd, *image_data, pixel_data_size);
if (n_read < 0) {
    perror("Failed to read pixel data");
    close(image_fd);
    free(*image_data);
    exit(EXIT_FAILURE);
}

close(image_fd);
}

// 初始化Framebuffer
void init_fb() {
fbfd = open(FBDEV, O_RDWR);
if (fbfd == -1) {
perror("Error: cannot open framebuffer device");
exit(EXIT_FAILURE);
}
// 获取固定屏幕信息
if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo) == -1) {
    perror("Error reading fixed information");
    exit(EXIT_FAILURE);
}

// 获取变量屏幕信息
if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo) == -1) {
    perror("Error reading variable information");
    exit(EXIT_FAILURE);
}

// 计算Framebuffer的大小
int screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;

// 映射Framebuffer到内存
fbp = (char*)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fbfd, 0);
if ((int)fbp == -1) {
    perror("Error: failed to map framebuffer device to memory");
    exit(EXIT_FAILURE);
}
}

// 处理输入事件
void handle_input_event(struct input_event ev, char *p_scratch, int scratch_size, float *scratch_percentage) {
// 判断是否为触摸屏事件
if (ev.type == EV_ABS && ev.code == ABS_X) {
int x = ev.value;
ev = (struct input_event){0};
read_event(EVENT_DEV, &ev);
int y = ev.value;
// 判断是否在屏幕范围内
    if (pixel_inside_screen(x, y)) {
        // 判断是否在刮开的区域内
        char *p = fbp + (y * vinfo.xres + x) * 4;
        if (pixel_inside_scratch(p, p_scratch, scratch_size)) {
            // 判断是否已经刮开
            if (!pixel_scratched(p, p_scratch)) {
                // 刮开像素
                p[0] = 0;
                p[1] = 0;
                p[2] = 0;
                p[3] = 0;
                // 更新刮开的比例
                update_scratch_percentage(p_scratch, scratch_size, scratch_percentage);
            }
        }
    }
  }
}

int main() {
// 初始化Framebuffer
init_fb();
// 加载图片
char *image_data = NULL;
int image_width, image_height;
load_image(IMAGE_PATH, &image_data, &image_width, &image_height);

// 计算刮开的区域大小
int scratch_size = SCREEN_WIDTH * SCREEN_HEIGHT * SCRATCH_PERCENTAGE;

// 随机生成刮开的区域
char *p_scratch = image_data + (rand() % (image_width - SCREEN_WIDTH)) * 3 + (rand() % (image_height - SCREEN_HEIGHT)) * image_width * 3;

//接下来是代码的后半部分,包括主循环和一些辅助函数:

// 初始化刮开的比例为0
float scratch_percentage = 0.0f;

// 主循环
struct input_event ev;
while (1) {
    // 读取输入事件
    read_event(EVENT_DEV, &ev);

    // 处理输入事件
    handle_input_event(ev, p_scratch, scratch_size, &scratch_percentage);

    // 判断是否已经刮开足够的比例
    if (scratch_percentage >= SCRATCH_PERCENTAGE) {
        // 显示完整图片
        memcpy(fbp, image_data, vinfo.xres * vinfo.yres * 3);
        break;
    }
}

// 等待用户按下回车键退出
printf("Press enter to exit\n");
getchar();

// 释放资源
munmap(fbp, vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8);
close(fbfd);
free(image_data);

return 0;
}

// 判断像素是否在屏幕范围内
int pixel_inside_screen(int x, int y) {
return x >= 0 && x < vinfo.xres && y >= 0 && y < vinfo.yres;
}

// 判断像素是否在刮开的区域内
int pixel_inside_scratch(char *p, char *p_scratch, int scratch_size) {
return p >= p_scratch && p < p_scratch + scratch_size;
}

// 判断像素是否已经刮开
int pixel_scratched(char *p, char *p_scratch) {
return p[3] == 0 || p < p_scratch;
}

// 更新刮开的比例
void update_scratch_percentage(char *p_scratch, int scratch_size, float *scratch_percentage) {
int scratched_count = 0;
for (char *p = p_scratch; p < p_scratch + scratch_size; p += 4) {
if (pixel_scratched(p, p_scratch)) {
scratched_count++;
}
}
*scratch_percentage = (float)scratched_count / (float)(scratch_size / 4);
}

// 读取输入事件
void read_event(const char *dev_path, struct input_event *ev) {
static int fd = -1;
if (fd == -1) {
fd = open(dev_path, O_RDONLY);
if (fd == -1) {
perror("Error: cannot open input device");
exit(EXIT_FAILURE);
}
}
ssize_t n_read = read(fd, ev, sizeof(struct input_event));
if (n_read < 0) {
perror("Error: failed to read input event");
exit(EXIT_FAILURE);
}
}

7.打地鼠游戏

源代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <linux/input.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <linux/fb.h>

// 游戏参数
#define SCREEN_WIDTH 800 // 屏幕宽度
#define SCREEN_HEIGHT 480 // 屏幕高度
#define HOLE_WIDTH 100 // 地鼠洞宽度
#define HOLE_HEIGHT 100 // 地鼠洞高度
#define HOLE_COUNT 9 // 地鼠洞数量
#define HOLE_INTERVAL 50 // 地鼠洞之间的间距
#define HOLE_HIT_SCORE 10 // 击中地鼠得分
#define HOLE_MISS_SCORE -5 // 错过地鼠扣分
#define GAME_TIME 60 // 游戏时间,单位秒

// 输入设备文件路径
#define EVENT_DEV "/dev/input/event0"

// Framebuffer设备文件路径
#define FBDEV "/dev/fb0"

// 红色地鼠图片路径
#define MOLE_RED_PATH "mole_red.bmp"

// 绿色地鼠图片路径
#define MOLE_GREEN_PATH "mole_green.bmp"

// 游戏状态
enum GameState {
    GAME_STATE_INIT,
    GAME_STATE_PLAYING,
    GAME_STATE_GAME_OVER
};

// 地鼠洞
struct Hole {
    int x; // 地鼠洞左上角x坐标
    int y; // 地鼠洞左上角y坐标
    int state; // 地鼠状态,0表示没有地鼠,1表示有红色地鼠,2表示有绿色地鼠
};

// Framebuffer设备信息
int fbfd = -1;
struct fb_var_screeninfo vinfo;
struct fb_fix_screeninfo finfo;
char *fbp = NULL;

// 红色地鼠图片数据
char *mole_red_data = NULL;
int mole_red_width, mole_red_height;

// 绿色地鼠图片数据
char *mole_green_data = NULL;
int mole_green_width, mole_green_height;

// 游戏状态
enum GameState game_state = GAME_STATE_INIT;

// 游戏时间
int game_time = 0;

// 游戏得分
int game_score = 0;

// 地鼠洞数组
struct Hole holes[HOLE_COUNT];

// 初始化地鼠洞
void init_holes() {
    int hole_x = (SCREEN_WIDTH - HOLE_WIDTH * 3 - HOLE_INTERVAL * 2) / 2;
    int hole_y = (SCREEN_HEIGHT - HOLE_HEIGHT * 3 - HOLE_INTERVAL * 2) / 2;
    for (int i = 0; i < HOLE_COUNT; i++) {
        holes[i].x = hole_x + (i % 3) * (HOLE_WIDTH + HOLE_INTERVAL);
        holes[i].y = hole_y + (i / 3) * (HOLE_HEIGHT + HOLE_INTERVAL);
        holes[i].state = 0;
    }
}

// 初始化红色地鼠
void init_mole_red() {
    // 加载红色地鼠图片
    load_image(MOLE_RED_PATH, &mole_red_data, &mole_red_width, &mole_red_height);

    // 缩放红色地鼠图片
    char *mole_red_data_resized = (char*)malloc(HOLE_WIDTH * HOLE_HEIGHT * 3);
    if (mole_red_data_resized == NULL) {
        perror("Failed to allocate memory for mole red data");
        exit(EXIT_FAILURE);
    }
    resize_image(mole_red_data, mole_red_width, mole_red_height, mole_red_data_resized, HOLE_WIDTH, HOLE_HEIGHT);
    free(mole_red_data);
    mole_red_data = mole_red_data_resized;
}

// 初始化绿色地鼠
void init_mole_green() {
    // 加载绿色地鼠图片
    load_image(MOLE_GREEN_PATH, &mole_green_data, &mole_green_width, &mole_green_height);

    // 缩放绿色地鼠图片
    char *mole_green_data_resized = (char*)malloc(HOLE_WIDTH * HOLE_HEIGHT * 3);
    if (mole_green_data_resized == NULL) {
        perror("Failed to allocate memory for mole green data");
        exit(EXIT_FAILURE);
    }
    resize_image(mole_green_data, mole_green_width, mole_green_height, mole_green_data_resized, HOLE_WIDTH, HOLE_HEIGHT);
    free(mole_green_data);
    mole_green_data = mole_green_data_resized;
}

// 初始化游戏
void init_game() {
    // 打开输入设备文件
    int evfd = open(EVENT_DEV, O_RDONLY);
    if (evfd == -1) {
        perror("Failed to open input device");
        exit(EXIT_FAILURE);
    }

    // 获取FrameBuffer设备信息
    fbfd = open(FBDEV, O_RDWR);
    if (fbfd == -1) {
        perror("Failed to open framebuffer device");
        exit(EXIT_FAILURE);
    }
    if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo) == -1) {
        perror("Failed to get framebuffer device info");
        exit(EXIT_FAILURE);
    }
    if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo) == -1) {
        perror("Failed to get framebuffer device info");
        exit(EXIT_FAILURE);
    }

    // 映射FrameBuffer内存
    fbp = (char*)mmap(0, finfo.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fbfd, 0);
    if ((int)fbp == -1) {
        perror("Failed to mmap framebuffer");
        exit(EXIT_FAILURE);
    }

    // 初始化地鼠洞
    init_holes();

    // 初始化红色地鼠
    init_mole_red();

    // 初始化绿色地鼠
    init_mole_green();

    // 初始化游戏时间
    game_time = GAME_TIME;

    // 初始化游戏得分
    game_score = 0;

    // 初始化游戏状态
    game_state = GAME_STATE_PLAYING;
}

// 绘制游戏界面
void draw_game() {
    // 清空屏幕
    clear_screen();

    // 绘制地鼠洞
    for (int i = 0; i < HOLE_COUNT; i++) {
        struct Hole hole = holes[i];
        if (hole.state == 1) {
            draw_image(mole_red_data, HOLE_WIDTH, HOLE_HEIGHT, hole.x, hole.y);
        } else if (hole.state == 2) {
            draw_image(mole_green_data, HOLE_WIDTH, HOLE_HEIGHT, hole.x, hole.y);
        }
    }

    // 绘制得分和游戏时间
    draw_text("Score: %d", game_score, 10, 10);
    draw_text("Time: %d", game_time, SCREEN_WIDTH - 100, 10);
}

// 游戏主循环
void game_loop() {
    // 获取输入事件
    struct input_event ev;
    while (read_input_event(&ev) > 0) {
        if (ev.type == EV_KEY && ev.code == BTN_TOUCH && ev.value == 1) {
            // 点击屏幕
            for (int i = 0; i < HOLE_COUNT; i++) {
                struct Hole hole = holes[i];
                if (ev.x >= hole.x && ev.x < hole.x + HOLE_WIDTH && ev.y >= hole.y && ev.y < hole.y + HOLE_HEIGHT) {
                    // 点击到地鼠洞
                    if (hole.state == 1) {
                        // 击中红色地鼠
                        game_score += HOLE_HIT_SCORE;
                        hole.state = 0;
                    } else if (hole.state == 2) {
                        // 击中绿色地鼠
                        game_score += HOLE_HIT_SCORE;
                        hole.state = 1;
                    } else {
                        // 错过地鼠
                        game_score += HOLE_MISS_SCORE;
                    }
                    break;
                }
            }
        }
    }

    // 更新游戏时间
    game_time--;
    for (int i = 0; i < NUM_HOLES; i++) {
        struct hole_t hole = holes[i];

        // 地鼠洞为空,有一定概率出现地鼠
        if (hole.state == 0) {
            if (rand() % 100 < 2) {
                hole.state = 1;
                hole.time_left = HOLE_SHOW_TIME;
            }
        } 
        // 地鼠洞有红色地鼠,减少显示时间
        else if (hole.state == 1) {
            hole.time_left--;
            if (hole.time_left <= 0) {
                // 地鼠逃走了
                hole.state = 0;
            }
            // 地鼠被击中
            if (hole.hit) {
                hole.state = 2;
                hole.time_left = HOLE_SHOW_TIME;
                game_score += 10;
            }
        } 
        // 地鼠洞有绿色地鼠,减少显示时间
        else if (hole.state == 2) {
            hole.time_left--;
            if (hole.time_left <= 0) {
                // 地鼠逃走了
                hole.state = 0;
            }
        }
        
        hole.hit = false; // 重置击中标志位
        holes[i] = hole;
    }


// 更新屏幕
draw_game();

// 判断游戏是否结束
if (game_time <= 0) {
    game_state = GAME_STATE_GAME_OVER;
}
}
// 游戏结束
void game_over() {
// 显示游戏结束界面
clear_screen();
draw_text("Game Over", SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2);
draw_text("Score: %d", game_score, SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2 + 50);

// 等待点击屏幕重新开始游戏
struct input_event ev;
while (read_input_event(&ev) > 0) {
    if (ev.type == EV_KEY && ev.code == BTN_TOUCH && ev.value == 1) {
        // 点击屏幕,重新开始游戏
        game_state = GAME_STATE_INIT;
        break;
    }
}
}

// 主函数
int main() {
// 初始化游戏
init_game();
// 游戏循环
while (1) {
    if (game_state == GAME_STATE_INIT) {
        // 初始化游戏
        init_game();
    } else if (game_state == GAME_STATE_PLAYING) {
        // 游戏进行中
        game_loop();
    } else if (game_state == GAME_STATE_GAME_OVER) {
        // 游戏结束
        game_over();
    }
}

return 0;
}

  • 82
    点赞
  • 200
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 43
    评论
【资源说明】 项目大致框架: ``` (1)GEC6818开发板LCD屏幕的初始化 (2)读取BMP图片文件信息,并显示在LCD屏幕上 (3)获取GEC6818开发板输入子事件 (4)判断输入子事件,实现点击功能 (5)打地鼠的基础玩法,多线程实现地鼠的自主出现和消失,记录分数和游戏结束条件判断 (6)主菜单界面 (7)排行榜界面 (8)程序退出 ``` # 项目程序和函数模块: ## (1)项目源码文件: ``` main.c:主函数,实现屏幕的初始化和主界面的加载 thread_pool.c:实现线程池 thread_pool.h:线程池的头文件 whack_mole.c:打地鼠游戏的功能实现 whack_mole.h:打地鼠游戏功能头文件 program:打地鼠游戏可执行程序(开发板) ``` 项目待开发功能: ``` (1)游戏得分(score)和血量(hp)可视化 (2)游戏界面的暂停和退出功能 (3)排行榜可视化 (4)退出功能插入退出成功图片 ``` 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载使用,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可直接用于毕设、课设、作业等。 欢迎下载,沟通交流,互相学习,共同进步!
基于粤嵌gec6818开发板小游戏五子棋2048游戏扫雷飞机大战钢琴游戏刮刮乐等。这些小游戏都可以通过简单的程序设计和硬件驱动来实现。 五子棋是一种简单而又经典的棋类游戏,玩家通过下棋子来争夺胜利。通过gec6818的触摸屏幕输入,可以实现玩家与电脑的对战,或者两个玩家之间的互动。 2048游戏是一款数学益智类游戏,玩家通过上下左右的滑动操作,将相同数值的方块合并,最终得到2048这个数值的方块。通过gec6818的触摸屏幕输入,可以实现玩家的滑动操作,将方块进行合并。 扫雷是一款经典的益智类游戏,玩家通过点击格子,来揭示隐藏的雷,避免踩雷。通过gec6818的触摸屏幕输入,可以实现玩家的点击操作,将雷揭示出来。 飞机大战是一款横版射击游戏,玩家通过控制飞机,射击敌方飞机和敌方炮台,躲避敌方的攻击。通过gec6818的按键输入,可以实现玩家的控制操作,进行射击和躲避。 钢琴游戏是一款音乐类游戏,玩家通过按下不同的琴键,发出不同的音符,弹奏出美妙的音乐。通过gec6818的按键输入,可以实现玩家的按键操作,发出不同的音符。 刮刮乐是一种益智类游戏,玩家通过刮开卡片上的涂层,获得隐藏的奖品。通过gec6818的触摸屏幕输入,可以实现玩家的刮卡操作,揭开涂层,看到奖品。 以上这些游戏都是基于粤嵌gec6818开发板设计的,通过合理的硬件和软件开发,可以让人们在休闲娱乐中享受到游戏乐趣。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 43
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

黎明的前夜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值