要在家目录下

makefile

  1 main : main.o fun.o input.o fb_draw.o
2 gcc -Wall -o $@ $^
3 clean :
4 rm -rf *.o main

fb_draw.h

#ifndef __FB_DRAW_H
#define __FB_DRAW_H int fb_open(void);
void fb_close(void);
void fb_draw_point(int x, int y, unsigned int color); int xres(void);
int yres(void); #endif

fun.h

#ifndef __INPUT_H
#define __INPUT_H #define KEYBOARDMODE 0
#define CHARMODE 1 void input_init(void); int input_choice_mode(int mode); int input_kb_mode(void); int input_char_mode(void); void input_recover(void); #endif

inc.h

#ifndef __INC_H
#define __INC_H #include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/fb.h>
#include <linux/input.h>
#include <unistd.h>
#include <sys/mman.h>
#include <string.h>
#include <termios.h>
#include "input.h"
#include "fb_draw.h" #endif

input.h

#ifndef __INPUT_H
#define __INPUT_H #define KEYBOARDMODE 0
#define CHARMODE 1 void input_init(void); int input_choice_mode(int mode); int input_kb_mode(void); int input_char_mode(void); void input_recover(void); #endif

fb_draw.c

#include "include/inc.h"

/***********************************************
结构体中保存了有关操作framebuffer设备所需的成员
fix : 本地的fb数据
var : 可变的fb数据
bpp : 一个像素点所占位数
fd : 保存fb文件的文件描述符
fbp : 获取映射空间地址
fbpi: 获取映射空间地址
************************************************/
struct
{
struct fb_fix_screeninfo fix;//本地fb数据
struct fb_var_screeninfo var;//可变fb数据
unsigned int bpp;//一个像素点所占位数
int fd;//保存fb文件的文件描述符
unsigned char *fbp;//获取映射空间地址
unsigned int *fbpi;//获取映射空间地址
}fb_st; /***********************************************
int fb_open(void);
功 能 : 把fb文件打开,通过ioctl控制fb设备
通过mmap映射fb文件
返回值 : 无
参 数 : 成功返回0, 失败返回-1
************************************************/
int fb_open(void)
{
int ret; fb_st.fd = open("/dev/fb0", O_RDWR);
if(-1 == fb_st.fd)
{
perror("open");
goto error;
} /* get fb_var_screeninfo */
ret = ioctl(fb_st.fd, FBIOGET_VSCREENINFO, &fb_st.var);
if(-1 == ret)
{
perror("ioctl(fb_st.var)");
goto close_fd;
} fb_st.bpp = fb_st.var.bits_per_pixel >> 3; /* get fb_fix_screeninfo */
ret = ioctl(fb_st.fd, FBIOGET_FSCREENINFO, &fb_st.fix);
if(-1 == ret)
{
perror("ioctl(fb_st.fix)");
goto close_fd;
} /* get framebuffer start address */
fb_st.fbp = mmap(0, fb_st.fix.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fb_st.fd, 0);
if((void *)-1 == fb_st.fbp)
{
perror("mmap");
goto close_fd;
} return 0; close_fd:
close(fb_st.fd);
error:
return -1;
} /***********************************************
void fb_close();
功 能 : 解除设备文件的映射,关闭文件
返回值 : 无
参 数 : 无
************************************************/
void fb_close()
{
munmap(fb_st.fbp, fb_st.fix.smem_len);
close(fb_st.fd);
} /***********************************************
void fb_draw_point(int x, int y, int color);
功 能 : 通过framebuff画点
返回值 : 无
参 数 : x 横坐标
y 纵坐标
color 要显示的颜色(现只支持白色0xFF 黑色0x00)
************************************************/
void fb_draw_point(int x, int y, unsigned int color)
{
unsigned long offset; offset = fb_st.bpp * x + y * fb_st.fix.line_length;
//memset(fb_st.fbp + offset, color, fb_st.bpp);
fb_st.fbpi = (unsigned int *)(fb_st.fbp + offset);
*(fb_st.fbpi) = color;
} /***********************************************
int xres(void);
功 能 : 获取x轴坐标
返回值 : 获取到的x轴坐标
参 数 : 无
************************************************/
int xres(void)
{
return fb_st.var.xres;
} /***********************************************
int yres(void);
功 能 : 获取y轴坐标
返回值 : 获取到的y轴坐标
参 数 : 无
************************************************/
int yres(void)
{
return fb_st.var.yres;
}

