要在家目录下

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. GitOps实践之kubernetes安装argocd

    1. 什么是argocd 1.Argo CD是Kubernetes的一个声明性GitOps持续交付工具. 2.应用程序定义.配置和环境应该是声明性的和版本控制的.应用程序部署和生命周期管理应自动化.可 ...

  2. Karmada多云多集群生产实践专场圆满落幕

    摘要:CNCF Karmada社区Cloud Native Days China 2022南京站成功举办. 本文分享自华为云社区<Karmada多云多集群生产实践专场圆满落幕|Cloud Nat ...

  3. java中的杨辉三角

    本文主要介绍如何打印杨辉三角(直角三角形),如下图所示: 规律如下: 第一行全为1,对角线元素全为1,设i表示行标,j表示列标. arr[i][0] = 1; arr[i][i] = 1; 当i &g ...

  4. Jmeter 模拟http发送zip文件

    发送zip文件的接口配置如下: 1.  在不知参数情况下使用fidder进行抓包操作,查看参数与MiME类型 2.  新建http取样器,并设置接口地址,进入文件上传设置参数与MIME类型 appli ...

  5. int类型bit都满了之后继续累加

    uint8_t的最大值是255,如果再加1那低8位都是0,最后结果也是0 #include<stdio.h> #define uint8_t unsigned char int main( ...

  6. Web应用怎样获取Access Token?

    1.在联盟创建服务器应用 参考文档:开发准备 2.获取用户级Access Token 2.1 获取code 参考文档:接入华为帐号获取凭证 2.1.1 先按照跳转链接进行配置url https://o ...

  7. APICloud 入门教程窗口篇

    什么是窗口,窗口可以理解为一屏幕内容的一个基本载体,里面可以放导航,图片,视频,文字等组成一屏幕内容. 不同的窗口组成一个APP, 例如购物APP有[首页],[购物车],[我的]等不同的窗口.不同的窗 ...

  8. [机器学习] Yellowbrick使用笔记1-快速入门

    Yellowbrick是一个机器学习可视化库,主要依赖于sklearn机器学习库,能够提供多种机器学习算法的可视化,主要包括特征可视化,分类可视化,回归可视化,回归可视化,聚类可视化,模型选择可视化, ...

  9. Java基础篇——垃圾收集详解

    JAVA垃圾收集 1.如何判断对象死亡 说道垃圾回收,那么首要问题就是jvm如何判断一个对象已经死亡呢 1.1 引用计数法 说白了,就是为每个对象设立一个引用计数器,每当有一个引用指向它,计数器加一, ...

  10. linux 基础之输入输出重定向

    输入输出重定向 输出重定向 正确命令 > 文件 (覆盖) 正确命令 >> 文件(追加) 错误命令 2> 文件(覆盖) 错误命令 2>>文件(追加) 命令> 文 ...