C语言中有没有获取键盘按键输入的函数或语句 用于控制终端方块移动
终端方块移动功能实现方案
核心问题:C标准库默认的输入函数为行缓冲模式,必须按下回车才会返回输入结果,无法满足实时控制需求,需要修改终端属性实现无缓冲、无回显的即时按键读取。
实现逻辑
- 程序启动时修改终端配置,关闭行缓冲和输入回显,按键按下即可立刻读取
- 编写主循环,每轮循环按顺序执行:清屏 → 读取按键 → 更新方块坐标 → 绘制画布 → 帧间隔延迟
- 程序退出前恢复终端原始配置,避免终端使用异常
- 补充边界校验逻辑,避免方块移出预设的16行24列画布范围
可运行参考代码(Linux/macOS 平台)
#include <stdio.h> #include <stdlib.h> #include <termios.h> #include <unistd.h> #include <fcntl.h> #define ROWS 16 #define COLS 24 // 你原来的宏定义可以保留使用 #define dot -> #define or || #define and && #define pointer * typedef struct Square { float x, y; float w, h; char c; } Square; void draw_squares(Square pointer pointer, int); Square pointer create_square(float, float, float, float, char); // 新增终端配置相关函数 void set_terminal_mode(); void reset_terminal_mode(); int get_key_press(); int main(void) { int square_count = 3; Square pointer pointer squares = malloc(sizeof(Square pointer) * square_count); squares[0] = create_square(14, 11, 4, 4, '#'); squares[1] = create_square(8, 6, 4, 3, '@'); squares[2] = create_square(1, 1, 3, 7, '&'); // 初始化终端模式 set_terminal_mode(); // 主循环,按q退出 int running = 1; while (running) { // 清屏 printf("\033[H\033[2J"); // 读取按键 int key = get_key_press(); Square pointer control_sq = squares[0]; // 控制#号方块 switch (key) { case 'w': if (control_sq dot y > 0) control_sq dot y -= 1; break; case 's': if (control_sq dot y + control_sq dot h < ROWS) control_sq dot y += 1; break; case 'a': if (control_sq dot x > 0) control_sq dot x -= 1; break; case 'd': if (control_sq dot x + control_sq dot w < COLS) control_sq dot x += 1; break; case 'q': running = 0; break; } // 绘制画布 draw_squares(squares, square_count); // 控制帧率,约30帧 usleep(33000); } // 恢复终端配置 reset_terminal_mode(); // 释放内存 for (int i = 0; i < square_count; i++) { free(squares[i]); } free(squares); return 0; } void draw_squares(Square pointer pointer squares, int len) { for(int y = 0; y < ROWS; ++ y) { for(int x = 0; x < COLS; ++ x) { char ch = ' '; for(int ix = 0; ix < len; ++ ix) { Square pointer s = squares[ix]; if( (s dot x) <= x and (s dot x + s dot w) > x and (s dot y) <= y and (s dot y + s dot h) > y ) { ch = s dot c; break; } } putchar(ch); } putchar('\n'); } } Square pointer create_square(float x, float y, float w, float h, char c) { Square pointer sq = malloc(sizeof(Square)); sq dot x = x; sq dot y = y; sq dot w = w; sq dot h = h; sq dot c = c; return sq; } // 以下为终端操作相关实现 static struct termios orig_termios; void set_terminal_mode() { tcgetattr(STDIN_FILENO, &orig_termios); struct termios new_termios = orig_termios; new_termios.c_lflag &= ~(ICANON | ECHO); tcsetattr(STDIN_FILENO, TCSANOW, &new_termios); fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK); } void reset_terminal_mode() { tcsetattr(STDIN_FILENO, TCSANOW, &orig_termios); } int get_key_press() { char c; if (read(STDIN_FILENO, &c, 1) == 1) { return c; } return 0; }
Windows 平台适配说明
将终端相关代码替换为以下内容即可:
- 头文件引入替换为
#include <conio.h>和<windows.h> - 删掉
set_terminal_mode、reset_terminal_mode、get_key_press函数实现 - 主循环中读取按键的逻辑替换为:
int key = 0; if (_kbhit()) { key = _getch(); } - 清屏逻辑替换为
system("cls") - 延迟函数替换为
Sleep(33)
内容的提问来源于stack exchange,提问作者Muffinz
相关产品推荐
相关产品推荐