input.c

#include "include/inc.h"

/***********************************************
结构体中保存了有关键盘操作或者终端设置的一些成员
old : 保存原始终端信息
new : 改变之后的终端信息
kb_fd : 保存键盘设备的设备号
ev : 保存输入设备的信息数据
************************************************/
struct
{
struct termios old;
struct termios new;
int kb_fd;
struct input_event ev;
}input_st; /***********************************************
void input_init(void);
功 能 : 用来在接收输入值之前设置终端
返回值 : 无
参 数 : 无
************************************************/
void input_init(void)
{
tcgetattr(0, &input_st.old);
input_st.new = input_st.old;
input_st.new.c_lflag &= ~ICANON;
input_st.new.c_lflag &= ~ECHO;
tcsetattr(0, TCSANOW, &input_st.new);
} /***********************************************
char *mystrcpy(char *dest, const char *src);
功 能 : 用来拷贝字符串,碰到尾0或者空格停止
返回值 : 指向dest的指针
参 数 : dest 拷贝的目标,dest指向拷贝的空间
src 拷贝的源,指向要拷贝的字符串
************************************************/
char *mystrcpy(char *dest, const char *src)
{
int i = 0; for(i = 0; src[i] != '\0' && src[i] != ' '; i++)
dest[i] = src[i];
dest[i] = '\0'; return dest;
} /***********************************************
void input_find_dev_file(char *buf_ev);
功 能 : 用来读取当前用户识别的键盘文件
返回值 : 无
参 数 : buf_ev 保存获取到的键盘设备文件名
************************************************/
void input_find_dev_file(char *buf_ev)
{
FILE *fp = NULL;
char buf[128] = {0};
char *find_kb = "keyboard";
char *find_ev = "event";
char *p = NULL; fp = fopen("/proc/bus/input/devices", "r"); while((fgets(buf, sizeof(buf) - 1, fp)) != NULL)
{
p = strstr(buf, find_kb);
if(p == NULL)
continue;
else
{
while((fgets(buf, sizeof(buf) - 1, fp)) != NULL)
{
p = strstr(buf, find_ev);
if(p == NULL)
continue;
else
{
mystrcpy(buf_ev, p);
break;
}
}
break;
}
} fclose(fp);
} /***********************************************
int input_choice_mode(int mode);
功 能 : 用来选择接收输入源的模式
返回值 : 0 代表使用键盘模式
1 代表使用字符模式
-1 代表选择模式失败
参 数 : KEYBOARDMODE 键盘模式
CHARMODE 字符模式
************************************************/
int input_choice_mode(int mode)
{
char dest[64] = "/dev/input/";
char buf[8] = {0};
switch(mode)
{
case KEYBOARDMODE :
input_find_dev_file(buf);
strcat(dest, buf);
input_st.kb_fd = open(dest, O_RDONLY);
if(input_st.kb_fd < 0)
{
perror("open()");
return -1;
}
break;
case CHARMODE : break;
default : return -1;
}
return mode;
} /***********************************************
int input_kb_mode(void);
功 能 : 获取键盘的键值,并返回
返回值 : 为了使用方便,返回[103上]
返回[108下], 返回[105左]
返回[106右], 返回[14落子]
返回[16quit]
参 数 : 无
************************************************/
int input_kb_mode(void)
{
read(input_st.kb_fd, &input_st.ev, sizeof(input_st.ev));
if(input_st.ev.type == EV_KEY)
if(input_st.ev.value == SYN_REPORT)
{
if(input_st.ev.code == 16)
{
tcsetattr(0, TCSANOW, &input_st.old);
close(input_st.kb_fd);
}
return input_st.ev.code;
}
return 0;
} /***********************************************
int input_char_mode(void);
功 能 : 获取键盘字符,并返回
返回值 : 为了使用方便,返回[w上]
返回[s下], 返回[a左]
返回[d右], 返回[' ']
返回[qquit]
请自行处理大小写
参 数 : 无
************************************************/
int input_char_mode(void)
{
int val = 0; val = getchar();
if(val == 'q' || val == 'Q')
tcsetattr(0, TCSANOW, &input_st.old);
return val;
} /***********************************************
void input_recover(void);
功 能 : 用来恢复设置终端
返回值 : 无
参 数 : 无
************************************************/
void input_recover(void)
{
tcsetattr(0, TCSANOW, &input_st.old);
}

