基于【C语言】和【framebuffer】的五子棋游戏项目

基于【C语言】和【framebuffer】的五子棋游戏项目 文章目录前言一、项目要求及意义二、项目功能描述及效果2.1 项目功能描述2.2 项目效果展示三、项目具体实现3.1 项目流程图3.2 项目具体解决方案3.3 核心技术3.3.1 Framebuffer 显示模块3.3.2 游戏逻辑模块之数据结构设计3.3.3 游戏逻辑模块之坐标映射机制3.3.4 游戏逻辑模块之落子算法3.3.5 游戏逻辑模块之胜负判定算法四、项目总结4.1 项目收获4.2 项目中遇到的问题及解决办法4.3 项目可优化点前言在进行此项目之前我们需要涉及到C语言相关的知识以及linux系统的基本知识和framebuffer帧缓存技术此项目旨在对C语言知识的巩固以及对模块化编程思想的加深所以按时不需要考虑framebuffer技术后文会直接提供。以下三篇文章是对C语言和linux基本知识的总结从0基础开始到熟练掌握C语言Linux入门指南linux系统中项目工程中的多文件管理makefile一、项目要求及意义要求编写C语言程序通过Linux系统的伪终端构建五子棋棋盘和落子位置等相关内容。意义通过实现五子棋游戏掌握 Linux 系统编程、内存映射了解底层图形渲染的核心方法以经典益智游戏为载体练习模块化代码设计、游戏逻辑实现与边界问题处理。二、项目功能描述及效果2.1 项目功能描述功能总览在Linux环境下、基于帧缓冲驱动的双人对战五子棋游戏完整覆盖从界面显示到对局逻辑的全流程。详细功能说明(1)界面显示功能支持黑白棋子绘制、红色选择光标显示。对局结束自动弹出胜负结果提示图支持BMP背景图加载绘制木色棋盘与20x20标准网。(2)操作交互功能键盘w/a/s/d控制光标上下左右移动选择落子位置;空格键执行落子黑白双方自动交替落子。r键实现单步悔棋回退上一步落子状态。(3)游戏规则功能自动拦截重复落子仅允许在空位落子实时胜负判定横、竖、斜向连成五子即判胜右侧提示区显示当前轮到哪一方落子。2.2 项目效果展示五子棋项目实现效果视频三、项目具体实现3.1 项目流程图此为五子棋项目的流程图3.2 项目具体解决方案在Linux环境下、基于帧缓冲驱动的双人对战五子棋游戏完整覆盖从界面显示到对局逻辑的全流程。3.3 核心技术3.3.1 Framebuffer 显示模块基础绘图函数封装通过draw_point()像素点绘制封装水平线、竖直线、矩形、实心圆、斜线、全屏清屏函数。以下代码为直接提供的framebuffer相关的代码我们直接使用暂时不做了解freebuffer.h#ifndef__FRAMEBUFFER_H__#define__FRAMEBUFFER_H__#defineRGB_FMT_88832#defineRGB_FMT_56516#defineRED0x00FF0000#defineGREEN0x0000FF00#defineBLUE0x000000FF#defineBLACK0x00000000#defineWHITE0x00FFFFFF#defineYELLOW0x00FFFF00#defineMUZHI0x00DEB887//#define WORD_D 5//#define SUM_D d1d2d3d4d5d6////当前显示设备可视化界面的分辨率externintfbx_g;//800 横向分辨率externintfby_g;//600 纵向分辨率//初始化显示设备:/dev/fb0externintinit_fb(char*devname);//绘制一个像素点//x 横向坐标//y 纵向坐标//col RGB888颜色值externvoiddraw_point(intx,inty,unsignedintcol);externvoiddraw_h_line(intx,inty,intlen,unsignedintcol);externvoiddraw_clean(unsignedintcol);externvoiddraw_s_line(intx,inty,intlen,unsignedintcol);externvoiddraw_rect(intx,inty,inth,intk,unsignedintcol);externvoiddraw_circle(intx0,inty0,intr,unsignedintcol);externvoiddraw_zxie_line(intx,inty,intsize,unsignedintcol);externvoiddraw_yxie_line(intx,inty,intsize,unsignedintcol);//extern void draw_win(int x, int y , int size, int thick, int col);externvoiddraw_bmp(intx,inty,char*bmpname);#endiffreebuffer.c#includestdio.h#includesys/types.h#includesys/stat.h#includefcntl.h#includeunistd.h#includestdlib.h#includesys/ioctl.h#includelinux/fb.h#includesys/mman.h#includemath.h#includeframebuffer.hvoid*pmemNULL;intfb;structfb_var_screeninfovinfo;intfbx_g0;intfby_g0;intinit_fb(char*devname){//1. 打开显示设备(/dev/fb0)fbopen(devname,O_RDWR);if(-1fb){perror(open fb error);return-1;}//2. 获取显示设备相关参数分辨率像素格式intretioctl(fb,FBIOGET_VSCREENINFO,vinfo);if(ret0){perror(ioctl error);return-1;}printf(xres %d, yres %d\n,vinfo.xres,vinfo.yres);// printf(xres_virtual %d, yres_virtual %d\n, vinfo.xres_virtual, vinfo.yres_virtual);printf(bits_per_pixel %d\n,vinfo.bits_per_pixel);fbx_gvinfo.xres;fby_gvinfo.yres;//3. 建立显存空间和用户空间的内存映射size_tlenvinfo.xres_virtual*vinfo.yres_virtual*vinfo.bits_per_pixel/8;pmemmmap(NULL,len,PROT_READ|PROT_WRITE,MAP_SHARED,fb,0);if(pmemMAP_FAILED){perror(mmap error);return-1;}return0;}voiddraw_point(intx,inty,unsignedintcol){if(xvinfo.xres||yvinfo.yres){return;}if(vinfo.bits_per_pixelRGB_FMT_888){unsignedint*ppmem;*(pvinfo.xres_virtual*yx)col;}elseif(vinfo.bits_per_pixelRGB_FMT_565){unsignedshort*ppmem;*(pvinfo.xres_virtual*yx)col;}}借助点绘制我们便可以自己实现水平线、竖直线、矩形、实心圆、斜线、全屏清屏voiddraw_h_line(intx,inty,intlen,unsignedintcol){for(intix;ixlen;i){draw_point(i,y,col);}}voiddraw_clean(unsignedintcol){for(inti0;ifby_g;i){draw_h_line(0,i,fbx_g,col);}}voiddraw_s_line(intx,inty,intlen,unsignedintcol){for(intiy;iylen;i){draw_point(x,i,col);}}voiddraw_rect(intx,inty,inth,intk,unsignedintcol){for(intiy;iyk;i){for(intjx;jxk;j){draw_point(j,i,col);}}}voiddraw_circle(intx0,inty0,intr,unsignedintcol){intx0;inty0;for(intr00;r0r;r0){for(doublesi0;si360;si1){xx0r0*cos(2*3.1415926/360*si);yy0r0*sin(2*3.1415926/360*si);draw_point(x,y,col);}}}voiddraw_zxie_line(intx,inty,intsize,unsignedintcol){for(inti0;isize;i){draw_point(xi,y2*i,col);}}voiddraw_yxie_line(intx,inty,intsize,unsignedintcol){for(inti0;isize;i){draw_point(x-i,y2*i,col);}}BMP 图片解析绘制此函数直接提供会用即可我们暂时不做了解。/********************************************* *draw_bmp 绘制bmp格式的图片 *参数 * x : 图像显示的起始横坐标 * y 图像显示的起始从坐标 * bmpname bmp图片的名称 * *********************************************/voiddraw_bmp(intx,inty,char*bmpname){#pragmapack(1)//bmp文件相关信息typedefstructtagBITMAPFILEHEADER{shortbfType;// 文件类型标志intbfSize;// 文件大小单位为字节shortbfReserved1;// 保留字节shortbfReserved2;// 保留字节intbfOffBits;// 数据偏移量即实际图像数据开始的位置}Bmp_file_head_t;//bmp图像信息typedefstructtagBITMAPINFOHEADER{intbiSize;// BITMAPINFOHEADER的大小单位为字节intbiWidth;// 位图的宽度单位为像素intbiHeight;// 位图的高度单位为像素shortbiPlanes;// 目标设备的位平面数必须为1shortbiBitCount;// 每像素位数颜色深度intbiCompression;// 图像压缩类型intbiSizeImage;// 图像大小单位为字节intbiXPelsPerMeter;// 水平分辨率单位为像素/米intbiYPelsPerMeter;// 垂直分辨率单位为像素/米intbiClrUsed;// 实际使用颜色数intbiClrImportant;// 重要颜色数}Bmp_info_t;#pragmapack()Bmp_file_head_t headinfo;Bmp_info_t bmpinfo;intfdopen(bmpname,O_RDONLY);if(-1fd){perror(open bmp error);return;}read(fd,headinfo,sizeof(headinfo));read(fd,bmpinfo,sizeof(bmpinfo));unsignedchar*buffmalloc(bmpinfo.biHeight*bmpinfo.biWidth*bmpinfo.biBitCount/8);read(fd,buff,bmpinfo.biHeight*bmpinfo.biWidth*bmpinfo.biBitCount/8);close(fd);unsignedchar*pbuff;unsignedcharr,g,b;for(intjbmpinfo.biHeight-1;j0;j--){for(inti0;ibmpinfo.biWidth;i){b*p;p;g*p;p;r*p;p;unsignedintcol(r16)|(g8)|(b0);draw_point(ix,jy,col);}}free(buff);}3.3.2 游戏逻辑模块之数据结构设计因为需要记录棋盘上每个位置的状态所以定义了一个枚举类型其中有空EMPTY、白子WHITE_P、黑子BLACK_P三种状态。还定义了两个结构体用来记录光标和棋子的位置。光标结构体保存光标当前像素坐标历史记录结构体保存前两步落子位置支持悔棋回滚。二维数组record[21][21]记录每个棋盘交叉点状态空 / 黑棋 / 白棋由于我定义的是每个格子的宽度并且格子数为20所以可以落子的位置就为21×21因此定义一个21×21的数组以此来记录所有的落子位置。3.3.3 游戏逻辑模块之坐标映射机制通过格子间距通过定义这个宏来实现棋子与数组元素之间的对应关系使得数组就能表现棋盘状态方便记录棋子落子位置。3.3.4 游戏逻辑模块之落子算法在检测到空格键按下时执行落子逻辑若棋盘上当前落点为空且无上一步棋子记录则落下白棋并保存该棋子类型与坐标若上一步落下的是白棋且当前格子为空则落下黑棋同时记录黑棋状态、保存前一步白棋的位置作为倒数第二步点位若上一步落下的是黑棋且当前格子为空则落下白棋记录白棋状态、保存前一步黑棋坐标以此交替切换黑白双方轮流落子保证双人交替下棋并且只允许在空白棋盘位置落子与此同时保存前两步的落子位置以此来支撑我们的悔棋操作。3.3.5 游戏逻辑模块之胜负判定算法这里以斜线方向为例。以最后落子点为中心向横向、纵向、左斜、右斜 4 个方向双向延伸每个方向独立统计连续同色棋子数量任意方向达到 5 子即判定获胜仅检测落子点周边无需遍历整个棋盘。四、项目总结4.1 项目收获初步了解了Linux Framebuffer在绘制元素点的基础上掌握了基础图形绘制等底层图形编程技能提升了模块化代码设计能力巩固了分层封装、数据结构与业务逻辑分离的开发思路积累了嵌入式环境下轻量级图形界面的开发与调试经验4.2 项目中遇到的问题及解决办法悔棋功能状态回滚异常增加二级历史记录结构体保存最近两步的落子位置与棋子类型实现状态完整回退在边界的胜负判定错误问题对判断数组递加的下标进行边界判定。项目陷入一些不明问题通过在伪终端打印一个大圆定位程序结束位置从而进行代码修改4.3 项目可优化点人机对战功能增加人机对战 AI 算法实现单人模式增加对局计时、比分统计功能时间限制功能在上次落子后就开始计时限定落子时间提高游戏体验。悔棋功能完善当前悔棋仅支持返回上一步增加悔棋算法使其没有次数限制。好啦以上就是本次基于C语言基础和linux系统framebuffer技术的五子棋项目希望对各位在C语言的学习上起到一定的作业相信各位在完成之后一定也会有成就感的一起加油