我的娱乐系统世界

这是第一次写博客,保存最近做的一次项目,代码有点长。(可能会有bug,不喜勿喷,纯粹用于个人纪录)。
时间:2020年7月31日
内容:Linux,6818开发板,触摸屏,花样展示图片(轮播,百叶窗,缩放等),视频,音频,2048小游戏
解释都在代码里
//新增音乐相册(可以在相册里点击进入)
//将相册目录改成了缩略图,可点击跳转对应图片。

头文件

#ifndef MYIOHEAD_H_
#define MYIOHEAD_H_
#include <time.h>
#include <errno.h>
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdint.h>
#include <string.h>
#include <strings.h>
#include <stdbool.h>
#include <pthread.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <dirent.h>
#include <linux/input.h>
#include <termio.h>
#include <bits/signum.h>
#include <signal.h>
#include <semaphore.h>

#endif



头文件不长,是常用的几个。

主代码

#include "myiohead.h"

//花样展示图片
int special_showbmp(char *bmppath)
{
	int bmpfd;
	int lcdfd;
	int i;
	int x,y;
	int w,h;
	
	//打开你要显示的w*h大小的bmp
	bmpfd=open(bmppath,O_RDWR);
	if(bmpfd==-1)
	{
		perror("打开图片失败!\n");
		return -1;
	}

	//读取图片的宽和高
	lseek(bmpfd,18,SEEK_SET);
	read(bmpfd,&w,4);//读取宽
	read(bmpfd,&h,4);//读取高

	//定义一个数组,依据图片的大小
	char bmpbuf[w*h*3]; //char占1个字节
	//定义另外一个数组,存放转换得到的ARGB数据
	int lcdbuf[w*h]; //int占4字节
	//定义中间变量。临时存放数据
	int tempbuf[w*h];

	//打开lcd驱动
	lcdfd=open("/dev/fb0",O_RDWR);
	if(lcdfd==-1)
	{
		perror("打开lcd失败!\n");
		return -1;
	}

	//映射得到lcd的首地址
	int *lcdmem=mmap(NULL,800*480*4,PROT_READ|PROT_WRITE,MAP_SHARED,lcdfd,0);
	if(lcdmem==NULL)
	{
		perror("映射lcd失败!\n");
		return -1;
	}
	
	//跳过bmp图片头信息54字节,从55字节开始读取
	lseek(bmpfd,54,SEEK_SET);
	
	//读取bmp图片的RGB数据
	//每三个字节为一组,构成一个像素点的RGB数据
	read(bmpfd,bmpbuf,w*h*3); //bmpbuf[0] bmpbuf[1] bmpbuf[2]
                                  //    B            G       R	
	                              //bmpbuf[3] bmpbuf[4] bmpbuf[5]  
	//把三个字节--》转换成四个字节
	/*
		细节分析如下:
		    lcdbuf[0]=0x00<<24|bmpbuf[0]<<16|bmpbuf[1]<<8|bmpbuf[2]
		    lcdbuf[1]=0x00<<24|bmpbuf[3]<<16|bmpbuf[4]<<8|bmpbuf[5] 
	*/
	for(i=0; i<w*h; i++)
		lcdbuf[i]=0x00<<24|bmpbuf[3*i+2]<<16|bmpbuf[3*i+1]<<8|bmpbuf[3*i];
	
	//把颠倒的图片翻转过来
	/*
		细节分析如下:
		    lcdbuf[0] --->lcdbuf[479*800]
			
	*/
	for(x=0; x<w; x++)
		for(y=0; y<h; y++)
			//lcdbuf[(h-1-y)*w+x]=lcdbuf[y*w+x];
			tempbuf[(h-1-y)*w+x]=lcdbuf[y*w+x];
		
	// //把转换后的数据写入lcd中
	// for(int i = 0;i < h;i++)
	// {
	// 	usleep(4000);
	// 	write(lcdfd,&tempbuf[w*i],w*4);
	// 	// *(lcdmem+(j*800)+i)=tempbuf[j*w+i];  
	// 	lseek(lcdfd,(800-w)*4,SEEK_CUR);             
	// }

	//把转换后的数据写入lcd中
	for (int j = 0; j < h; j++)
	{
		usleep(4000);
		for(int i = 0,n = 0;i < w;i++)
		{
			*(lcdmem+(j*800)+i)=tempbuf[j*w+i];  
			//n++;           
		}
	}
	
	//关闭
	close(bmpfd);
	close(lcdfd);
	return 0;
}

//缩放图片
int zoom_showbmp(char *bmppath)
{
	int bmpfd;
	int lcdfd;
	int i;
	int x,y;
	int w,h;
	
	//打开你要显示的w*h大小的bmp
	bmpfd=open(bmppath,O_RDWR);
	if(bmpfd==-1)
	{
		perror("打开图片失败!\n");
		return -1;
	}

	//读取图片的宽和高
	lseek(bmpfd,18,SEEK_SET);
	read(bmpfd,&w,4);//读取宽
	read(bmpfd,&h,4);//读取高

	//定义一个数组,依据图片的大小
	char bmpbuf[w*h*3]; //char占1个字节
	//定义另外一个数组,存放转换得到的ARGB数据
	int lcdbuf[w*h]; //int占4字节
	//定义中间变量。临时存放数据
	int tempbuf[w*h];

	//打开lcd驱动
	lcdfd=open("/dev/fb0",O_RDWR);
	if(lcdfd==-1)
	{
		perror("打开lcd失败!\n");
		return -1;
	}

	//映射得到lcd的首地址
	int *lcdmem=mmap(NULL,800*480*4,PROT_READ|PROT_WRITE,MAP_SHARED,lcdfd,0);
	if(lcdmem==NULL)
	{
		perror("映射lcd失败!\n");
		return -1;
	}
	
	//跳过bmp图片头信息54字节,从55字节开始读取
	lseek(bmpfd,54,SEEK_SET);
	
	//读取bmp图片的RGB数据
	//每三个字节为一组,构成一个像素点的RGB数据
	read(bmpfd,bmpbuf,w*h*3); //bmpbuf[0] bmpbuf[1] bmpbuf[2]
                                  //    B            G       R	
	                              //bmpbuf[3] bmpbuf[4] bmpbuf[5]  
	//把三个字节--》转换成四个字节
	/*
		细节分析如下:
		    lcdbuf[0]=0x00<<24|bmpbuf[0]<<16|bmpbuf[1]<<8|bmpbuf[2]
		    lcdbuf[1]=0x00<<24|bmpbuf[3]<<16|bmpbuf[4]<<8|bmpbuf[5] 
	*/
	for(i=0; i<w*h; i++)
		lcdbuf[i]=0x00<<24|bmpbuf[3*i+2]<<16|bmpbuf[3*i+1]<<8|bmpbuf[3*i];
	
	//把颠倒的图片翻转过来
	/*
		细节分析如下:
		    lcdbuf[0] --->lcdbuf[479*800]
			
	*/
	for(x=0; x<w; x++)
		for(y=0; y<h; y++)
			//lcdbuf[(h-1-y)*w+x]=lcdbuf[y*w+x];
			tempbuf[(h-1-y)*w+x]=lcdbuf[y*w+x];
		
	
	
	// //把转换后的数据写入lcd中
	for (int j = 0,m = 0; j < (h/2); j++,m = m+2)
	{

		for(int i = 0,n = 0;i < (w/2);i++,n = n+2)
		{
			*(lcdmem+(j*800)+i)=tempbuf[m*w+n];             
		}
	}	
	
	//关闭
	close(bmpfd);
	close(lcdfd);
	return 0;
}