fun.c

#include <stdio.h>
#include <stdlib.h>
#include "include/inc.h"
#include "include/fun.h" int color = 0x000000; //棋盘线颜色 黑色
int back_color = 0xFFFFFF; //棋盘背景颜色 白色
int play1_color = 0xCC9966;//0x00BFFF; //玩家1棋子颜色
int play2_color = 0x000000;//0xFFBBFF; //玩家2棋子颜色 struct cir c = {0, 0, 20, 0x00BFFF}; int ifset(int (*arr)[17], int *x, int *y)
{
if((*x) > 16)
*x = 0;
if((*x) < 0)
*x = 16;
if((*y) > 16)
*y = 0;
if((*y) < 0)
*y = 16;
if(arr[(*x)][(*y)] == 1 || arr[(*x)][(*y)] == 2)
return 1;
return 0;
} void draw_circle(int x, int y, int r, int color)
{
int x0, y0; for(x0 = x - r; x0 <= x + r; x0++)
{
for(y0 = y - r; y0 <= y + r; y0++)
{
if((x0 - x) * (x0 - x) + (y0 - y) * (y0 - y) <= r * r)
fb_draw_point(x0, y0, color);
}
}
} int is_win(int arr[][17], int x, int y, int mode)
{
int i = 0, j = 0, sum = 0; for(i = x; i < x + 5 && i <= 16; i++) //判断横向能否赢
{
if(arr[i+1][y] == mode)
sum++;
else
break;
}
for(i = x; i > x - 5 && i >= 0; i--)
{
if(arr[i-1][y] == mode)
sum++;
else
break; }
if(sum >= 4)
return 1;
else
sum = 0; for(i = y; i < y + 5 && i <= 16; i++) //判断纵向能否赢
{
if(arr[x][i+1] == mode)
sum++;
else
break;
}
for(i = y; i >= y - 5 && i >= 0; i--)
{
if(arr[x][i-1] == mode)
sum++;
else
break;
}
if(sum >= 4)
return 1;
else
sum = 0; j = y;
for(i = x; i < x + 5 && i <= 16; i++) //判断撇能否赢
{
if(arr[i+1][j-1] == mode)
sum++;
else
break;
j--;
}
j = y;
for(i = x; i > x - 5 && i >= 0; i--)
{
if(arr[i-1][j+1] == mode)
sum++;
else
break;
j++;
}
if(sum >= 4)
return 1;
else
sum = 0; j = y;
for(i = x; i < x + 5 && i <= 16; i++) //判断捺能否赢
{
if(arr[i+1][j+1] == mode)
sum++;
else
break;
}
j = y;
for(i = x; i > x - 5 && i >= 0; i--)
{
if(arr[i-1][j-1] == mode)
sum++;
else
break;
j--;
}
if(sum >= 4)
return 1; return 0;
} void print() //打印棋盘
{
int i = 0, j = 0; for(i = 510; i <= 1410; i++) //打印棋盘背景颜色
{
for(j = 90; j <= 990; j++)
fb_draw_point(i, j, back_color);
} for(i = 530; i <= 1390; i++) //打印棋盘外边框 上
{
for(j = 110; j <= 113; j++)
fb_draw_point(i, j, color);
} for(i = 530; i <= 1390; i++) //打印棋盘外边框 下
{
for(j = 970; j <= 973; j++)
fb_draw_point(i, j, color);
} for(i = 530; i <= 533; i++) //打印棋盘外边框 左
{
for(j = 110; j <= 970; j++)
fb_draw_point(i, j, color);
} for(i = 1390; i >= 1385; i--) //打印棋盘外边框 右
{
for(j = 112; j <= 970; j++)
fb_draw_point(i, j, color);
}
} void print_line()
{
int i = 0, j = 0; for(i = 560; i <= 1360; i++) //打印棋盘线条
{
for(j = 140; j <= 940; j += 50)
fb_draw_point(i, j, color);
} for(i = 560; i <= 1360; i += 50)
{
for(j = 140; j <= 940; j++)
fb_draw_point(i, j, color);
}
} void print_intime(int (*xy_point)[17], struct cir q)
{
int i = 0, j = 0, c = 0, d = 0, x = 0, y = 0; for(i = 560, x = 0; i <= 1360; i += 50, x++)
{
for(j = 140, y = 0; j <= 940; j += 50, y++)
{
if(xy_point[x][y] == 1)
draw_circle(i, j, q.r, play1_color);
else if(xy_point[x][y] == 2)
draw_circle(i, j, q.r, play2_color);
else if(xy_point[x][y] == 0)
{
draw_circle(i, j, q.r, back_color);
for(c = i + 20, d = j; c >= i - 20; c--)
{
if(c < 560 || c > 1360)
continue;
fb_draw_point(c, d, color);
}
for(d = j + 20, c = i; d >= j - 20; d--)
{
if(d < 140 || d > 940)
continue;
fb_draw_point(c, d, color);
}
}
}
}
} void _set(int *x, int *y)
{
(*x)++;
if((*x) == 17)
{
(*x) = 0;
(*y)++;
if((*y) == 17)
(*y) = 0;
} } int play(int (*xy_point)[17], int mode)
{
int ret = 0, flag = 0, val = 0, tmpx = 0, tmpy = 0; flag = input_choice_mode(CHARMODE); c.x = 0; c.y = 0;
while(ifset(xy_point, &c.x, &c.y))
_set(&c.x, &c.y);
xy_point[c.x][c.y] = mode;
print_intime(xy_point, c);
LEAP:
if(flag == 0)
{
val = input_kb_mode();
switch(val)
{
case 103 : tmpy = c.y;
tmpx = c.x;
c.y--;
while(ifset(xy_point, &c.x, &c.y))
_set(&c.x, &c.y);
xy_point[tmpx][tmpy] = 0;
break;
case 108 : tmpy = c.y;
tmpx = c.x;
c.y++;
while(ifset(xy_point, &c.x, &c.y))
_set(&c.x, &c.y);
xy_point[tmpx][tmpy] = 0;
break;
case 105 : tmpx = c.x;
tmpy = c.y;
c.x--;
while(ifset(xy_point, &c.x, &c.y))
_set(&c.x, &c.y);
xy_point[tmpx][tmpy] = 0;
break;
case 106 : tmpx = c.x;
tmpy = c.y;
c.x++;
while(ifset(xy_point, &c.x, &c.y))
_set(&c.x, &c.y);
xy_point[tmpx][tmpy] = 0;
break;
case 14 : ret = 1;
break;
case 16 : exit(0) ;
}
}
else if(flag == 1)
{
val = input_char_mode();
switch(val)
{
case 'W' :
case 'w' : tmpx = c.x;
tmpy = c.y;
c.y--;
while(ifset(xy_point, &c.x, &c.y))
_set(&c.x, &c.y);
xy_point[tmpx][tmpy] = 0;
break;
case 'S' :
case 's' : tmpx = c.x;
tmpy = c.y;
c.y++;
while(ifset(xy_point, &c.x, &c.y))
_set(&c.x, &c.y);
xy_point[tmpx][tmpy] = 0;
break;
case 'A' :
case 'a' : tmpx = c.x;
tmpy = c.y;
c.x--;
while(ifset(xy_point, &c.x, &c.y))
_set(&c.x, &c.y);
xy_point[tmpx][tmpy] = 0;
break;
case 'D' :
case 'd' : tmpx = c.x;
tmpy = c.y;
c.x++;
while(ifset(xy_point, &c.x, &c.y))
_set(&c.x, &c.y);
xy_point[tmpx][tmpy] = 0;
break;
case ' ' : ret = 1; break;
case 'q' : exit(0) ;
}
}
xy_point[c.x][c.y] = mode;
print_intime(xy_point, c);
if(ret != 1)
goto LEAP;
if(is_win(xy_point, c.x, c.y, mode))
return mode;
return 0;
}

