*),可用W/A/S/D鍵移動Ctrl+C退出
typedef struct { int x, y; } Point;
int main() {
int width, height, origin_x, origin_y;
// 輸入邊框參數...
Point box_origin = {origin_x, origin_y};
Point box_size = {width, height};
Point dot = {origin_x + 5, origin_y + 5}; // 初始點位置
term_init();
system("clear");
draw_frame(&box_origin, &box_size, &dot);
char c;
while (read(STDIN_FILENO, &c, 1) == 1) {
Point new_dot = dot;
switch (c) {
case 'w': case 'W': if (dot.y > box_origin.y + 1) new_dot.y--; break;
case 's': case 'S': if (dot.y < box_origin.y + box_size.y - 2) new_dot.y++; break;
case 'a': case 'A': if (dot.x > box_origin.x + 1) new_dot.x--; break;
case 'd': case 'D': if (dot.x < box_origin.x + box_size.x - 2) new_dot.x++; break;
case 'q': case 'Q': goto exit_loop;
}
dot = new_dot;
system("clear");
draw_frame(&box_origin, &box_size, &dot);
}
exit_loop:
term_restore();
return 0;
}
void draw_frame(Point *o, Point *sz, Point *dot) {
for (int y = o->y; y < o->y + sz->y; y++) {
for (int x = o->x; x < o->x + sz->x; x++) {
bool is_border = (y == o->y || y == o->y + sz->y - 1 ||
x == o->x || x == o->x + sz->x - 1);
bool is_dot = (x == dot->x && y == dot->y);
putchar(is_border || is_dot ? '*' : ' ');
}
putchar('\n');
}
}
dot.x > origin.x + 1 確保不覆蓋左邊框(+1跳過邊框列)system("cls")VMIN=1, VTIME=0實現阻塞單字符讀取(0,0)在左上角,x向右,y向下ncurses替代system("clear"),無閃爍、高效刷新select()或非阻塞IO實現定時自動更新/動畫X10/X11鼠標協議)TerminalUI庫通過termios切換終端到原始模式,配合system("clear")重繪,實現了交互式終端圖形程序。這是理解終端控制、原始輸入、座標繪製、邊界約束的優秀入門項目,也是ncurses、vim、tmux等工具的核心原理縮影。