6818开发板五子棋游戏

学校安排我们去粤嵌实习,本人也是刚刚从实习回来,不过比起说是实习感觉更像是短时间的培训。以下代码是我们完成的项目其中的一个五子棋游戏,代码也是在网上搜索到后加以学习修改的,如果有什么不对的地方,还请见谅。

开发板我们使用的是粤嵌的6818开发板,因为使用的是ARM的处理器,所以将代码编写完成后我们是下载了一个Linux系统的虚拟机,在Linux系统中使用“arm-linux-gcc XXX.c -o XXX”指令生成一个能被ARM处理器读取的文件,然后再用SecureCRT下载到6818开发板中运行。

因为我们整个项目没有做文件的封装,我们将所有代码都整合在了一个文件中运行,所以库文件的调用其实并不需要调用这么多。

游戏中加入了背景音乐,需要用到madplay文件,如果没有madplay需要自行下载到/usr/bin路径下,madplay其实是一个开源的MP3播放器,对于音乐的播放暂停继续等操作可以直接使用它提供的指令。

代码中涉及到了显示屏和触碰屏的功能,这里就不继续一一讲述了,代码中也添加了许多注释,希望这些对你能有帮助。

#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <linux/input.h>
#include <linux/fb.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
#include <math.h>



int *p = NULL;  //避免野指针,造成程序崩溃。
int lcd_fd = -1;//全局声明显示屏lcd_fd
int cpp_fd = -1;//全局声明触碰屏cpp_fd
int t_x,t_y;   //触摸屏坐标
int wide, height;//图片的宽度(19~22),高度(23~26)

#define  MMAP_SIZE  800*480*4

struct input_event ts;//定义一个结构体变量 

void lcd_init()
{
	//打开lcd
	lcd_fd = open("/dev/fb0",O_RDWR);
	if(lcd_fd < 0)   //打开失败
	{
		perror("显示屏文件打开失败\n");
		return;
	}
	
	//进行内存映射
	p = mmap(NULL,800*480*4,PROT_READ | PROT_WRITE,MAP_SHARED,lcd_fd,0);
	if(p == NULL)
	{
		perror("内存映射失败\n");
		return;
	}
}


//触碰屏文件打开
void cpp_init()
{
    //打开触摸屏文件
    cpp_fd = open("/dev/input/event0",O_RDWR);
    if(cpp_fd < 0)
    {
        perror("触碰屏文件打开失败\n");
        return;
    }
}

//图标位置显示(输入坐标和图片地址,输出图片长宽,显示图片)
void show(int x0,int y0,char* path_name)  // x0,y0图片起始坐标,path_name 图片路径
{	
	//打开cpp
	int bmp_fd = open(path_name,O_RDWR);
	if(bmp_fd < 0)   //打开失败
	{
		perror("图片打开失败\n");
		return;
	}
	
	//偏移54个字节
	// lseek(bmp_fd,54,SEEK_SET);
    lseek(bmp_fd,18,SEEK_SET);
    read(bmp_fd,&wide,4);
    read(bmp_fd,&height,4);
    //printf("wide:%d height:%d\n",wide,height);

	//读取图片数据
    //偏移54个字节
	lseek(bmp_fd,54,SEEK_SET);
	char bmp_buf[wide*height*3];
	read(bmp_fd,bmp_buf,wide*height*3);
	
	int x,y,color,i=0;
	char r,g,b;
	for(y=0;y<height;y++)
	{
		for(x=0;x<wide;x++)
		{
			b = bmp_buf[i++];
			g = bmp_buf[i++];
			r = bmp_buf[i++];
			color = b | g << 8 | r << 16;
			*(p+800*(height-1-y+y0)+x+x0) = color;  
		}
	}
	close(bmp_fd);
}