//普通展示图片
int showbmp(char *bmppath)
{
	int bmpfd;
	int lcdfd;
	int i;
	int x,y;
	int w,h;
	
	//打开你要显示的w*h大小的bmp
	bmpfd=open(bmppath,O_RDWR);
	if(bmpfd==-1)
	{
		perror("打开图片失败!\n");
		return -1;
	}

	//读取图片的宽和高
	lseek(bmpfd,18,SEEK_SET);
	read(bmpfd,&w,4);//读取宽
	read(bmpfd,&h,4);//读取高

	//定义一个数组,依据图片的大小
	char bmpbuf[w*h*3]; //char占1个字节
	//定义另外一个数组,存放转换得到的ARGB数据
	int lcdbuf[w*h]; //int占4字节
	//定义中间变量。临时存放数据
	int tempbuf[w*h];

	//打开lcd驱动
	lcdfd=open("/dev/fb0",O_RDWR);
	if(lcdfd==-1)
	{
		perror("打开lcd失败!\n");
		return -1;
	}

	//映射得到lcd的首地址
	int *lcdmem=mmap(NULL,800*480*4,PROT_READ|PROT_WRITE,MAP_SHARED,lcdfd,0);
	if(lcdmem==NULL)
	{
		perror("映射lcd失败!\n");
		return -1;
	}
	
	//跳过bmp图片头信息54字节,从55字节开始读取
	lseek(bmpfd,54,SEEK_SET);
	
	//读取bmp图片的RGB数据
	//每三个字节为一组,构成一个像素点的RGB数据
	read(bmpfd,bmpbuf,w*h*3); //bmpbuf[0] bmpbuf[1] bmpbuf[2]
                                  //    B            G       R	
	                              //bmpbuf[3] bmpbuf[4] bmpbuf[5]  
	//把三个字节--》转换成四个字节
	/*
		细节分析如下:
		    lcdbuf[0]=0x00<<24|bmpbuf[0]<<16|bmpbuf[1]<<8|bmpbuf[2]
		    lcdbuf[1]=0x00<<24|bmpbuf[3]<<16|bmpbuf[4]<<8|bmpbuf[5] 
	*/
	for(i=0; i<w*h; i++)
		lcdbuf[i]=0x00<<24|bmpbuf[3*i+2]<<16|bmpbuf[3*i+1]<<8|bmpbuf[3*i];
	
	//把颠倒的图片翻转过来
	/*
		细节分析如下:
		    lcdbuf[0] --->lcdbuf[479*800]
			
	*/
	for(x=0; x<w; x++)
		for(y=0; y<h; y++)
			//lcdbuf[(h-1-y)*w+x]=lcdbuf[y*w+x];
			tempbuf[(h-1-y)*w+x]=lcdbuf[y*w+x];
		
	//把转换后的数据写入lcd中
	for (int j = 0; j < h; j++)
	{
		for(int i = 0,n = 0;i < w;i++)
		{
			*(lcdmem+(j*800)+i)=tempbuf[j*w+i];  
			//n++;           
		}
	}
	
	
	//关闭
	close(bmpfd);
	close(lcdfd);
	return 0;
}


//定义一个结构体表示双向循环列表,为了省事把此双向链表类型定义为dlist
typedef struct doublelist
{
	char data[100];
	struct doublelist *next;
	struct doublelist *fnext;
}dlist;

dlist * init_list()
{
	dlist *head = calloc(1,sizeof(dlist));
	// head->data = "1.bmp";
	//strcpy(head->data, "1.bmp");
	head->next = head;
	head->fnext = head;

	return head;
}

//尾插
int insert_(char * newdata,dlist * head)
{
	dlist * p =head;
	while(p->next != head)
	{
		p = p->next;
	}
	dlist *newnode = calloc(1,sizeof(dlist));
	//newnode->data = newdata;
	strcpy(newnode->data, newdata);
	newnode->next = head;
	p->next = newnode;
	head->fnext = newnode;
	newnode->fnext = p;
}

//读取目录,获得图片名字
int read_dir(char *path,dlist * head)
{
	DIR * dir = opendir(path);
	if (NULL == dir)
	{
		perror("打开目录失败!");
		exit(0);
	}

	struct dirent * rd = NULL;
	while((rd = readdir(dir)) != NULL) 
	{ 
		//printf("d_name : %s\n", rd->d_name); 
		if (rd->d_type == DT_REG)
	 	{
	 		//printf("这是普通文件!\n");
	 		if (strstr(rd->d_name,".bmp") != 0)
	 		{
	 			insert_(rd->d_name,head);
	 		}
	 	}

	 	// if (rd->d_type == DT_DIR)
	 	// {
	 	// 	printf("这是目录!\n");
	 	// 	system("cp *.txt ..");
	 	// 	system("cp *.txt abs");
	 	// }
	 }

	return 0;
}

//获取触摸屏坐标
int get_x_y(int *touch_x,int *touch_y)
{
	int flag = 0;

	int to = open ("/dev/input/event0",O_RDWR);
	
	if (-1 == to)
	{
		perror("打开触摸屏的驱动失败!");
		exit(0);
	}

	struct input_event myevent;
	while(1)
	{
		read(to,&myevent,sizeof(struct input_event));
		if (myevent.type == EV_ABS)
		{
			if(myevent.code==ABS_X) //x坐标
			//由于新开发板的坐标范围跟800*480不一致,按比例修正
			//printf("你点击的坐标位置X坐标是:%d\n",myevent.value);
			{
				flag++;
				* touch_x = (myevent.value*800)/1024;
			}
				
			if(myevent.code==ABS_Y) //y坐标
			{
				flag++;
				* touch_y = (myevent.value*480)/600;
			}

			if (2 == flag)
			{
				flag = 0;
				break;
			}
			
		}	
	}
	close(to);
}

//获取滑动方向的触摸屏坐标
int yxget_x_y(int *touch_x,int *touch_x1,int *touch_y,int *touch_y1)
{
    int flag = 1;

    int to = open ("/dev/input/event0",O_RDWR);
    
    if (-1 == to)
    {
        perror("打开触摸屏的驱动失败!");
        exit(0);
    }

    struct input_event myevent;
    int count = 1;
    while(1)
    {   
        read(to,&myevent,sizeof(struct input_event));
        if (myevent.type == EV_ABS)
        {   
            if(myevent.code==ABS_X) //x坐标
            //由于新开发板的坐标范围跟800*480不一致,按比例修正
            //printf("你点击的坐标位置X坐标是:%d\n",myevent.value);
            {   
                * touch_x1 = (myevent.value*800)/1024;
                if (count)
                {
                    * touch_x = (myevent.value*800)/1024;
                    count = 0;
                }                        
                
            }
                
            if(myevent.code==ABS_Y) //y坐标
            {
                * touch_y1 = (myevent.value*480)/600;
                if (flag)
                {
                    * touch_y = (myevent.value*480)/600;
                    flag = 0;
                }
                
                
            }
            
        }

        if(myevent.type==EV_KEY && myevent.code==BTN_TOUCH && myevent.value==0)
        {
            //count = 0;
            //printf("x0=%d,y0=%d\n", *touch_x,*touch_y);
            //printf("x1=%d,y1=%d\n", *touch_x1,*touch_y1);
            break;
        }

    }
    close(to);
}

//缩放图片--用于相册缩略图
int zoom1_showbmp(char *bmppath,int num)
{
	int bmpfd;
	int lcdfd;
	int w,h;
	
	//打开你要显示的w*h大小的bmp
	bmpfd=open(bmppath,O_RDWR);
	if(bmpfd==-1)
	{
		perror("打开图片失败!\n");
		return -1;
	}

	//读取图片的宽和高
	lseek(bmpfd,18,SEEK_SET);
	read(bmpfd,&w,4);//读取宽
	read(bmpfd,&h,4);//读取高

	//定义一个数组,依据图片的大小
	char bmpbuf[w*h*3]; //char占1个字节
	//定义另外一个数组,存放转换得到的ARGB数据
	int lcdbuf[w*h]; //int占4字节
	//定义中间变量。临时存放数据
	int tempbuf[w*h];

	//打开lcd驱动
	lcdfd=open("/dev/fb0",O_RDWR);
	if(lcdfd==-1)
	{
		perror("打开lcd失败!\n");
		return -1;
	}

	//映射得到lcd的首地址
	int *lcdmem=mmap(NULL,800*480*4,PROT_READ|PROT_WRITE,MAP_SHARED,lcdfd,0);
	if(lcdmem==NULL)
	{
		perror("映射lcd失败!\n");
		return -1;
	}
	
	//跳过bmp图片头信息54字节,从55字节开始读取
	lseek(bmpfd,54,SEEK_SET);
	
	//读取bmp图片的RGB数据
	//每三个字节为一组,构成一个像素点的RGB数据
	read(bmpfd,bmpbuf,w*h*3); //bmpbuf[0] bmpbuf[1] bmpbuf[2]
                                  //    B            G       R	
	                              //bmpbuf[3] bmpbuf[4] bmpbuf[5]  
	//把三个字节--》转换成四个字节
	/*
		细节分析如下:
		    lcdbuf[0]=0x00<<24|bmpbuf[0]<<16|bmpbuf[1]<<8|bmpbuf[2]
		    lcdbuf[1]=0x00<<24|bmpbuf[3]<<16|bmpbuf[4]<<8|bmpbuf[5] 
	*/
	for(int i=0; i<w*h; i++)
		lcdbuf[i]=0x00<<24|bmpbuf[3*i+2]<<16|bmpbuf[3*i+1]<<8|bmpbuf[3*i];
	
	//把颠倒的图片翻转过来
	/*
		细节分析如下:
		    lcdbuf[0] --->lcdbuf[479*800]
			
	*/
	for(int x=0; x<w; x++)
		for(int y=0; y<h; y++)
			//lcdbuf[(h-1-y)*w+x]=lcdbuf[y*w+x];
			tempbuf[(h-1-y)*w+x]=lcdbuf[y*w+x];
		
	/*//把转换后的数据写入lcd中,高缩小2倍,宽缩小2倍
	for (int j = 0,m = 0; j < (h/2); j++,m = m+2)
	{

		for(int i = 0,n = 0;i < (w/2);i++,n = n+2)
		{
			*(lcdmem+(j*800)+i)=tempbuf[m*w+n];             
		}
	}
	*/

	// //把转换后的数据写入lcd中,高缩小(h/160)倍,宽缩小w/160倍
	int a = (num%5)*160;
	int b = (num/5)*160;
	for (int j = 0,m = 0; j < (h/(h/160)); j = j-b+1,m = m+(h/160))
	{
		j = j+b;
		for(int i = 0,n = 0;i < (w/(w/160));i = i-a+1,n = n+(w/160))
		{
			i = i + a;
			*(lcdmem+(j*800)+i)=tempbuf[m*w+n];             
		}
	}	
	
	//关闭
	close(bmpfd);
	close(lcdfd);
	return 0;
}

