/* タートルグラフィックスインタプリタ 基本プログラム */ #include #include #include #include #include "turtle.h" #include "draw.h" // ヘッダファイル名は人それぞれ... #include "pbm.h" // ...各自の分割状況に適合させよう. #define WIDTH 320 // 画像の横幅 #define HEIGHT 240 // 画像の高さ #define BUFLEN 256 // コマンド行の最大文字数 #define ARGNUM 64 // コマンド引数の最大個数 /* タートルの移動 */ void TgMove(Turtle *t, Pbm *pbm, double dist) { int x1, y1, x2, y2; double rad; int pen; x1 = (int)TurtleGetX(t); // 移動前の位置 y1 = (int)TurtleGetY(t); rad = TurtleGetDir(t)*M_PI/180.0; // 方角(rad) TurtleAddX(t, dist*cos(rad)); // 移動 TurtleAddY(t, dist*sin(rad)); x2 = (int)TurtleGetX(t); // 移動後の位置 y2 = (int)TurtleGetY(t); pen = TurtleGetPen(t); DrawLine(pbm, x1, y1, x2, y2, pen); // penup のとき消しゴムになる // if (pen) DrawLine(pbm, x1, y1, x2, y2, pen); // penup のとき消さない } /* タートルの方向転換 */ void TgTurn(Turtle *t, double angle) { TurtleAddDir(t, angle); } /* スクリプトの処理 */ void Tg(Turtle *t, FILE *fp, Pbm *pbm) { char buf[BUFLEN], *cmd, *p; // コマンド行関連 char *arg[ARGNUM]; // コマンドの引数(argv[] 的なヤツラ) int narg; // コマンドの引数の個数(argc 的なヤツ) int i, nrep, fpos; // repeat コマンド関連 while (1) { // コマンド行をバッファへ入力 if (fgets(buf, 256, fp) == NULL) break; // バッファからコマンドを取得 cmd = strtok(buf, " \t\n"); if (cmd == NULL) continue; // バッファからコマンド引数を取得 narg = 0; while (1) { p = strtok(NULL, " \t\n"); if (p == NULL) break; arg[narg] = p; narg++; } // 描画コマンドの処理 if (strcmp(cmd, "forward") == 0) { if (narg < 1) break; TgMove(t, pbm, atof(arg[0])); } else if (strcmp(cmd, "left") == 0) { if (narg < 1) break; TgTurn(t, -atof(arg[0])); } else if (strcmp(cmd, "right") == 0) { if (narg < 1) break; TgTurn(t, atof(arg[0])); } // 反復コマンドの処理 else if (strcmp(cmd, "repeat") == 0) { if (narg < 1) break; nrep = atoi(arg[0]); fpos = ftell(fp); // 現在のファイル位置を記録 for (i = 0; i < nrep; i++) { fseek(fp, fpos, SEEK_SET); // 記録されたファイル位置へ移動 Tg(t, fp, pbm); // 再帰呼び出し } } else if (strcmp(cmd, "end") == 0) { return; // 再帰終了 } } } void Help() { fprintf(stderr, "使い方:$ ./tg スクリプト.tg | display\n"); exit(EXIT_FAILURE); } int main(int argc, char *argv[]) { FILE *fp; Pbm *pbm; Turtle t; /* 前処理 */ if (argc != 2) Help(); fp = fopen(argv[1], "r"); if (fp == NULL) Help(); pbm = NewPbm(WIDTH, HEIGHT); if (pbm == NULL) return (1); /* タートルの初期化 */ TurtleSetPos(&t, WIDTH/2.0, HEIGHT/2.0); // 画面中央 TurtleSetDir(&t, -90.0); // 上向き TurtleSetPen(&t, 1); // 足跡残す /* 本体 */ Clear(pbm, 0); Tg(&t, fp, pbm); Output(pbm); /* 後処理 */ FreePbm(pbm); fclose(fp); return (0); }