//图片触碰屏功能(无输入,输出触碰屏触屏位置,运行一次可输出一次)
int cppgn()
{
    while(1)
    {
        //获取结构体成员的值
        read(cpp_fd,&ts,sizeof(ts));
        //判断是否为触摸屏事件
        if(ts.type == EV_ABS)
        {
            if(ts.code == ABS_X)   //X轴事件
            {
                //x = ts.value;  //蓝色版本
                t_x = ts.value*800/1024;  //黑色版本
            }
            if(ts.code == ABS_Y)   //Y轴事件
            {
                //y = ts.value;  //蓝色版本
                t_y = ts.value*480/600;  //黑色版本
            }
        }
        //判断是否松手
        if(ts.type == EV_KEY && ts.code == BTN_TOUCH && ts.value == 0)
        {
            printf("(x:%d,y:%d)\n",t_x,t_y);
            return 0;
        }
    }
}

int *lcd_fp=NULL;
struct fb_var_screeninfo lcd_info;
FILE *abs_screen ;

//数组棋盘
int sheet[16][16]={0};


//设置全屏背景颜色
void draw_background(int color)
{
	printf("进入全屏背景\n");
    for(int y = 0;y < 480;y++)
    {
        for(int x=0;x< 800;x++)
        {
            *(p + 800*y + x) = color;  //颜色
        }
    }
}


//画左半圆,x、y为圆心
void draw_round1(int x,int y,int n,int color)
{
    for(int i=0;i<=x;i++)
    {
        for(int j=0;j<480;j++)
        {
            int dx=x-i;
            int dy=y-j;
            if(dx*dx+dy*dy<=n*n)
            {
                 *(p + 800*j + i) = color;  //颜色
            }
        }
    }
}
//画右半圆,x、y为圆心
void draw_round2(int x,int y,int n,int color)
{
    for(int i=x;i<=800;i++)
    {
        for(int j=0;j<480;j++)
        {
            int dx=x-i;
            int dy=y-j;
            if(dx*dx+dy*dy<=n*n)
            {
                *(p + 800*j + i) = color;  //颜色
            }
        }
    }
}


//结算界面
void draw_taiji()
{    
    //设置底色为黄色
    draw_background(0xffcc00);

    //设置大圆
    draw_round1(400,240,200,0xffffff);
    draw_round2(400,240,200,0x000000);

    //设置小半圆
    draw_round1(400,140,100,0x000000);
    draw_round2(400,340,100,0xffffff);

    //设置最小圆
    draw_round1(400,140,30,0xffffff);
    draw_round2(400,140,30,0xffffff);
    draw_round1(400,340,30,0x000000);
    draw_round2(400,340,30,0x000000);
    show(0,380,"./data/back.bmp");
    show(700,0,"./data/end.bmp");
    show(650,430,"./data/paihan.bmp");
    show(0,0,"./data/again.bmp");
}


//画棋盘
void checkerboard()
{
    //竖向
    for(int i=10;i<480;i=i+30)
    {
        for(int j=10;j<460;j++)
        {
            *(p + 800*j + i) = 0x00000000;
        }
    }
    //横向
    for(int i=10;i<460;i++)
    {
        for(int j=10;j<480;j=j+30)
        {
            *(p + 800*j + i) = 0x00000000;
        }
    }
}


//排行榜
void leaderboard(int victory1,int victory2)
{
    show(0,380,"./data/huitui.bmp");
    show(0,70,"./data/num.bmp");
    int m=0,n=0;
    //循环画胜利次数个圆
    for(int i=1;i<=victory1;i++)
    {
        draw_round1(i*100,130+m,30,0x000000);
        draw_round2(i*100,130+m,30,0x000000);
        //每画7个圆y轴加40
        if(i%7==0)
        m=m+40;
    }
    for(int j=1;j<=victory2;j++)
    {
        draw_round1(j*100,330+n,30,0xE0E0E0);
        draw_round2(j*100,330+n,30,0xE0E0E0);
        if(j%7==0)
        n=n+40;
    }
}



