要在家目录下

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;
}

最新文章

  1. Visual Studio跨平台开发Xamarin
  2. Internet网
  3. android--gradle编译龟速?offline!
  4. 02Spring_Ioc和DI介绍
  5. DOM节点关系,节点关系
  6. hdu----(4686)Arc of Dream(矩阵快速幂)
  7. UDP 打洞 原理解释
  8. 学习java 第1天
  9. WebAPI 时代
  10. sysfs分析
  11. WebForm中如何防止页面刷新,后退导致的重复提交
  12. About Wisdom
  13. 如何使用 iOS 7 的 AVSpeechSynthesizer 国家有声读物(4)
  14. 大数据系列修炼-Scala课程08
  15. css随笔属性
  16. js slice 假分页
  17. [HNOI2009]最小圈(分数规划+SPFA判负环)
  18. Javaweb拦截器
  19. html 统一资源定位器(url)和url编码
  20. Linux虚拟机安装应用程序提示Graphical installers are not supported by the vm

热门文章

  1. 大数据-业务数据采集-FlinkCDC
  2. 【数据结构与算法】希尔排序 python和c++实现
  3. 【ASP.NET Core】MVC控制器的各种自定义:IActionHttpMethodProvider 接口
  4. MassTransit 知多少 | 基于MassTransit Courier实现Saga 编排式分布式事务
  5. 获取Exceptionless的日志
  6. 从零入门项目集成Karate和Jacoco,配置测试代码覆盖率
  7. 【机器学习】李宏毅——Recurrent Neural Network(循环神经网络)
  8. JUC基础学习笔记
  9. Vue3 企业级优雅实战 - 组件库框架 - 9 实现组件库 cli - 上
  10. 【转载】EXCEL VBA 自定义排序的三种方法