input_demo.c

Download
c 221 lines 5.9 KB
  1// input_demo.c
  2// 비동기 ν‚€λ³΄λ“œ μž…λ ₯ μ‹œμ—° ν”„λ‘œκ·Έλž¨
  3// termiosλ₯Ό μ‚¬μš©ν•˜μ—¬ non-blocking μž…λ ₯을 κ΅¬ν˜„ν•©λ‹ˆλ‹€.
  4
  5#include <stdio.h>
  6#include <stdlib.h>
  7#include <termios.h>
  8#include <unistd.h>
  9#include <fcntl.h>
 10
 11// μ›λž˜ 터미널 μ„€μ • μ €μž₯
 12static struct termios original_termios;
 13
 14// 터미널을 raw λͺ¨λ“œλ‘œ μ„€μ •
 15void enable_raw_mode(void) {
 16    // ν˜„μž¬ 터미널 μ„€μ • μ €μž₯
 17    tcgetattr(STDIN_FILENO, &original_termios);
 18
 19    struct termios raw = original_termios;
 20
 21    // μž…λ ₯ ν”Œλž˜κ·Έ μˆ˜μ •
 22    // ECHO: μž…λ ₯ν•œ 문자 화면에 ν‘œμ‹œ μ•ˆν•¨
 23    // ICANON: 라인 버퍼링 끄기 (μ—”ν„° 없이 μ¦‰μ‹œ 읽기)
 24    raw.c_lflag &= ~(ECHO | ICANON);
 25
 26    // μ΅œμ†Œ μž…λ ₯ 문자 수: 0 (non-blocking κ°€λŠ₯)
 27    raw.c_cc[VMIN] = 0;
 28    // νƒ€μž„μ•„μ›ƒ: 0 (μ¦‰μ‹œ λ°˜ν™˜)
 29    raw.c_cc[VTIME] = 0;
 30
 31    // μˆ˜μ •λœ μ„€μ • 적용
 32    tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw);
 33}
 34
 35// 터미널 μ„€μ • 볡원
 36void disable_raw_mode(void) {
 37    tcsetattr(STDIN_FILENO, TCSAFLUSH, &original_termios);
 38}
 39
 40// ν‚€ μž…λ ₯ 확인 (non-blocking)
 41// λ°˜ν™˜: 1 = μž…λ ₯ 있음, 0 = μž…λ ₯ μ—†μŒ
 42int kbhit(void) {
 43    int ch = getchar();
 44    if (ch != EOF) {
 45        ungetc(ch, stdin);  // 읽은 문자λ₯Ό λ‹€μ‹œ 버퍼에 λ„£μŒ
 46        return 1;
 47    }
 48    return 0;
 49}
 50
 51// ν‚€ 읽기 (non-blocking)
 52int getch(void) {
 53    return getchar();
 54}
 55
 56// λ°©ν–₯ν‚€ 및 νŠΉμˆ˜ν‚€ μ½”λ“œ
 57typedef enum {
 58    KEY_NONE = 0,
 59    KEY_UP,
 60    KEY_DOWN,
 61    KEY_LEFT,
 62    KEY_RIGHT,
 63    KEY_QUIT,
 64    KEY_SPACE,
 65    KEY_ENTER,
 66    KEY_OTHER
 67} KeyCode;
 68
 69// ν‚€ 읽기 및 해석 (escape sequence 처리)
 70KeyCode read_key(void) {
 71    int ch = getchar();
 72
 73    // μž…λ ₯ μ—†μŒ
 74    if (ch == EOF) return KEY_NONE;
 75
 76    // μ’…λ£Œ ν‚€
 77    if (ch == 'q' || ch == 'Q') return KEY_QUIT;
 78
 79    // μŠ€νŽ˜μ΄μŠ€λ°”
 80    if (ch == ' ') return KEY_SPACE;
 81
 82    // μ—”ν„°
 83    if (ch == '\n' || ch == '\r') return KEY_ENTER;
 84
 85    // Escape sequence (λ°©ν–₯ν‚€ λ“±)
 86    // λ°©ν–₯ν‚€λŠ” 3λ°”μ΄νŠΈ: ESC(27) + '[' + 문자
 87    if (ch == '\033') {
 88        int ch2 = getchar();
 89        if (ch2 == '[') {
 90            int ch3 = getchar();
 91            switch (ch3) {
 92                case 'A': return KEY_UP;
 93                case 'B': return KEY_DOWN;
 94                case 'C': return KEY_RIGHT;
 95                case 'D': return KEY_LEFT;
 96            }
 97        }
 98        // ESC만 λˆŒλ €μ„ λ•Œ
 99        return KEY_QUIT;
100    }
101
102    // WASD ν‚€ 지원
103    switch (ch) {
104        case 'w': case 'W': return KEY_UP;
105        case 's': case 'S': return KEY_DOWN;
106        case 'a': case 'A': return KEY_LEFT;
107        case 'd': case 'D': return KEY_RIGHT;
108    }
109
110    return KEY_OTHER;
111}
112
113// ν‚€ μ½”λ“œλ₯Ό λ¬Έμžμ—΄λ‘œ λ³€ν™˜
114const char* keycode_to_string(KeyCode key) {
115    switch (key) {
116        case KEY_UP: return "μœ„μͺ½";
117        case KEY_DOWN: return "μ•„λž˜μͺ½";
118        case KEY_LEFT: return "μ™Όμͺ½";
119        case KEY_RIGHT: return "였λ₯Έμͺ½";
120        case KEY_SPACE: return "슀페이슀";
121        case KEY_ENTER: return "μ—”ν„°";
122        case KEY_QUIT: return "μ’…λ£Œ";
123        default: return "기타";
124    }
125}
126
127int main(void) {
128    // raw λͺ¨λ“œ ν™œμ„±ν™”
129    enable_raw_mode();
130    // ν”„λ‘œκ·Έλž¨ μ’…λ£Œ μ‹œ μžλ™μœΌλ‘œ 터미널 μ„€μ • 볡원
131    atexit(disable_raw_mode);
132
133    // ν™”λ©΄ μ΄ˆκΈ°ν™”
134    printf("\033[2J\033[H");  // ν™”λ©΄ μ§€μš°κΈ° + μ»€μ„œ ν™ˆ
135    printf("\033[?25l");       // μ»€μ„œ 숨기기
136
137    printf("=== 비동기 ν‚€λ³΄λ“œ μž…λ ₯ μ‹œμ—° ===\n\n");
138    printf("μ‘°μž‘λ²•:\n");
139    printf("  - λ°©ν–₯ν‚€ λ˜λŠ” WASD: 이동\n");
140    printf("  - 슀페이슀: 점프\n");
141    printf("  - Q λ˜λŠ” ESC: μ’…λ£Œ\n\n");
142    printf("κ²Œμž„ ν™”λ©΄:\n");
143    printf("β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”\n");
144    for (int i = 0; i < 15; i++) {
145        printf("β”‚                                        β”‚\n");
146    }
147    printf("β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜\n");
148
149    // ν”Œλ ˆμ΄μ–΄ 초기 μœ„μΉ˜
150    int x = 20, y = 12;
151    int jump_height = 0;
152    int key_count = 0;
153
154    // μƒνƒœ ν‘œμ‹œ μœ„μΉ˜
155    int status_row = 23;
156
157    // 메인 루프
158    while (1) {
159        // ν‚€ μž…λ ₯ 읽기 (non-blocking)
160        KeyCode key = read_key();
161
162        if (key == KEY_QUIT) break;
163
164        // 이전 μœ„μΉ˜ μ§€μš°κΈ°
165        printf("\033[%d;%dH ", y - jump_height, x);
166
167        // μž…λ ₯ 처리
168        switch (key) {
169            case KEY_UP:
170                if (y > 7) y--;
171                key_count++;
172                break;
173            case KEY_DOWN:
174                if (y < 20) y++;
175                key_count++;
176                break;
177            case KEY_LEFT:
178                if (x > 3) x--;
179                key_count++;
180                break;
181            case KEY_RIGHT:
182                if (x < 41) x--;
183                key_count++;
184                break;
185            case KEY_SPACE:
186                jump_height = (jump_height == 0) ? 2 : 0;
187                key_count++;
188                break;
189            default:
190                break;
191        }
192
193        // μƒˆ μœ„μΉ˜μ— ν”Œλ ˆμ΄μ–΄ 그리기
194        printf("\033[%d;%dH\033[32m@\033[0m", y - jump_height, x);
195
196        // μƒνƒœ 정보 μ—…λ°μ΄νŠΈ
197        printf("\033[%d;1H", status_row);
198        printf("μœ„μΉ˜: (%d, %d)  ", x, y);
199        printf("점프: %s  ", jump_height > 0 ? "ON " : "OFF");
200        printf("μž…λ ₯ 횟수: %d  ", key_count);
201        if (key != KEY_NONE) {
202            printf("λ§ˆμ§€λ§‰ μž…λ ₯: %s    ", keycode_to_string(key));
203        }
204
205        // ν™”λ©΄ κ°±μ‹ 
206        fflush(stdout);
207
208        // ν”„λ ˆμž„ 레이트 μ œμ–΄ (50ms = 20 FPS)
209        usleep(50000);
210    }
211
212    // μ’…λ£Œ 처리
213    printf("\033[2J\033[H");  // ν™”λ©΄ μ§€μš°κΈ°
214    printf("\033[?25h");       // μ»€μ„œ 보이기
215
216    printf("ν”„λ‘œκ·Έλž¨μ„ μ’…λ£Œν•©λ‹ˆλ‹€.\n");
217    printf("총 μž…λ ₯ 횟수: %d\n", key_count);
218
219    return 0;
220}