引言  -  getch简述

  引用老的TC版本getch说明. (文章介绍点有点窄,  应用点都是一些恐龙游戏时代的开发细节)

#include <conio.h>

/*
* 立即从客户端得到输入的字符. 出错返回EOF
*/
int __cdecl getch(void);

记得三年之前看过一本书 <<C专家编程>> 有一章提到在立即从标准输入中得到输入字符(后面还介绍了一种linux实现, 对于现在linux版本不行了).

那位作者评价就是, 由于linux对于''getch''支持的不友好, 导致了linux错失了很多游戏开发人员.

  当然现在版本, window 上也没有这个函数了. 改成下面这个挫的样子

#include <conio.h>    

_Check_return_     _DCRTIMP int __cdecl _getch(void);

总得而言''立即交互'' 是游戏开发的入口. 很有必要.

前言  -  从实际例子中了解getch

  现在Visual Studio 2015 Update3 中测试一段 getch 立即得到结果的代码 main.c

#include <stdio.h>
#include <stdlib.h>
#include <conio.h> /*
* 制作等待, 函数
*/
int main(int argc, char * argv[]) { printf("请输入任意字符结束程序......");
int rt = _getch();
printf("%d => %c\n", rt, rt);
rt = _getch();
printf("%d => %c\n", rt, rt);
system("pause");
return ;
}

运行结果

从上可以看出, _getch 名字变了, 但是功能和getch没有变化.

这里我们封装一下.  看新的文件, 一个演示小demo

#include <stdio.h>
#include <conio.h> /*
* 定义统一接口 sh_getch 理解得到玩家输入
* : 返回 输入int值, 错误为EOF
*/
#define sh_getch _getch /*
* 等待函数
*/
static void _pause(void) {
printf("请按任意键继续. . .");
rewind(stdin);
sh_getch();
} /*
* 继续等待函数
*/
int main(int argc, char * argv[]) { _pause();
return ;
}

来替代原先的 window 上 的 system("pause"), linux 上 pause(). rewind 重置文件FILE * 流, 清除输入流保证当前流是干净的.

正文   -   linux上实现一个getch, 立即接收

  linux 需要借助 termio.h 终端控制头文件.  主要实现如下

#include <termio.h>

/*
* 得到用户输入的一个字符
* : 返回得到字符
*/
int
sh_getch(void) {
int cr;
struct termios nts, ots; if (tcgetattr(, &ots) < ) // 得到当前终端(0表示标准输入)的设置
return EOF; nts = ots;
cfmakeraw(&nts); // 设置终端为Raw原始模式,该模式下所有的输入数据以字节为单位被处理
if (tcsetattr(, TCSANOW, &nts) < ) // 设置上更改之后的设置
return EOF; cr = getchar();
if (tcsetattr(, TCSANOW, &ots) < ) // 设置还原成老的模式
return EOF; return cr;
}

主要是设置终端为原始接收字符模式, 可以接收立即返回, 随后还原老的环境设置. 终端缓冲, 也是出于效率考虑, 否则编程太复杂了.

同样测试 一个 getch.c 

#include <stdio.h>
#include <termio.h> /*
* 得到用户输入的一个字符
* : 返回得到字符
*/
int sh_getch(void); /*
* 测试标准快速输入
*/
int main(int argc, char * argv[]) {
int ch; printf("请按任意键继续. . .");
ch = sh_getch();
printf("%d => %c\n", ch, ch); ch = sh_getch();
printf("%d => %c\n", ch, ch); return ;
}

linux上演示结果

 gcc -Wall -ggdb3 -o getch.out getch.c

一切正常.

  到这里我们关闭getch跨平台实现细节都确定了. 那么我们实现一个跨平台的getch版本. 先看头文件声明部分(*.h 文件插入).

/*
* error => 以后再说
* 跨平台的丑陋从这里开始
* __GNUC => linux 平台特殊操作
* __MSC_VER => window 平台特殊操作
*/
#ifdef __GUNC__ // 下面是依赖GCC编译器实现 #include <termio.h> /*
* 得到用户输入的一个字符
* : 返回得到字符
*/
int sh_getch(void); #elif _MSC_VER // 下面是依赖Visual Studio编译器实现 #include <conio.h> // window 上用_getch 替代了getch, 这里为了让其回来
#define sh_getch _getch #else
#error "error : Currently only supports the Visual Studio and GCC!"
#endif

再看实现部分 (*.c 文件中插入)

// 为linux扩展一些功能
#if defined(__GUNC__) /*
* 得到用户输入的一个字符
* : 返回得到字符
*/
int
sh_getch(void) {
int cr;
struct termios nts, ots; if (tcgetattr(, &ots) < ) // 得到当前终端(0表示标准输入)的设置
return EOF; nts = ots;
cfmakeraw(&nts); // 设置终端为Raw原始模式,该模式下所有的输入数据以字节为单位被处理
if (tcsetattr(, TCSANOW, &nts) < ) // 设置上更改之后的设置
return EOF; cr = getchar();
if (tcsetattr(, TCSANOW, &ots) < ) // 设置还原成老的模式
return EOF; return cr;
} #endif

这就是getch跨平台实现的关键了. 从这里开始,你就可以构建自己喜欢的游戏了, 通过 sh_getch 入口开始.

预备下次重构C字符串,再下次采用simplec框架重写一个老的灭龙传说V2.0.0游戏, 让其支持跨平台, 并支持配置扩展.

后记   -   未来有 ∞ 次

