You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

终端贪吃蛇开发:如何实时检测用户按下的方向键?

解决终端贪吃蛇的方向键检测与实时输入问题

核心问题分析

  • getchar()是阻塞式的,会导致游戏等待输入时完全暂停,无法实现实时运行的贪吃蛇逻辑
  • 方向键在终端中是以转义序列形式发送的(比如上方向键对应ESC [ A,ASCII码为27、91、65),不是单个字符,无法通过单字符读取直接识别

解决方案

1. 改造非阻塞键盘读取函数

通过调整termios参数实现非阻塞输入,同时处理方向键的转义序列:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <termios.h>
#include <stdbool.h>

// 定义方向键常量,方便后续逻辑判断
#define KEY_UP    1001
#define KEY_DOWN  1002
#define KEY_LEFT  1003
#define KEY_RIGHT 1004
#define KEY_ESC   27
#define KEY_QUIT  's'

int get_key() {
    struct termios oldt, newt;
    int ch;
    tcgetattr(STDIN_FILENO, &oldt);
    newt = oldt;
    
    // 关闭规范模式与回显,让输入无需回车即可读取
    newt.c_lflag &= ~(ICANON | ECHO);
    // 设置非阻塞模式:VMIN=0(无需等待字符),VTIME=0(无超时)
    newt.c_cc[VMIN] = 0;
    newt.c_cc[VTIME] = 0;
    
    tcsetattr(STDIN_FILENO, TCSANOW, &newt);
    ch = getchar();
    
    // 处理方向键的转义序列
    if (ch == KEY_ESC) {
        int ch2 = getchar();
        if (ch2 == '[') {
            int ch3 = getchar();
            switch(ch3) {
                case 'A': ch = KEY_UP; break;
                case 'B': ch = KEY_DOWN; break;
                case 'D': ch = KEY_LEFT; break;
                case 'C': ch = KEY_RIGHT; break;
                default: ch = ch3; break;
            }
        }
    }
    
    tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
    return ch;
}

2. 改造主循环实现实时游戏逻辑

主循环持续运行,同时非阻塞检查键盘输入,确保游戏不会因等待输入暂停:

int main() {
    system("clear");
    int snake_health = 3;
    bool horizontal = true;

    // 初始绘制蛇
    for (int i = 0; i <= snake_health; i++) {
        printf(i == snake_health ? ">" : "=");
    }
    printf("\n");

    while (1) {
        int key = get_key();
        
        // 仅当有输入时处理按键逻辑
        if (key != -1) {
            if (key == KEY_QUIT) {
                break;
            }
            // 打印按键反馈(可替换为蛇的转向逻辑)
            switch(key) {
                case KEY_UP: printf("上方向键\n"); break;
                case KEY_DOWN: printf("下方向键\n"); break;
                case KEY_LEFT: printf("左方向键\n"); break;
                case KEY_RIGHT: printf("右方向键\n"); break;
                default: printf("按下按键: %c\n", key); break;
            }
            
            system("clear");
            // 重新绘制蛇
            for (int i = 0; i <= snake_health; i++) {
                printf(i == snake_health ? ">" : "=");
            }
            printf("\n");
        }
        
        // 控制游戏帧率,调整数值改变蛇的移动速度
        usleep(100000);
    }

    return 0;
}

关键说明

  • 非阻塞设置:VMIN=0和VTIME=0让getchar()在无输入时立即返回-1,不会阻塞游戏循环
  • 方向键处理:终端方向键发送3字符转义序列,需连续读取多字符完成识别
  • 头文件补充:原代码使用bool但未包含<stdbool.h>,添加后可避免编译报错
  • 速度控制:通过usleep()控制每帧间隔,平衡游戏流畅度与可操作性

内容的提问来源于stack exchange,提问作者skami0_0

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 14:55:21