//登陆和注册
int denglu()
{
	char usename[100] = {0};
	char newname[100] = {0};
	char password[100] = {0};
	char newword[100] = {0};
	int *touch_x = calloc(1,1000);
	int *touch_y = calloc(1,1000);

	//打开保存注册名字的文件
	int fd = open("a.txt",O_RDWR);
	if (-1 == fd)
	{
		perror("打开源文件失败");
		exit(0);
	}

	char  buf[1000] = {0};
	char  buff[1000] = {0};

	while(1)
	{
		//注册账号和密码
		get_x_y(touch_x,touch_y);
		if ((*touch_x>322) &&(*touch_x<361) && (*touch_y>258) && (*touch_y<277) )
		{	
			printf("请输入你想注册的账号!(<=12位)\n");
			scanf("%s",newname);
			printf("请输入你想注册的密码!(<=12位)\n");
			scanf("%s",newword);
			lseek(fd,0,SEEK_SET);
			write(fd,newname,sizeof(newname));
			
			lseek(fd,12,SEEK_SET);
			write(fd,newword,sizeof(newword));
			lseek(fd,12,SEEK_SET);
			
			printf("注册成功,请重新登陆\n");
			continue;
		}

		else
		{
			for (int i = 0; i < 100; ++i)
			{
				lseek(fd,24*i,SEEK_SET);
				read(fd,buf+i,12);//把注册名存到buf中
				lseek(fd,24*i+12,SEEK_SET);
				read(fd,buff+i,12);//把密码存到buff中
			}

			printf("请输入用户名!\n");//初始用户名我设置为chenwangxin
			scanf("%s",usename);

			printf("请输入密码!\n");//初始密码我设置为123456
			scanf("%s",password);


			if ((strcmp(usename,"chenwangxin") == 0) && (strcmp(password,"123456") == 0))
			{
				break;
			}

			 int i = 0;
			while ((strcmp(usename,buf+i) != 0) || (strcmp(password,buff+i) != 0))
			{
				i++;
				if (i = 99)
				{
					break;
				}
			}
			
			if ((strcmp(usename,buf+i) == 0) && (strcmp(password,buff+i) == 0))
			{
				break;
			}
			printf("用户名或密码错误,请重新输入!\n");
		}
		
	}

}

//我的相册
int myphoto()
{
	int *touch_x = calloc(1,1000);
	int *touch_y = calloc(1,1000);
	int *touch_x1 = calloc(1,1000);
    int *touch_y1 = calloc(1,1000);

	dlist *mydlist=init_list();
	read_dir("/myphoto/",mydlist);
	char a[500] = "/myphoto/";
	int page = 0;
	int count = 0;
	int num = 0;

	//计算总共有多少张图片
	dlist * p = mydlist;
	while(p->next != mydlist)
	{
		p = p->next;
		count++;
	}

	p = mydlist;
	while(p->next != NULL)
	{
		printf("点击底层中部进入音乐相册,顶层中部进入相册缩略图,点击可跳转对应对应图片。\n");
		yxget_x_y(touch_x,touch_x1,touch_y,touch_y1);
		//上一张
		if ((*touch_x<200) &&(*touch_y>360))
		{
			p = p->fnext;
			if (p == mydlist)
			{
				p = p->fnext;
			}		
			bzero(a,500);
			strcpy(a,"/myphoto/");
			strcat(a,p->data);
			//showbmp(a);
			printf("a里面的内容%s\n",a  );
			special_showbmp(a);
		}

		//下一张
		if ((*touch_x>600) && (*touch_y>360))
		{
			p = p->next;
			if (p == mydlist)
			{
				p = p->next;
			}
			bzero(a,500);
			strcpy(a,"/myphoto/");
			strcat(a,p->data);
			//showbmp(a);
			printf("a里面的内容%s\n",a  );
			special_showbmp(a);
		}

		//音乐相册
		if ((*touch_x>350) && (*touch_x<450) && (*touch_y>360))
		{
			system("./music_album");
			printf("退出音乐后要点击上/下一张回到相册后才能退出哦\n");
			bzero(touch_x,1000);
        	bzero(touch_y,1000);
			// continue;
		}

		//显示目录,加载目录中的照片
		if ((*touch_x>300) &&(*touch_x<500) && (*touch_y<66))
		{
			//开头显示第一页缩略图
			int k = 0;
			page = 0;
			p = mydlist;
			while(p->next != mydlist && k<15)
			{	
				k++;
				p = p->next;
				num++;
				bzero(a,500);
				strcpy(a,"/myphoto/");
				strcat(a,p->data);
				zoom1_showbmp(a,num-1);
			}
			num = 0;

			p = mydlist;
			while(1)
			{
				//到while循环的顶部了
				yxget_x_y(touch_x,touch_x1,touch_y,touch_y1);

				//向左划,下一页缩略图
				if((*touch_x>*touch_x1)&&((*touch_x-*touch_x1)>=80))
				{	
					if (count<=15)
					{
						printf("所有图片都在这里了噢。\n");
						continue;
					}

					if (page <= count/15)
					{
						page++;
					}

					if (page > count/15)
					{
						if (count%15 == 0)
						{
							printf("这已经是最后一页了。\n");
							if (page > count/15)
							{
								page--;
							}
							continue;
						}
					}					
					
					p = mydlist;
					for (int i = 0; i < 15*page; i++)
					{
						p = p->next;
					}
					k = 0;		
					while(p->next != mydlist && k<15)
					{	
						k++;
						p = p->next;
						num++;
						bzero(a,500);
						strcpy(a,"/myphoto/");
						strcat(a,p->data);
						zoom1_showbmp(a,num-1);
					}
				}
				num = 0;

				//向右划,上一页
				if( ((*touch_x1-*touch_x) >=80) && (*touch_x1>=*touch_x) )
				{	
					if (page==0)
					{
						printf("当前已经是第一页了。\n");
						continue;
					}
					
					page--;		

					p = mydlist;
					for (int i = 0; i < 15*page; i++)
					{
						p = p->next;
					}
					k = 0;		
					while(p->next != mydlist && k<15)
					{	
						k++;
						p = p->next;
						num++;
						bzero(a,500);
						strcpy(a,"/myphoto/");
						strcat(a,p->data);
						zoom1_showbmp(a,num-1);
					}
				}
				num = 0;

				//跳转点击到的图片
				if( ((*touch_x1-*touch_x) <80) && (*touch_x1>=*touch_x) )
				{
					int h = (*touch_x1/160) + (*touch_y1/160)*5;
					p = mydlist->next;
					for (int i = 0; i < 15*page; i++)
					{
						p = p->next;
					}

					for (int i = 0; i < h; i++)
					{
						if (p->next != mydlist)
						{
							p = p->next;
						}
						else
						{
							printf("当前位置没有对应图片,自动跳转到最后一张图片。\n");
							break;
						}
					}

					bzero(a,500);
					strcpy(a,"/myphoto/");
					strcat(a,p->data);
					special_showbmp(a);
					break;
				}

				//跳转点击到的图片
				if( ((*touch_x-*touch_x1) <80) && (*touch_x>=*touch_x1) )
				{
					int h = (*touch_x1/160) + (*touch_y1/160)*5;
					p = mydlist->next;
					for (int i = 0; i < 15*page; i++)
					{
						p = p->next;
					}

					for (int i = 0; i < h; i++)
					{
						if (p->next != mydlist)
						{
							p = p->next;
						}
						else
						{
							printf("当前位置没有对应图片,自动跳转到最后一张图片。\n");
							break;
						}
					}

					bzero(a,500);
					strcpy(a,"/myphoto/");
					strcat(a,p->data);
					special_showbmp(a);
					break;
				}

				//到while循环的底部了
			}
		}

		//退出相册
		if ((*touch_x>742) && (*touch_y<36))
		{
			break;
		}
	}
	printf("退出了我的相册\n");
}



//我的音乐
int mymusic()
{
	printf("左下方为上一首,右下方为上一首\n");
	printf("中间为暂停/播放,滑动快进/退\n");
	system("./mymusic");
	printf("退出了我的音乐\n");
}

