/* タートルグラフィックスインタプリタ 基本プログラム */ #include #include #include #include #include "draw.h" // ヘッダファイル名は人それぞれ. #include "pbm.h" // 各自の分割状況に適合させよう. #define WIDTH 320 // 画像の横幅 #define HEIGHT 240 // 画像の高さ #define BUFLEN 256 // コマンド行の最大文字数 #define ARGNUM 64 // コマンド引数の最大個数 /* タートル構造体 */ typedef struct{ double x, y; // 位置(右が+x,下が+y) double angle; // 方位(角度,右が0,下が90) int pen; // 軌跡フラグ(足跡無しが0,有りが1) } Turtle; /* タートルの移動 */ void TurtleMove(Turtle *t, Pbm *pbm, double dist) { int x1, y1, x2, y2; x1 = (int)(t->x); y1 = (int)(t->y); t->x += dist*cos(t->angle*M_PI/180.0); t->y += dist*sin(t->angle*M_PI/180.0); x2 = (int)(t->x); y2 = (int)(t->y); // if (t->pen) DrawLine(pbm, x1, y1, x2, y2, t->pen); // penup のとき消さない DrawLine(pbm, x1, y1, x2, y2, t->pen); // penup のとき消しゴムになる } /* タートルの方向転換 */ void TurtleTurn(Turtle *t, double angle) { t->angle += 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; TurtleMove(t, pbm, atof(arg[0])); } else if (strcmp(cmd, "left") == 0) { if (narg < 1) break; TurtleTurn(t, -atof(arg[0])); } else if (strcmp(cmd, "right") == 0) { if (narg < 1) break; TurtleTurn(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); /* タートルの初期化 */ t.x = WIDTH/2.0; // 画面中央 t.y = HEIGHT/2.0; t.angle = -90.0; // 上向き t.pen = 1; // 足跡残す /* 本体 */ Clear(pbm, 0); Tg(&t, fp, pbm); Output(pbm); /* 後処理 */ FreePbm(pbm); fclose(fp); return (0); }