Get Over  http://music.163.com/#/song?id=22771653

C基础 一个可以改变linux的函数getch的更多相关文章

  1. 给定一个字符串,把字符串内的字母转换成该字母的下一个字母,a换成b,z换成a,Z换成A,如aBf转换成bCg, 字符串内的其他字符不改变,给定函数,编写函数 void Stringchang(const char*input,char*output)其中input是输入字符串,output是输出字符串

    import java.util.Scanner; /*** * 1. 给定一个字符串,把字符串内的字母转换成该字母的下一个字母,a换成b,z换成a,Z换成A,如aBf转换成bCg, 字符串内的其他字 ...

  2. [转]一个简单的Linux多线程例子 带你洞悉互斥量 信号量 条件变量编程

    一个简单的Linux多线程例子 带你洞悉互斥量 信号量 条件变量编程 希望此文能给初学多线程编程的朋友带来帮助,也希望牛人多多指出错误. 另外感谢以下链接的作者给予,给我的学习带来了很大帮助 http ...

  3. Linux内核分析第三周学习总结:构造一个简单的Linux系统MenuOS

    韩玉琪 + 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.Linux内 ...

  4. linux 线程函数大全

    Technorati 标签: Linux thread 索引: 1.创建线程pthread_create 2.等待线程结束pthread_join 3.分离线程pthread_detach 4.创建线 ...

  5. HOOK API (一)——HOOK基础+一个鼠标钩子实例

    HOOK API (一)——HOOK基础+一个鼠标钩子实例 0x00 起因 最近在做毕业设计,有一个功能是需要实现对剪切板的监控和进程的防终止保护.原本想从内核层实现,但没有头绪.最后决定从调用层入手 ...

  6. PHP基础入门(三)---PHP函数基础

    PHP基础入门(三)---函数 今天来给大家分享一下PHP的函数基础.有了前两章的了解,想必大家对PHP有了一定的基础了解.想回顾前两章的朋友可以点击"PHP基础入门(一)"&qu ...

  7. linux API函数大全

    获取当前执行路径:getcwd1. API之网络函数 WNetAddConnection 创建同一个网络资源的永久性连接 WNetAddConnection2 创建同一个网络资源的连接 WNetAdd ...

  8. linux select函数详解

    linux select函数详解 在Linux中,我们可以使用select函数实现I/O端口的复用,传递给 select函数的参数会告诉内核: •我们所关心的文件描述符 •对每个描述符,我们所关心的状 ...

  9. 【 MAKEFILE 编程基础之四】详解MAKEFILE 函数的语法与使用!

    本站文章均为 李华明Himi 原创,转载务必在明显处注明: 转载自[黑米GameDev街区] 原文链接: http://www.himigame.com/gcc-makefile/771.html   ...

随机推荐

  1. BZOJ4868 Shoi2017期末考试(三分+贪心)

    容易想到枚举最晚发布成绩的课哪天发布,这样与ti和C有关的贡献固定.每门课要么贡献一些调节次数,要么需要一些调节次数,剩下的算贡献也非常显然.这样就能做到平方级别了. 然后大胆猜想这是一个凸函数三分就 ...

  2. Vika and Segments - CF610D

    Vika has an infinite sheet of squared paper. Initially all squares are white. She introduced a two-d ...

  3. POJ 3261 Milk Patterns (后缀数组,求可重叠的k次最长重复子串)

    Milk Patterns Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 16742   Accepted: 7390 Ca ...

  4. [洛谷P4111][HEOI2015]小Z的房间

    题目大意:有一个$n\times m$的房间,一些位置是房间,另一些位置是柱子,相邻两个房间之间有墙,问有多少种方案可以打通一些墙把所有房间连成一棵树,柱子不可以打通 题解:矩阵树定理,把房间当点,墙 ...

  5. [NOIP2015 TG D2T3]运输计划

    题目大意: 给你一棵n个节点的树,有边权,有多个任务,每个要求从ui号节点到 vi号节点去.m 个计划, 这 m 个计划会同时开始.当这 m 个任务都完成时,工作完成. 现在可以把任意一个边的边权变为 ...

  6. [bzoj] 1068 压缩 || 区间dp

    原题 f[i][j][0/1]表示i-1处有一个M,i到j压缩后的长度,0/1表示i到j中有没有m. 初始为j-i+1 f[i][j][0]=min(f[i][j][0],f[i][k][0]+j-k ...

  7. bzoj1656: [Usaco2006 Jan] The Grove 树木 (bfs+新姿势)

      题目大意:一个n*m的图中,“.”可走,“X”不可走,“*”为起点,问从起点开始绕所有X一圈回到起点最少需要走多少步. 一开始看到这题,自己脑洞了下怎么写,应该是可过,然后跑去看了题解,又学会了一 ...

  8. bzoj1014: [JSOI2008]火星人prefix(splay+hash+二分)

    题目大意:一个字符串三个操作:①求两个后缀的LCP②插入一个字符③修改一个字符. 前几天刚学了hash+二分求lcp,就看到这题. 原来splay还能这么用?!原来splay模板这么好写?我以前写的s ...

  9. 将Visual Studio项目转换为Dot Net Core项目 csproj to xproj

    删除csproj文件. 将 package.config 重命名为 project.json . 转换文件,将xml转换为json格式. <?xml version="1.0" ...

  10. Tree and Permutation dfs hdu 6446

    Problem Description There are N vertices connected by N−1 edges, each edge has its own length.The se ...