//我的视频
int myvideo()
{
	printf("左下方为上一集,右下方为上一集\n");
	printf("中间为暂停/播放,滑动快进/退\n");
	system("./myvideo");
	printf("退出了我的视频\n");
}


int main(int argc, char const *argv[])
{
	int *touch_x = calloc(1,1000);
	int *touch_y = calloc(1,1000);

	showbmp("dl.bmp");
	printf("点击登陆或注册后登陆才能进入我的娱乐世界哦\n");

	//登陆和注册
	denglu();
	printf("登陆成功,欢迎进入我的娱乐世界!\n");
	showbmp("zjm.bmp");
	printf("使用相册和音视频播放器等应用时:左下角为播放上一张/首/个,右下角为播放下一张/首/个,左上角为退出当前应用\n");
	

	while(1)
	{
		//打开相册
		get_x_y(touch_x,touch_y);
		if ((*touch_x>22) &&(*touch_x<96) && (*touch_y>144) && (*touch_y<222) )
		{
			special_showbmp("1.bmp");
			sleep(1);
			zoom_showbmp("3.bmp");
			myphoto();
		}
		showbmp("zjm.bmp");

		//打开音乐播放器
		if ((*touch_x>31) &&(*touch_x<102) && (*touch_y>23) && (*touch_y<98) )
		{
			showbmp("mymp3.bmp");
			printf("已经打开音乐播放器,请点击进行播放音乐!\n");
			mymusic();
		}
		showbmp("zjm.bmp");

		//打开视频播放器
		if ((*touch_x>129) &&(*touch_x<207) && (*touch_y>23) && (*touch_y<108) )
		{
			printf("已经打开视频播放器,请点击上/下一集进行播放视频!\n");
			showbmp("mymp3.bmp");
			myvideo();
		}
		showbmp("zjm.bmp");

		if ((*touch_x>119) &&(*touch_x<199) && (*touch_y>140) && (*touch_y<217) )
        {
            system("./yx1");
        }
        showbmp("zjm.bmp");
	}
	
	
	
	return 0;
}

上面的是主代码,2048代码,音频模块,视频模块,新增的音乐相册如下:
(2048还有待改善)

音频模块

//音频模块,下面的视频模块的思路也是一样的

//音频模块
#include "myiohead.h"

//获取滑动方向的触摸屏坐标
int yxget_x_y(int *touch_x,int *touch_x1,int *touch_y,int *touch_y1)
{
    int flag = 1;

    int to = open ("/dev/input/event0",O_RDWR);
    
    if (-1 == to)
    {
        perror("打开触摸屏的驱动失败!");
        exit(0);
    }

    struct input_event myevent;
    int count = 1;
    while(1)
    {   
        read(to,&myevent,sizeof(struct input_event));
        if (myevent.type == EV_ABS)
        {   
            if(myevent.code==ABS_X) //x坐标
            //由于新开发板的坐标范围跟800*480不一致,按比例修正
            //printf("你点击的坐标位置X坐标是:%d\n",myevent.value);
            {   
                * touch_x1 = (myevent.value*800)/1024;
                if (count)
                {
                    * touch_x = (myevent.value*800)/1024;
                    count = 0;
                }                        
                
            }
                
            if(myevent.code==ABS_Y) //y坐标
            {
                * touch_y1 = (myevent.value*480)/600;
                if (flag)
                {
                    * touch_y = (myevent.value*480)/600;
                    flag = 0;
                }
                
                
            }
            
        }

        if(myevent.type==EV_KEY && myevent.code==BTN_TOUCH && myevent.value==0)
        {
            //count = 0;
            //printf("x0=%d,y0=%d\n", *touch_x,*touch_y);
            //printf("x1=%d,y1=%d\n", *touch_x1,*touch_y1);
            break;
        }

    }
    close(to);
}

//定义一个结构体表示双向循环列表,为了省事把此双向链表类型定义为dlist
typedef struct doublelist
{
	char data[100];
	struct doublelist *next;
	struct doublelist *fnext;
}dlist;

dlist * init_list()
{
	dlist *head = calloc(1,sizeof(dlist));
	// head->data = "1.bmp";
	strcpy(head->data, "1.bmp");
	head->next = head;
	head->fnext = head;

	return head;
}

//尾插
int insert_(char * newdata,dlist * head)
{
	dlist * p =head;
	while(p->next != head)
	{
		p = p->next;
	}
	dlist *newnode = calloc(1,sizeof(dlist));
	//newnode->data = newdata;
	strcpy(newnode->data, newdata);
	newnode->next = head;
	p->next = newnode;
	head->fnext = newnode;
	newnode->fnext = p;
}

//读取目录,获得音乐名字
int read_dir(char *path,dlist * head)
{
	DIR * dir = opendir(path);
	if (NULL == dir)
	{
		perror("打开目录失败!");
		exit(0);
	}

	struct dirent * rd = NULL;
	while((rd = readdir(dir)) != NULL) 
	{ 
		//printf("d_name : %s\n", rd->d_name); 
		if (rd->d_type == DT_REG)
	 	{
	 		//printf("这是普通文件!\n");
	 		if (strstr(rd->d_name,".mp3") != 0)
	 		{
	 			insert_(rd->d_name,head);
	 		}
	 	}

	 	// if (rd->d_type == DT_DIR)
	 	// {
	 	// 	printf("这是目录!\n");
	 	// 	system("cp *.txt ..");
	 	// 	system("cp *.txt abs");
	 	// }
	 }

	return 0;
}

void * task(void * n)//播放/暂停/快进/快退/上/下一首音乐
{
	int *touch_x1 = calloc(1,1000);
    int *touch_y1 = calloc(1,1000);
    int *touch_x = calloc(1,1000);
    int *touch_y = calloc(1,1000);

	dlist * mydlist = init_list();
	read_dir("/myword/2048bmp/",mydlist);
	char a[100] = {0};
	if (access("/root/myfifo",F_OK) == -1)
	{
		int ret = mkfifo("/root/myfifo",0777);
		if (-1 == ret)
		{
			perror("创建管道文件失败!");
			exit(0);
		}
	}
	int fd = open("/root/myfifo", O_RDWR);
	if (-1 == fd)
	{
		perror("打开管道文件失败!");
		exit(0);
	}

	dlist * p =mydlist;
	int count = 0;
	int flag = 2;
	while(1)
	{
		yxget_x_y(touch_x,touch_x1,touch_y,touch_y1);
		if ((*touch_x<200)&&(*touch_y>360))//上一首
		{
			if (count == 1)
			{
				system("killall -9 mplayer");
			}
			
			p = p->fnext;
			if (p == mydlist)
			{
				p = p->fnext;
			}
			bzero(a,100);
			strcpy(a,"mplayer -quiet -slave -input file=/root/myfifo /myword/2048bmp/");
			strcat(a,p->data);
			strcat(a," &");
			system(a);
			count = 1;
			flag = 1;
		}

		if ((*touch_x>600) && (*touch_y>360))//下一首
		{
			if (count == 1)
			{
				system("killall -9 mplayer");
			}

			p = p->next;
			if (p == mydlist)
			{
				p = p->next;
			}
			bzero(a,100);
			strcpy(a,"mplayer -quiet -slave -input file=/root/myfifo /myword/2048bmp/");
			strcat(a,p->data);
			strcat(a," &");
			system(a);
			count = 1;
			flag = 1;
		}

		if ((*touch_x>358) && (*touch_x<414) && (*touch_y>203) && (*touch_y<268)) //暂停/播放
		{
			if (flag == 1)//暂停
			{
				system("killall  -STOP  mplayer");
				flag = 0;
			}

			else if (flag == 0)//播放
			{
				system("killall  -CONT  mplayer");
				flag = 1;
			}
		}

		//快退5秒
		if((*touch_x>*touch_x1)&&((*touch_x-*touch_x1)>=80))
		{
			/// 写入的字节数一定要和实际一模一样,不然会出问题
			// 不能快进快退
			char msg[] = "seek -5\n";
			write (fd,msg,strlen(msg));		
		}

		//快进5s
		if((*touch_x1>*touch_x)&&((*touch_x1-*touch_x)>=80))
		{
			// 写入的字节数一定要和实际一模一样,不然会出问题
			// 不能快进快退
			char msg[] = "seek 5\n";
			write (fd,msg,strlen(msg));
		}

		if ((*touch_x>742) && (*touch_y<36))
        {
        	system("killall -9 mplayer");
        	raise(9);
           	break;
        }

	}
	
}

int main(int argc, char const *argv[])
{
	pthread_t id;
	pthread_create(&id,NULL,task, NULL);

  	pthread_join(id,NULL);
	return 0;
}

视频模块

视频模块(和音频大同小异)

//这里是视频模块
#include "myiohead.h"