main.c

#include <stdio.h>
#include "include/fun.h"
#include "include/inc.h" int main(void)
{
int i = 0, j = 0; //循环变量
int xy_point[17][17] = {0}; //保存棋盘坐标
int ret = 0; //接收函数返回值 fb_open();
xres();
yres();
input_init(); print(); //打印棋盘边框和背景
print_line(); //打印棋盘 while(1)
{
ret = play(xy_point, 1); //玩家1下棋
if(ret < 0)
break;
else if(ret == 1)
{
printf("play1 win\n");
break;
} ret = play(xy_point, 2); //玩家2下棋
if(ret < 0)
break;
else if(ret == 2)
{
printf("play2 win\n");
break;
}
} input_recover();
fb_close(); return 0;
}

五子棋 framebuffer版的更多相关文章

  1. 五子棋Web版的开发(一)---搭建IDEA SSH环境

    最近公司都没啥事,我在完成了控制台版的本地五子棋后(github地址:https://github.com/lkq51/wuziqi_console2),想将他升级成为一个web版的五子棋游戏.因为公 ...

  2. 五子棋C++版

    当前只完成了单机人人对战  后续会完成联机和AI的实现 定义棋盘 typedef struct { int kind; }Map; //棋盘 0为无子 1为黑子 2为白子 Map maps[line_ ...

  3. JavaScript五子棋第二版

      这是博主做的一个移动端五子棋小游戏,请使用手机体验.由于希望能有迭代开发的感觉,所以暂时只支持双人对战且无其他提示及对战界面,只有胜利提示,悔棋.对战双方显示.人机对战.集成TS(用于学习).和局 ...

  4. 五子棋Web版的开发(三)

    最近在这个上面花费的时间不多,进展不大,而且遇到了一个问题好久也没有解决..我将struct2 改为Spring MVC.但是ziRUL的自动映射却无法起作用.   一直不知道为什么会出现这个问题.. ...

  5. 五子棋Web版的开发(二)--整合Spring4.3+hibernate4+Struts2.3

    拖了这么久才把ssh框架给整合完毕,期间发现自己对SSH的知识真的是知之甚少.在整合期间遇到了无数的坑,我还是先把项目地址发一下吧 首先我遇到的第一个问题是 CreateQuery is not va ...

  6. 五子棋——C++

    最近在学C++,这个是照葫芦画瓢的五子棋C++版- - 依赖SDL_PingGe_1.3,很多实用的函数,类我都封装成DLL了调用起来真是舒服啊.. 不过一方面要对DLL做测试,一方面要开发,一个人还 ...

  7. JAVA小项目之五子棋

    五子棋V1.0 功能: 人人对战,人机对战(初级) 记录双方分数: 主要知识点: 二维坐标系中,各方向坐标的关系及规律. 效果图: 主框架类: package com.gxlee.wzq; /** * ...

  8. 五子棋的斜对角方向上的规则 -- java编程(简单粗暴版)

    五子棋判断输赢规则 --- 斜对角线方向上 一.左上右下方向上 1.分析图 2.代码 /**判断左上右下方向上是否有连续五颗相同颜色的棋子 * 全部遍历法 */ int loop = 0; boole ...

  9. Javascript版五子棋

    Javascript版五子棋,无禁手.欢迎提出算法的改进意见.2. [代码]HTML     <!DOCTYPE html><html>    <head>    ...

  10. Web版简易五子棋

    前些时候把大三写的C++版五子棋改成Web板挂到了网上,具有一定傻瓜式智能,欢迎体验使用拍砖:http://www.zhentiyuan.com/Games/QuickFiveChess.aspx 现 ...

随机推荐

  1. 教你铁威马NAS中如何进行阵列升级

    磁盘阵列 (RAID) 是磁盘阵列的管理工具.当TNAS 中安装的硬盘多于1个时,组建适当的磁盘阵列能提高硬盘的存储效率,提高数据的安全性. 磁盘阵列升级,比如,将原来是RAID 0 或者RAID 1 ...

  2. 手写promise解决回调地狱问题

    在介绍promise之前我们先来看一段代码: 根据案例我们可以看出,这段代码可以无限的嵌套下去,但是每嵌套一层,代码的运行就会降低,而解决回调地狱最好的办法就是new promise 一.什么是 pr ...

  3. [R语言] 基于R语言实现树形图的绘制

    树状图(或树形图)是一种网络结构.它由一个根节点组成,根节点产生由边或分支连接的多个节点.层次结构的最后一个节点称为叶.本文主要基于R语言实现树形图的绘制.关于python实现树形图的绘制见:基于ma ...

  4. 前菜--Numpy

    import numpy as np NumPy : numberial python NumPy的核心:数据结构 ndarray 1.1 数组方法 np.array 创建数组 基本语法:np.arr ...

  5. Go语言的template

    html/template包实现了数据驱动的模板,用于生成可防止代码注入的安全的HTML内容.它提供了和 text/template包相同的接口,Go语言中输出HTML的场景都应使用html/temp ...

  6. Objects非空判断-声明异常throws

    Objects非空判断 还记得我们学习过一个类Objects吗,曾经提到过它由一些静态的实用方法组成,这些方法是null-save(空指针安全的)或null-tolerant (容忍空指针的),那么在 ...

  7. Unity屏幕永远保持为固定分辨率

    Unity屏幕永远保持为固定分辨率 Unity屏幕永远保持为固定分辨率 前言 开题废话 Unity版本 正题: 打开一场景 创建脚本并且编写 挂在脚本到场景摄像机上边 以不同比的分辨率运行程序,并且观 ...

  8. 我们从 CircleCI 安全事件获得的3个经验教训

    CircleCI 作为业内最受欢迎的 CI/CD 平台提供商之一,有超过20万个 DevOps 团队使用其平台.该公司在今年1月在其官网报告了一起安全事件引起客户恐慌.在此事件中,有身份不明的恶意攻击 ...

  9. Sqoop导出ClickHouse数据到Hive

    背景 公司采购了外部服务,其存储为ClickHouse,按照公司要求需要将其数据采集到Hive. 验证环境 CDH: 6.3.2 ClickHouse: 19.15.4.10 Sqoop: 1.4.7 ...

  10. 手把手教你将Eureka升级Nacos注册中心

    由于原有SpringCloud体系版本比较老,最初的注册中心使用的Eureka后期官方无升级方案,配置中心无法在线管理配置,还有实时上下线的问题,因此需要将原有系统的Eureka服务升级Nacos注册 ...