//下子
int chess(int color1,int color2,int num)
{
    for(int i=10;i<480;i=i+30)
    {
        for(int j=10;j<480;j=j+30)
        {
            if(abs(t_x-i)<15&& abs(t_y-j)<15)
            {
                int x=i/30;
                int y=j/30;
                if(sheet[x][y]==0)
                {
                    draw_round1(i,j,10,color1);
                    draw_round2(i,j,10,color1);
                    draw_round1(600,140,30,color2);
                    draw_round2(600,140,30,color2);
                    if(color1==0x000000)
                    {
                        sheet[x][y]=1;
                        num++;
                    }
                    else if(color1==0xE0E0E0)
                    {
                        sheet[x][y]=2;
                        num++;
                    }
                }
            }
        }
    }
    return num;
}


//判断A是否连成五子
int AWin(int sum1)
{
    //遍历判断五子
    for(int i=0;i<16;i++)
    {
        for(int j=0;j<16;j++)
        {
            //当发现子时寻找周围连成线的四子判断是否相等
            if(sheet[i][j]==1)
            {
                //横
                for(int k=1;k<5;k++)
                {
                    if(sheet[i][j]!=sheet[i][j+k])
                    {
                        sum1=0;
                        break;
                    }
                    else
                    sum1=k+1;
                    if(sum1==5)
                    return sum1;
                }
                //竖
                for(int k=1;k<5;k++)
                {
                    if(sheet[i][j]!=sheet[i+k][j])
                    {
                        sum1=0;
                        break;
                    }
                    else
                    sum1=k+1;
                    if(sum1==5)
                    return sum1;
                }
                //左斜
                for(int k=1;k<5;k++)
                {
                    if(sheet[i][j]!=sheet[i-k][j+k])
                    {
                        sum1=0;
                        break;
                    }
                    else
                    sum1=k+1;
                    if(sum1==5)
                    return sum1;
                }
                //右斜
                for(int k=1;k<5;k++)
                {
                    if(sheet[i][j]!=sheet[i+k][j+k])
                    {
                        sum1=0;
                        break;
                    }
                    else
                    sum1=k+1;
                    if(sum1==5)
                    return sum1;
                }
            }
        }
    }   
    return sum1;
}

//判断B是否连成五子
int BWin(int sum2)
{
    //遍历判断五子
    for(int i=0;i<16;i++)
    {
        for(int j=0;j<16;j++)
        {
            //当发现子时寻找周围连成线的四子判断是否相等
            if(sheet[i][j]==2)
            {
                //横
                for(int k=1;k<5;k++)
                {
                    if(sheet[i][j]!=sheet[i][j+k])
                    {
                        sum2=0;
                        break;
                    }
                    else
                    sum2=k+1;
                    if(sum2==5)
                    return sum2;
                }
                //竖
                for(int k=1;k<5;k++)
                {
                    if(sheet[i][j]!=sheet[i+k][j])
                    {
                        sum2=0;
                        break;
                    }
                    else
                    sum2=k+1;
                    if(sum2==5)
                    return sum2;
                }
                //左斜
                for(int k=1;k<5;k++)
                {
                    if(sheet[i][j]!=sheet[i-k][j+k])
                    {
                        sum2=0;
                        break;
                    }
                    else
                    sum2=k+1;
                    if(sum2==5)
                    return sum2;
                }
                //右斜
                for(int k=1;k<5;k++)
                {
                    if(sheet[i][j]!=sheet[i+k][j+k])
                    {
                        sum2=0;
                        break;
                    }
                    else
                    sum2=k+1;
                    if(sum2==5)
                    return sum2;
                }
            }
        }
    }   
    return sum2;
}

//数组重新置为空
void chess_again()
{
    for(int i=0;i<16;i++)
    {
        for(int j=0;j<16;j++)
            sheet[i][j]=0;
    }
    
}