//获取滑动方向的触摸屏坐标
int yxget_x_y(int *touch_x,int *touch_x1,int *touch_y,int *touch_y1)
{
    int flag = 1;

    int to = open ("/dev/input/event0",O_RDWR);
    
    if (-1 == to)
    {
        perror("打开触摸屏的驱动失败!");
        exit(0);
    }

    struct input_event myevent;
    int count = 1;
    while(1)
    {   
        read(to,&myevent,sizeof(struct input_event));
        if (myevent.type == EV_ABS)
        {   
            if(myevent.code==ABS_X) //x坐标
            //由于新开发板的坐标范围跟800*480不一致,按比例修正
            //printf("你点击的坐标位置X坐标是:%d\n",myevent.value);
            {   
                * touch_x1 = (myevent.value*800)/1024;
                if (count)
                {
                    * touch_x = (myevent.value*800)/1024;
                    count = 0;
                }                        
                
            }
                
            if(myevent.code==ABS_Y) //y坐标
            {
                * touch_y1 = (myevent.value*480)/600;
                if (flag)
                {
                    * touch_y = (myevent.value*480)/600;
                    flag = 0;
                }
                
                
            }
            
        }

        if(myevent.type==EV_KEY && myevent.code==BTN_TOUCH && myevent.value==0)
        {
            //count = 0;
            //printf("x0=%d,y0=%d\n", *touch_x,*touch_y);
            //printf("x1=%d,y1=%d\n", *touch_x1,*touch_y1);
            break;
        }

    }
    close(to);
}

//定义一个结构体表示双向循环列表,为了省事把此双向链表类型定义为dlist
typedef struct doublelist
{
	char data[100];
	struct doublelist *next;
	struct doublelist *fnext;
}dlist;

dlist * init_list()
{
	dlist *head = calloc(1,sizeof(dlist));
	// head->data = "1.bmp";
	strcpy(head->data, "1.bmp");
	head->next = head;
	head->fnext = head;

	return head;
}

//尾插
int insert_(char * newdata,dlist * head)
{
	dlist * p =head;
	while(p->next != head)
	{
		p = p->next;
	}
	dlist *newnode = calloc(1,sizeof(dlist));
	//newnode->data = newdata;
	strcpy(newnode->data, newdata);
	newnode->next = head;
	p->next = newnode;
	head->fnext = newnode;
	newnode->fnext = p;
}

//读取目录,获得音乐名字
int read_dir(char *path,dlist * head)
{
	DIR * dir = opendir(path);
	if (NULL == dir)
	{
		perror("打开目录失败!");
		exit(0);
	}

	struct dirent * rd = NULL;
	while((rd = readdir(dir)) != NULL) 
	{ 
		//printf("d_name : %s\n", rd->d_name); 
		if (rd->d_type == DT_REG)
	 	{
	 		//printf("这是普通文件!\n");
	 		if (strstr(rd->d_name,".avi") != 0)
	 		{
	 			insert_(rd->d_name,head);
	 		}
	 	}

	 	// if (rd->d_type == DT_DIR)
	 	// {
	 	// 	printf("这是目录!\n");
	 	// 	system("cp *.txt ..");
	 	// 	system("cp *.txt abs");
	 	// }
	 }

	return 0;
}

void * task(void * n)//播放/暂停/快进/快退/上/下一个视频
{
	int *touch_x1 = calloc(1,1000);
    int *touch_y1 = calloc(1,1000);
    int *touch_x = calloc(1,1000);
    int *touch_y = calloc(1,1000);

	dlist * mydlist = init_list();
	read_dir("/myword/2048bmp/",mydlist);
	char a[100] = {0};
	if (access("/root/myfifo",F_OK) == -1)
	{
		int ret = mkfifo("/root/myfifo",0777);
		if (-1 == ret)
		{
			perror("创建管道文件失败!");
			exit(0);
		}
	}
	int fd = open("/root/myfifo", O_RDWR);
	if (-1 == fd)
	{
		perror("打开管道文件失败!");
		exit(0);
	}

	dlist * p =mydlist;
	int count = 0;
	int flag = 2;
	while(1)
	{
		yxget_x_y(touch_x,touch_x1,touch_y,touch_y1);
		if ((*touch_x<200)&&(*touch_y>360))//上一个
		{
			if (count == 1)
			{
				system("killall -9 mplayer");
			}
			
			p = p->fnext;
			if (p == mydlist)
			{
				p = p->fnext;
			}
			bzero(a,100);
			strcpy(a,"mplayer -quiet -slave -input file=/root/myfifo /myword/2048bmp/");
			strcat(a,p->data);
			strcat(a," &");
			system(a);
			count = 1;
			flag = 1;
		}

		if ((*touch_x>600) && (*touch_y>360))//下一个
		{
			if (count == 1)
			{
				system("killall -9 mplayer");
			}

			p = p->next;
			if (p == mydlist)
			{
				p = p->next;
			}
			bzero(a,100);
			strcpy(a,"mplayer -quiet -slave -input file=/root/myfifo /myword/2048bmp/");
			strcat(a,p->data);
			strcat(a," &");
			system(a);
			count = 1;
			flag = 1;
		}

		if ((*touch_x>358) && (*touch_x<414) && (*touch_y>203) && (*touch_y<268)) //暂停/播放
		{
			if (flag == 1)//暂停
			{
				system("killall  -STOP  mplayer");
				flag = 0;
			}

			else if (flag == 0)//播放
			{
				system("killall  -CONT  mplayer");
				flag = 1;
			}
		}

		//快退5秒
		if((*touch_x>*touch_x1)&&((*touch_x-*touch_x1)>=80))
		{
			/// 写入的字节数一定要和实际一模一样,不然会出问题
			// 不能快进快退
			char msg[] = "seek -5\n";
			write (fd,msg,strlen(msg));		
		}

		//快进5s
		if((*touch_x1>*touch_x)&&((*touch_x1-*touch_x)>=80))
		{
			// 写入的字节数一定要和实际一模一样,不然会出问题
			// 不能快进快退
			char msg[] = "seek 5\n";
			write (fd,msg,strlen(msg));
		}

		if ((*touch_x>742) && (*touch_y<36))
        {
        	system("killall -9 mplayer");
        	raise(9);
           	break;
        }

	}
	
}

int main(int argc, char const *argv[])
{
	pthread_t id;
	pthread_create(&id,NULL,task, NULL);

  	pthread_join(id,NULL);
	return 0;
}

音乐相册

音乐相册

//音乐相册
#include "myiohead.h"

//获取触摸屏坐标
int get_x_y(int *touch_x,int *touch_y)
{
    int flag = 0;

    int to = open ("/dev/input/event0",O_RDWR);
    
    if (-1 == to)
    {
        perror("打开触摸屏的驱动失败!");
        exit(0);
    }

    struct input_event myevent;
    while(1)
    {
        read(to,&myevent,sizeof(struct input_event));
        if (myevent.type == EV_ABS)
        {
            if(myevent.code==ABS_X) //x坐标
            //由于新开发板的坐标范围跟800*480不一致,按比例修正
            //printf("你点击的坐标位置X坐标是:%d\n",myevent.value);
            {
                flag++;
                * touch_x = (myevent.value*800)/1024;
            }
                
            if(myevent.code==ABS_Y) //y坐标
            {
                flag++;
                * touch_y = (myevent.value*480)/600;
            }

            if (2 == flag)
            {
                flag = 0;
                break;
            }
            
        }   
    }
    close(to);
}

