/* 名稱: randwalk.c 作者: 洪朝貴 http://www.cyut.edu.tw/~ckhung/ 功能: 從命令列上讀入 delay 與 step, 隨機移動遊標, 並隨意亂走 step 步, 每走一步休息 delay 毫秒 需求: 螢幕必須支援 ANSI escape sequence */ #include #include #include /* 使用到 random() 和 exit() */ #include /* 使用到 usleep() */ #include /* 使用到 time() */ void clearscr(void); /* 清除螢幕 */ void gotorc(int r, int c); /* 將遊標移到第 r 列, 第 c 行 */ int main(int argc, char *argv[]) { int const MAX_ROW = 25, MAX_COL = 80; /* 螢幕的高度與寬度 (常數) */ int step; /* 總共要走多少步 */ int delay; /* 每步休息多少毫秒 */ int row, col; /* 目前遊標的位置 */ int row_new, col_new; /* 新的遊標位置 */ int dir; /* 接下來要走那個方向 */ int last_dir; /* 上次走那個方向 */ if (3 < argc) { fprintf(stderr, "usage: %s [delay [[#_of_steps]]\n", argv[0]); exit(1); /* return 敘述只能往上跳一層; exit() 函數則可終止程式 */ } /* 如果使用者沒有說每步要休息多久, 就休息 0.1 秒 */ delay = 2<=argc ? atoi(argv[1]) : 100; assert(delay > 0); /* 如果使用者沒有說要走多少步, 就走 200 步 */ step = 3<=argc ? atoi(argv[2]) : 200; assert(step > 0); clearscr(); /* 清除螢幕 */ srandom(time(NULL)); /* 用系統目前的時間起始亂數 */ /* 用亂數隨機決定遊標的起始坐標 */ row = 1 + (int) (random() / (RAND_MAX + 1.0) * MAX_ROW); col = 1 + (int) (random() / (RAND_MAX + 1.0) * MAX_COL); last_dir = -3; while (0 <= step) { /* 偷懶法: 用上限當做註標變數 ... */ /* 不斷地試, 直到決定下一步該怎麼走為止 */ do { /* 用亂數隨機決定下一步的方向 */ dir = random() / (RAND_MAX / 4); if (4 <= dir) dir = 3; if (2 == (dir-last_dir) || 2 == (last_dir-dir)) { /* 不要走回頭路 */ row_new = -1; /* 試試看: 拿掉這一句會怎麼樣? */ continue; } switch (dir) { /* 按照 右-下-左-上 的順序 */ case 0: col_new = col+1; row_new = row; break; case 1: col_new = col; row_new = row+1; break; case 2: col_new = col-1; row_new = row; break; case 3: col_new = col; row_new = row-1; break; default: assert(0); /* 不可能! */ } } while (0 >= col_new || col_new > MAX_COL || 0 >= row_new || row_new > MAX_ROW); /* 終於找到一個不會撞到牆壁的方向了 */ gotorc(row_new, col_new); /* 先到新的位置去 ... */ fflush(stdout); /* 把緩衝區裡的東西清乾淨 */ usleep(delay*1000); /* 休息一下 */ col = col_new; row = row_new; /* 重新上路 */ last_dir = dir; --step; /* ... 倒著數就可以不必另外宣告註標變數了 */ } gotorc(MAX_ROW, 1); /* 把遊標移到左下角 */ return 0; } /* 參考資料: 有關 ANSI escape sequence, 請參考: http://www.cs.utk.edu/~shuford/terminal/dec.html */ void clearscr(void) /* 不需要參數, 沒有傳回值 */ /* 清楚螢幕 */ { printf("\x1b[2J"); } void gotorc(int r, int c) /* 沒有傳回值 */ /* 將遊標移到螢幕上第 r 列, 第 c 行. */ { printf("\x1b[%d;%dH", r, c); }