//五子棋游戏驱动
int dakai()
{
	printf("游戏运行\n");

	//播放背景音乐
	system("madplay bgm.mp3 -r &");
	
    //读取胜利次数
    int victory1 = 0;
    int victory2 = 0;
	
    nothing:
    //主界面
    show(0,0,"./data/start.bmp");
	show(0 ,0 ,"fanhuianjian.bmp");
    while (1)
    {
		if(cppgn() == 0)
        {
			if(t_x>266 && t_y>360 &&t_x<532 &&t_y<480)//开始游戏
			{			
				
		 		again:
			    //画出棋盘和相关按钮
			    draw_background(0xffffff);
			    show(0,0,"./data/checkerboard.bmp");
			    show(500,0,"./data/what.bmp");
			    show(700,380,"./data/huitui.bmp");
			    show(480,400,"./data/gameagain.bmp");
			    show(720,0,"./data/surrender.bmp");
			    checkerboard();
					
		        //黑棋先下
		        draw_round1(600,140,30,0x000000);
		        draw_round2(600,140,30,0x000000);
		        int num=0;//记录下子数
		        int sum1=0,sum2=0;//记录连子数
		        while (cppgn() == 0)
				{ 
		            //返回主界面
		            if(t_x<800 && t_y>380 &&t_x>700 &&t_y<480)
		            {              
						chess_again();
		                goto nothing;
		            }
		            //重开
		            else if(t_x<560 && t_y>380 &&t_x>480 &&t_y<480)
		            {
		                chess_again();
		                goto again;
		            }
					//投降
		            else if(t_x<800 && t_y>0 &&t_x>720 &&t_y<80)
		            {
		                //判断谁投降,另一个胜利
		                if(num%2==0)
						{
		                    draw_taiji();   
		                    show(50,120,"./data/bai.bmp");
		                    victory2++;
		                    break; 
		                }
		                else if (num%2==1)
	                    {
							draw_taiji();
		                    show(650,120,"./data/hei.bmp");
		                    victory1++;
		                    break;
		                }
		            }
		            //循环交替下子
		            else
		            {
		                if(num%2==0)
		                {
							num=chess(0x000000,0xE0E0E0,num);
		                    sum1=AWin(sum1);
		                    //连子数为5,胜利,退出循环
		                    if(sum1==5)
		                    {
		                        draw_taiji();
		                        show(650,120,"./data/hei.bmp");
		                        victory1++;
		                        break;
		                    }
		                }
		                else if(num%2==1)
		                {
		                    num=chess(0xE0E0E0,0x000000,num);
		                    sum2=BWin(sum2);
		                    if(sum2==5)
		                    {
								draw_taiji();   
		                        show(50,120,"./data/bai.bmp");
		                        victory2++;
		                        break;             
		                    }
		                }
		            }
				}

		        //清空数组,棋盘清理
		        chess_again();
					
		        click_one:
		        //返回主界面
		        if(cppgn() == 0)
   			    {
			        if(t_x<150 && t_y>380 &&t_x>0 &&t_y<480)
			        {
		    	        goto nothing;
			        }
			        //退出游戏  
			        else if(t_x<800 && t_y>0 &&t_x>700 &&t_y<100)
		 		    {
			            goto tuichu;
			        }
			        //重开
			        else if(t_x<100 && t_y>0 &&t_x>0 &t_y<100)
			        {
			            //返回棋盘位置
			            goto again;
			        }
			        //排行榜
			        else if(t_x<800 && t_y>400 &&t_x>600 &&t_y<480)
			        {
		    	    	//画出排行榜界面
			            draw_background(0xffffff);
			            show(300,0,"./data/ban.bmp");
						show(760,0,"./data/backstart.bmp");
			            //画出每个人的胜利次数
			            leaderboard(victory1,victory2);
							
			            click_two:
			            if(cppgn() == 0)
			            {
			                //重开
			                if(t_x<100 && t_y>380 &&t_x>0 &&t_y<480)
			               		goto again;
			                //返回主界面
			                else if(t_x<800 && t_y>0 &&t_x>700 &&t_y<70)
			           	    	goto nothing;                   
							//点击其他区域重新获取点击
			                else
			                	goto click_two;
			            }
			        }
			        else
			        {
			            //点击其他区域再次获取点击
			            goto click_one;
		            }
				}
			}
			else if(t_x >= 0 && t_x <= 100 + 0 & t_y >= 0 && t_y <= 100 + 0)
			{
				tuichu:
				system("killall -SIGKILL madplay");
				return 0;	
			}
   		}
	}
}

int main()
{
    dakai();
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值