//普通展示图片
int showbmp(char *bmppath)
{
	int bmpfd;
	int lcdfd;
	int w,h;
	int i;
	int x,y;
	
	//打开你要显示的w*h大小的bmp
	bmpfd=open(bmppath,O_RDWR);
	if(bmpfd==-1)
	{
		perror("打开图片失败!\n");
		return -1;
	}

	//读取图片的宽和高
	lseek(bmpfd,18,SEEK_SET);
	read(bmpfd,&w,4);//读取宽
	read(bmpfd,&h,4);//读取高

	//定义一个数组,依据图片的大小
	char bmpbuf[w*h*3]; //char占1个字节
	//定义另外一个数组,存放转换得到的ARGB数据
	int lcdbuf[w*h]; //int占4字节
	//定义中间变量。临时存放数据
	int tempbuf[w*h];

	//打开lcd驱动
	lcdfd=open("/dev/fb0",O_RDWR);
	if(lcdfd==-1)
	{
		perror("打开lcd失败!\n");
		return -1;
	}

	//映射得到lcd的首地址
	int *lcdmem=mmap(NULL,800*480*4,PROT_READ|PROT_WRITE,MAP_SHARED,lcdfd,0);
	if(lcdmem==NULL)
	{
		perror("映射lcd失败!\n");
		return -1;
	}

	
	
	//跳过bmp图片头信息54字节,从55字节开始读取
	lseek(bmpfd,54,SEEK_SET);
	
	//读取bmp图片的RGB数据
	//每三个字节为一组,构成一个像素点的RGB数据
	read(bmpfd,bmpbuf,w*h*3); //bmpbuf[0] bmpbuf[1] bmpbuf[2]
                                  //    B            G       R	
	                              //bmpbuf[3] bmpbuf[4] bmpbuf[5]  
	//把三个字节--》转换成四个字节
	/*
		细节分析如下:
		    lcdbuf[0]=0x00<<24|bmpbuf[0]<<16|bmpbuf[1]<<8|bmpbuf[2]
		    lcdbuf[1]=0x00<<24|bmpbuf[3]<<16|bmpbuf[4]<<8|bmpbuf[5] 
	*/
	for(i=0; i<w*h; i++)
		lcdbuf[i]=0x00<<24|bmpbuf[3*i+2]<<16|bmpbuf[3*i+1]<<8|bmpbuf[3*i];
	
	//把颠倒的图片翻转过来
	/*
		细节分析如下:
		    lcdbuf[0] --->lcdbuf[479*800]
			
	*/
	for(x=0; x<w; x++)
		for(y=0; y<h; y++)
			//lcdbuf[(h-1-y)*w+x]=lcdbuf[y*w+x];
			tempbuf[(h-1-y)*w+x]=lcdbuf[y*w+x];
		
	//把转换后的数据写入lcd中
	for (int j = 0; j < h; j++)
	{
		for(int i = 0,n = 0;i < w;i++)
		{
			*(lcdmem+(j*800)+i)=tempbuf[j*w+i];  
			//n++;           
		}
	}
	
	
	//关闭
	close(bmpfd);
	close(lcdfd);
	return 0;
}

 //定义一个结构体表示双向循环列表,为了省事把此双向链表类型定义为dlist
typedef struct doublelist
{
	char data[100];
	struct doublelist *next;
	struct doublelist *fnext;
}dlist;

dlist * init_list()
{
	dlist *head = calloc(1,sizeof(dlist));
	// head->data = "1.bmp";
	strcpy(head->data, "1.bmp");
	head->next = head;
	head->fnext = head;

	return head;
}

//尾插
int insert_(char * newdata,dlist * head)
{
	dlist * p =head;
	while(p->next != head)
	{
		p = p->next;
	}
	dlist *newnode = calloc(1,sizeof(dlist));
	//newnode->data = newdata;
	strcpy(newnode->data, newdata);
	newnode->next = head;
	p->next = newnode;
	head->fnext = newnode;
	newnode->fnext = p;
}

//读取目录,获得图片名字
int read_dir(char *path,dlist * head)
{
	DIR * dir = opendir(path);
	if (NULL == dir)
	{
		perror("打开目录失败!");
		exit(0);
	}

	struct dirent * rd = NULL;
	while((rd = readdir(dir)) != NULL) 
	{ 
		//printf("d_name : %s\n", rd->d_name); 
		if (rd->d_type == DT_REG)
	 	{
	 		//printf("这是普通文件!\n");
	 		if (strstr(rd->d_name,".bmp") != 0)
	 		{
	 			insert_(rd->d_name,head);
	 		}
	 	}

	 	// if (rd->d_type == DT_DIR)
	 	// {
	 	// 	printf("这是目录!\n");
	 	// 	system("cp *.txt ..");
	 	// 	system("cp *.txt abs");
	 	// }
	 }

	return 0;
}

void * task(void * n)//循环播放相册
{
	dlist * mydlist = init_list();
	read_dir("/myphoto",mydlist);
	char a[100] = "/myphoto/";

	dlist * p =mydlist;
	while(p->next != NULL)
	{
		p = p->next;
		if (p == mydlist)
		{
			p = p->next;
		}
		bzero(a,100);
		strcpy(a,"/myphoto/");
		strcat(a,p->data);
		showbmp(a);
		sleep(1);
	}	
}

void * task1(void * n)
{
	system("mplayer Apologize.mp3 &");
}

int main(int argc, char const *argv[])
{
	pthread_t id;
	pthread_create(&id,NULL,task, NULL);

	pthread_t id1;
	pthread_create(&id1,NULL,task1, NULL);

	int *touch_x = calloc(1,1000);
	int *touch_y = calloc(1,1000);

	while(1)
	{
		get_x_y(touch_x,touch_y);
		if ((*touch_x>742) && (*touch_y<36))
        {
        	pthread_cancel(id);
        	pthread_cancel(id1);
        	system("killall -9 mplayer");
        	raise(9);
           	break;
        }	
	}


	return 0;
}

2048

下面是2048小游戏

#include "myiohead.h"

int showbmp(int w,int h,char *bmppath)
{
    int bmpfd;
    int lcdfd;
    int i;
    int x,y;
    //定义一个数组,依据图片的大小
    char bmpbuf[w*h*3]; //char占1个字节
    //定义另外一个数组,存放转换得到的ARGB数据
    int lcdbuf[w*h]; //int占4字节
    //定义中间变量。临时存放数据
    int tempbuf[w*h];
    //打开你要显示的w*h大小的bmp
    bmpfd=open(bmppath,O_RDWR);
    if(bmpfd==-1)
    {
        perror("打开图片失败!\n");
        return -1;
    }
    //打开lcd驱动
    lcdfd=open("/dev/fb0",O_RDWR);
    if(lcdfd==-1)
    {
        perror("打开lcd失败!\n");
        return -1;
    }

    //映射得到lcd的首地址
    int *lcdmem=mmap(NULL,800*480*4,PROT_READ|PROT_WRITE,MAP_SHARED,lcdfd,0);
    if(lcdmem==NULL)
    {
        perror("映射lcd失败!\n");
        return -1;
    }
    
    //跳过bmp图片头信息54字节,从55字节开始读取
    lseek(bmpfd,54,SEEK_SET);
    
    //读取bmp图片的RGB数据
    //每三个字节为一组,构成一个像素点的RGB数据
    read(bmpfd,bmpbuf,w*h*3); //bmpbuf[0] bmpbuf[1] bmpbuf[2]
                                  //    B            G       R  
                                  //bmpbuf[3] bmpbuf[4] bmpbuf[5]  
    //把三个字节--》转换成四个字节
    /*
        细节分析如下:
            lcdbuf[0]=0x00<<24|bmpbuf[0]<<16|bmpbuf[1]<<8|bmpbuf[2]
            lcdbuf[1]=0x00<<24|bmpbuf[3]<<16|bmpbuf[4]<<8|bmpbuf[5] 
    */
    for(i=0; i<w*h; i++)
        lcdbuf[i]=0x00<<24|bmpbuf[3*i+2]<<16|bmpbuf[3*i+1]<<8|bmpbuf[3*i];
    
    //把颠倒的图片翻转过来
    /*
        细节分析如下:
            lcdbuf[0] --->lcdbuf[479*800]
            
    */
    for(x=0; x<w; x++)
        for(y=0; y<h; y++)
            //lcdbuf[(h-1-y)*w+x]=lcdbuf[y*w+x];
            tempbuf[(h-1-y)*w+x]=lcdbuf[y*w+x];
        
    //把转换后的数据写入lcd中
    for (int j = 0; j < h; j++)
    {
        for(int i = 0,n = 0;i < w;i++)
        {
            *(lcdmem+(j*800)+i)=tempbuf[j*w+i];  
            //n++;           
        }
    }
    
    
    //关闭
    close(bmpfd);
    close(lcdfd);
    return 0;
}

