引言  -  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. 【题解】CF#1012 C-Hill

    感觉这题的状态还是比较明显的.设置状态 \(f[i][j][0/1]\) 表示dp到第 \(i\) 个位置,前面(包括这里)已经出现了 \(j\) 个山峰,当前位置是不是山峰即可 dp.这样的状态有一 ...

  2. 洛谷3258:[USACO2012 MAR]Flowerpot 花盆——题解

    https://www.luogu.org/problemnew/show/P2698#sub 老板需要你帮忙浇花.给出N滴水的坐标,y表示水滴的高度,x表示它下落到x轴的位置. 每滴水以每秒1个单位 ...

  3. 【神仙DP】【单调队列】【模拟题】区间覆盖

    传送门 Description 给出数轴上的n个线段,保留最多k条线段,问这些被保留下来的线段的并集长度为最多为多少. Input 第一行两个数n和k 接下来n行,每行两个数,表示一条线段的左右端点. ...

  4. DPM(Deformable Parts Model)--原理(一)

    http://blog.csdn.net/ttransposition/article/details/12966521 DPM(Deformable Parts Model) Reference: ...

  5. 《python核心编程》读书笔记--第18章 多线程编程

    18.1引言 在多线程(multithreaded,MT)出现之前,电脑程序的运行由一个执行序列组成.多线程对某些任务来说是最理想的.这些任务有以下特点:它们本质上就是异步的,需要多个并发事务,各个事 ...

  6. Coconuts HDU - 5925 二维离散化 自闭了

    TanBig, a friend of Mr. Frog, likes eating very much, so he always has dreams about eating. One day, ...

  7. [解决]java.io.IOException: Cannot obtain block length for LocatedBlock

    在hadoop测试集群运行job的过程中发现部分运行失败,有Cannot obtain block length for LocatedBlock,使用hdfs dfs -cat ${文件}的时候也报 ...

  8. CMDB资产管理系统开发【day26】:CMDB上节回顾

    一.上节知识点回顾 服务器设计了一个表结构 开发了一个客户端 二.后台创建缓存区表 客户端连接服务器,在服务器的下面看报错信息 因为URL都没有写,所以我找不到呀 1.在MadKing\url.py ...

  9. 子字符串substring 问题 - KMP 字符串匹配算法备忘录

    本文为自己对KMP的理解. 对KMP很好的介绍可以参考 http://www.cnblogs.com/yjiyjige/p/3263858.html 本文为对这篇文章的提炼和补充. KMP算法基本思想 ...

  10. rocketmq单机搭建

    RocketMQ 是alibaba开源的消息队列. 本文使用的是开源版本v3.18 系统: centos6.x最小化安装 需要用到的软件包: jdk-7u67-linux-x64.tar.gz ali ...