//2048数字图片的映射
int showyxbmp(int w,int h,int r,int s,char *bmppath)
{
    int bmpfd;
    int lcdfd;
    int i;
    int x,y;
    //定义一个数组,依据图片的大小
    char bmpbuf[w*h*3]; //char占1个字节
    //定义另外一个数组,存放转换得到的ARGB数据
    int lcdbuf[w*h]; //int占4字节
    //定义中间变量。临时存放数据
    int tempbuf[w*h];
    //打开你要显示的w*h大小的bmp
    bmpfd=open(bmppath,O_RDWR);
    if(bmpfd==-1)
    {
        perror("打开图片失败!\n");
        return -1;
    }
    //打开lcd驱动
    lcdfd=open("/dev/fb0",O_RDWR);
    if(lcdfd==-1)
    {
        perror("打开lcd失败!\n");
        return -1;
    }

    //映射得到lcd的首地址
    int *lcdmem=mmap(NULL,800*480*4,PROT_READ|PROT_WRITE,MAP_SHARED,lcdfd,0);
    if(lcdmem==NULL)
    {
        perror("映射lcd失败!\n");
        return -1;
    }
    
    //跳过bmp图片头信息54字节,从55字节开始读取
    lseek(bmpfd,54,SEEK_SET);
    
    //读取bmp图片的RGB数据
    //每三个字节为一组,构成一个像素点的RGB数据
    read(bmpfd,bmpbuf,w*h*3); //bmpbuf[0] bmpbuf[1] bmpbuf[2]
                                  //    B            G       R  
                                  //bmpbuf[3] bmpbuf[4] bmpbuf[5]  
    //把三个字节--》转换成四个字节
    /*
        细节分析如下:
            lcdbuf[0]=0x00<<24|bmpbuf[0]<<16|bmpbuf[1]<<8|bmpbuf[2]
            lcdbuf[1]=0x00<<24|bmpbuf[3]<<16|bmpbuf[4]<<8|bmpbuf[5] 
    */
    for(i=0; i<w*h; i++)
        lcdbuf[i]=0x00<<24|bmpbuf[3*i+2]<<16|bmpbuf[3*i+1]<<8|bmpbuf[3*i];
    
    //把颠倒的图片翻转过来
    /*
        细节分析如下:
            lcdbuf[0] --->lcdbuf[479*800]
            
    */
    for(x=0; x<w; x++)
        for(y=0; y<h; y++)
            //lcdbuf[(h-1-y)*w+x]=lcdbuf[y*w+x];
            tempbuf[(h-1-y)*w+x]=lcdbuf[y*w+x];
        
    //把转换后的数据写入lcd中
    for (int j = 0; j < h; j++)
    {
        for(int i = 0,n = 0;i < w;i++)
        {
        	//我的背景方格是360*360,也就是每个小格子为90*90
            *(lcdmem+((j*800)+(90*s)+(90*800*r))+i)=tempbuf[j*w+i]; 
            //*(lcdmem+(j*800)+i)=tempbuf[j*w+i];            
        }
    }
    
    // //把转换后的数据写入lcd中
    // lseek(lcdfd,((90*s)+(r*90*800))*4,SEEK_SET);
    // for(int i = 0;i < h;i++)
    // {
    //  write(lcdfd,&tempbuf[w*i],w*4);
    //  lseek(lcdfd,(800-w)*4,SEEK_CUR);
                      
    // }

    //关闭
    close(bmpfd);
    close(lcdfd);
    return 0;
}

//获取触摸屏坐标
// int get_x_y(int *touch_x,int *touch_y)
// {
//     int flag = 0;

//     int to = open ("/dev/input/event0",O_RDWR);
    
//     if (-1 == to)
//     {
//         perror("打开触摸屏的驱动失败!");
//         exit(0);
//     }

//     struct input_event myevent;
//     while(1)
//     {
//         read(to,&myevent,sizeof(struct input_event));
//         if (myevent.type == EV_ABS)
//         {
//             if(myevent.code==ABS_X) //x坐标
//             //由于新开发板的坐标范围跟800*480不一致,按比例修正
//             //printf("你点击的坐标位置X坐标是:%d\n",myevent.value);
//             {
//                 flag++;
//                 * touch_x = (myevent.value*800)/1024;
//             }
                
//             if(myevent.code==ABS_Y) //y坐标
//             {
//                 flag++;
//                 * touch_y = (myevent.value*480)/600;
//             }

//             if (2 == flag)
//             {
//                 flag = 0;
//                 break;
//             }
            
//         }   
//     }
//     close(to);
// }

//获取游戏滑动方向的触摸屏坐标
int yxget_x_y(int *touch_x,int *touch_x1,int *touch_y,int *touch_y1)
{
    int flag = 1;

    int to = open ("/dev/input/event0",O_RDWR);
    
    if (-1 == to)
    {
        perror("打开触摸屏的驱动失败!");
        exit(0);
    }

    struct input_event myevent;
    int count = 1;
    while(1)
    {   
        read(to,&myevent,sizeof(struct input_event));
        if (myevent.type == EV_ABS)
        {   
            if(myevent.code==ABS_X) //x坐标
            //由于新开发板的坐标范围跟800*480不一致,按比例修正
            //printf("你点击的坐标位置X坐标是:%d\n",myevent.value);
            {   
                * touch_x1 = (myevent.value*800)/1024;
                if (count)
                {
                    * touch_x = (myevent.value*800)/1024;
                    count = 0;
                }
                    
                
                
            }
                
            if(myevent.code==ABS_Y) //y坐标
            {
                * touch_y1 = (myevent.value*480)/600;
                if (flag)
                {
                    * touch_y = (myevent.value*480)/600;
                    flag = 0;
                }
                
                
            }
            
        }

        if(myevent.type==EV_KEY && myevent.code==BTN_TOUCH && myevent.value==0)
        {
            //count = 0;
            //printf("x0=%d,y0=%d\n", *touch_x,*touch_y);
            //printf("x1=%d,y1=%d\n", *touch_x1,*touch_y1);
            break;
        }

    }
    close(to);
}

int play_game()
{
    int *touch_x1 = calloc(1,1000);
    int *touch_y1 = calloc(1,1000);
    int *touch_x = calloc(1,1000);
    int *touch_y = calloc(1,1000);
    int ifmove = 0;

    showbmp(360,360,"2048.bmp");

    /* 了解到游戏初始化时出现的两个数一定会有个2,所以先随机生成一个2,其他均为0 */
    int n;
    n = rand() % 16;
    int board[4][4] = {0};
    
    for (int i = 0; i < 4; ++i) 
    {
        
        for (int j = 0; j < 4; ++j) 
        {
            board[i][j] = (n-- == 0 ? 2 : 0);
        }
    }

    /* 前面已经生成了一个2,这里再生成一个随机的2或者4,概率之比9:1 */
    n = 0;
    for (int i = 0; i < 4; ++i) 
    {
        
        for (int j = 0; j < 4; ++j) 
        {
            if (board[i][j] == 0)
            {
                n = n+1;
            }          
        }
    }
    srand((unsigned int) time(0));
    n = rand() % n; /* 确定在何处空位置生成随机数 */
    for (int i = 0; i < 4; ++i) 
    {       
        for (int j = 0; j < 4; ++j) 
        {
            /* 定位待生成的位置 */
            if (board[i][j] == 0 && n-- == 0) 
            {
                board[i][j] = (rand() % 10 ? 2 : 4); /* 生成数字2或4,生成概率为9:1 */
            }
        }
    }

    //展示初始画面
    for (int i = 0; i < 4; ++i) 
    {
        
        for (int j = 0; j < 4; ++j) 
        {
            if (board[i][j] == 0)
            {
                showyxbmp(80,80,i,j,"num0.bmp");
            } 

            if (board[i][j] == 2)
            {
                showyxbmp(80,80,i,j,"num2.bmp");
            }  

            if (board[i][j] == 4)
            {
                showyxbmp(80,80,i,j,"num4.bmp");
            }       
        }
    }


    while(1)
    {
        yxget_x_y(touch_x,touch_x1,touch_y,touch_y1);
        //printf("x是%d,x1是%d,y是%d,y1是%d\n", *touch_x,*touch_x1,*touch_y,*touch_y1);
        //向左划
        if((*touch_y1-*touch_y)<(*touch_x-*touch_x1)&&(*touch_y1-*touch_y)>(*touch_x1-*touch_x))
        {
            // printf("这里是左\n");
            ifmove = 1;
            for (int i = 0; i < 4; i++) 
            {
                /* 变量i用来遍历行项的下标,并且在移动时所有行相互独立,互不影响 */
                /* 变量j为列下标,变量k为待比较(合并)项的下标,循环进入时k<j */
                for (int j = 3; j >= 0; j--) 
                {
                    int k = 0;
                    if (board[i][j] == 0) /* 找出k后面第一个不为空的项,下标为j,之后分三种情况 */
                    {
                        continue; 
                    }

                    if (j != 0)
                    {
                        k = j-1;
                    }
                    else 
                        k = 0;
                    

                    while(board[i][k] == 0)
                    {
                        board[i][k] = board[i][j];
                        board[i][j] = 0;
                        if (k != 0)
                        {
                            k--;
                        }
                        else
                            break;
                        
                    }
                    if (board[i][j] == 0) 
                    {
                        continue;
                    }

                    if (board[i][j] == board[i][k] && j != 0)
                    {
                        board[i][k] = 2*board[i][k];
                        board[i][j] = 0;
                    }

                    if (board[i][j] != board[i][k] && board[i][k] != 0)
                    {
                        if ((k+1) !=j)
                        {
                            board[i][k+1] = board[i][j];
                            board[i][j] = 0;
                        }
                    }

                    if (board[i][j] != board[i][k] && board[i][k] == 0)
                    {
                        board[i][k] = board[i][j];
                        board[i][j] = 0;
                    }

                }
            }

            
        }

        //向右划
        else if((*touch_x1-*touch_x)>(*touch_y1-*touch_y)&&(*touch_x1-*touch_x)>(*touch_y-*touch_y1))
        {   
            // printf("这里是右\n");
            ifmove = 1;
            for (int i = 0; i < 4; i++) 
            {
                for (int j = 0; j < 4; j++) 
                {
                    int k = 0;
                    if (board[i][j] == 0) 
                    {
                        continue;
                    }

                    if (j != 3)
                    {
                        k = j+1;
                    }
                    else
                        k = 3;
                    

                    while(board[i][k] == 0 )
                    {
                        board[i][k] = board[i][j];
                        board[i][j] = 0;
                        if (k != 3)
                        {
                            k++;
                        }
                        else
                            break;
                    }

                    if (board[i][j] == 0) 
                    {
                        continue;
                    }

                    if (board[i][j] == board[i][k] && j !=3)
                    {
                        board[i][k] = 2*board[i][k];
                        board[i][j] = 0;
                    }

                    if (board[i][j] != board[i][k] && board[i][k] != 0)
                    {
                        if ((k-1)!=j)
                        {
                           board[i][k-1] = board[i][j];
                           board[i][j] = 0;
                        }
                    }

                    if (board[i][j] != board[i][k] && board[i][k] == 0)
                    {
                        board[i][k] = board[i][j];
                        board[i][j] = 0;
                    }
                }
            }

            
        }



        //向上划
         else if((*touch_x1-*touch_x)>(*touch_y1-*touch_y)&&(*touch_x1-*touch_x)<(*touch_y-*touch_y1))
        {   
            // printf("这里是上\n");
            ifmove = 1;
            /* 仿照左移操作,区别仅仅是行列互换后遍历 */
            for (int j = 0; j < 4; j++) 
            {
                
                for (int i = 3; i >= 0; i--) 
                {   
                    int k = 0;
                    if (board[i][j] == 0) 
                    {
                        continue;
                    }

                    if (i != 0)
                    {
                        k = i-1;
                    }
                    else 
                        k = 0;

                    while(board[k][j] == 0)
                    {
                        board[k][j] = board[i][j];
                        board[i][j] = 0;
                        if (k != 0)
                        {
                            k--;
                        }
                        else 
                            break;
                        
                    }
                    if (board[i][j] == 0) 
                    {
                        continue;
                    }

                    if (board[i][j] == board[k][j] && i != 0)
                    {
                        board[k][j] = 2*board[i][j];
                        board[i][j] = 0;
                    }

                    if (board[i][j] != board[k][i] && board[k][i] != 0)
                    {
                        if ((k+1) !=i)
                        {
                            board[k+1][j] = board[i][j];
                            board[i][j] = 0;
                        }
                    }

                    if (board[i][j] != board[k][i] && board[k][i] == 0)
                    {
                        board[k][i] = board[i][j];
                        board[i][j] = 0;
                    }
                }
            }
            
        }

        //向下划
        else if((*touch_y1-*touch_y)>(*touch_x-*touch_x1)&&(*touch_y1-*touch_y)>(*touch_x1-*touch_x))
        {
            // printf("这里是下\n");
            ifmove = 1;
            /* 仿照左移操作,区别仅仅是行列互换后遍历,且j和k都反向遍历 */
            for (int j = 0; j < 4; j++) 
            {
                for (int i = 0; i< 4; i++) 
                {
                    int k = 0;
                    if (board[i][j] == 0) 
                    {
                        continue;
                    }

                    if (i != 3)
                    {
                        k = i+1;
                    }
                    else
                        k = 3;
                    

                    while(board[k][j] == 0)
                    {
                        board[k][j] = board[i][j];
                        board[i][j] = 0;
                        if (k !=3)
                        {
                            k++;
                        }
                        else
                            break;
                    }
                    if (board[i][j] == 0) 
                    {
                        continue;
                    }

                    if (board[i][j] == board[k][j] && i !=3)
                    {
                        board[k][j] = 2*board[i][j];
                        board[i][j] = 0;
                    }

                    if (board[i][j] != board[k][i] && board[k][i] != 0)
                    {
                        if ((k-1) !=i)
                        {
                            board[k-1][j] = board[i][j];
                            board[i][j] = 0;
                        }
                    }

                    if (board[i][j] != board[k][i] && board[k][i] == 0)
                    {
                        board[k][i] = board[i][j];
                        board[i][j] = 0;
                    }
                }
            }
            
        }

                        if (ifmove == 1)
                        {
           
       
                            /* 这里再生成一个随机的2或者4,概率之比9:1 */
                            n = 0;
                            for (int l = 0; l < 4; ++l) 
                            {
        
                                for (int m = 0; m < 4; ++m) 
                                {
                                    if (board[l][m] == 0)
                                    {
                                        n = n+1;
                                    }          
                                }
                            }
                            srand((unsigned int) time(0));
                            n = rand() % n; /* 确定在何处空位置生成随机数 */
                            for (int l = 0; l < 4; ++l) 
                            {       
                                for (int m = 0; m < 4; ++m) 
                                {
                                    /* 定位待生成的位置 */
                                    if (board[l][m] == 0 && n-- == 0) 
                                    {
                                        board[l][m] = (rand() % 10 ? 2 : 4); /* 生成数字2或4,生成概率为9:1 */
                                    }
                                }
                            }
                        }

                        //从头开始打印
            for (int i = 0; i < 4; ++i) 
            {
                for (int j = 0; j < 4; ++j) 
                {
                    if (board[i][j] == 0)
                    {
                        showyxbmp(80,80,i,j,"num0.bmp");
                    } 

                    if (board[i][j] == 2)
                    {
                        showyxbmp(80,80,i,j,"num2.bmp");
                    }  

                    if (board[i][j] == 4)
                    {
                        showyxbmp(80,80,i,j,"num4.bmp");
                    }  
                    if (board[i][j] == 8)
                    {
                        showyxbmp(80,80,i,j,"num8.bmp");
                    } 
                    if (board[i][j] == 16)
                    {
                        showyxbmp(80,80,i,j,"num16.bmp");
                    } 
                    if (board[i][j] == 32)
                    {
                        showyxbmp(80,80,i,j,"num32.bmp");
                    } 
                    if (board[i][j] == 64)
                    {
                        showyxbmp(80,80,i,j,"num64.bmp");
                    } 
                    if (board[i][j] == 128)
                    {
                        showyxbmp(80,80,i,j,"num128.bmp");
                    } 
                    if (board[i][j] == 256)
                    {
                        showyxbmp(80,80,i,j,"num256.bmp");
                    } 
                    if (board[i][j] == 512)
                    {
                        showyxbmp(80,80,i,j,"num512.bmp");
                    }
                    if (board[i][j] == 1024)
                    {
                        showyxbmp(80,80,i,j,"num1024.bmp");
                    }
                    if (board[i][j] == 2048)
                    {
                        showyxbmp(80,80,i,j,"num2048.bmp");
                    }
                    if (board[i][j] == 4096)
                    {
                        showyxbmp(80,80,i,j,"num4096.bmp");
                    }
                    if (board[i][j] == 8192)
                    {
                        showyxbmp(80,80,i,j,"num8192.bmp");
                    } 
                }     
            }
        int ifgameover = 0;

        for (int i = 0; i < 3; i++) 
        {
            for (int j = 0; j < 4; j++) 
            {
                /* 横向和纵向比较挨着的两个元素是否相等,若有相等则游戏不结束 */
                if (board[i][j] == board[i][j + 1] || board[j][i] == board[j + 1][i]) 
                {
                    break;
                }
                else
                    ifgameover++;
            }
        }
        
        //printf("ganmeover%d\n", ifgameover);
        if (ifgameover == 11)
        {
            break;
        }

        if ((*touch_x>742) && (*touch_y<36))
        {
            break;
        }
    }
    printf("您已退出了游戏。\n");
}

int main(int argc, char const *argv[])
{
    // int *touch_x = calloc(1,1000);
    // int *touch_x1 = calloc(1,1000);
    // int *touch_y = calloc(1,1000);
    // int *touch_y1 = calloc(1,1000);
    // showbmp(800,480,"zjm.bmp");
    // // showyxbmp(80,80,2,3,"num2.bmp");
    // while(1)
    // {
    //     //打开2048小游戏
    //     yxget_x_y(touch_x,touch_x1,touch_y,touch_y1);
        //get_x_y(touch_x,touch_y);
        // if ((*touch_x>119) &&(*touch_x<199) && (*touch_y>140) && (*touch_y<217) )
        // {
            play_game();
        // }

        // if ((*touch_x>742) && (*touch_y<36))
        // {
        //     break;
        // }
    // }
    // printf("已回到主界面。\n");

    // showbmp(800,480,"zjm.bmp");
    // return 0;
}

2048 右移逻辑,先找到第一个不为空格的数a[ i ][ j ],然后用另一个数组,与a[i][j]对比各种情况;
eg:当a[i][j]与a[i][k]相等时,a【i】【k】= a【i】【j】,a【i】【j】= 0;若不相等,则a【i】【k-1】= a【i】【j】;还有各种细节,可以看代码,上下左右都是同一个逻辑。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值