// 例題5 包囲ゲーム // move.c 手入力部 #include #include #include // ヘッダファイル読み込み #include "game.h" #include "board.h" #include "move.h" #include "rule.h" // 投了を表すデータ const Move resign = { -1, -1, -1, -1, 0}; // 投了と飛び越しの終了判定関数 inline bool resigned(Point p) { return (p.x<0)&&(p.y<0); } inline bool ended(Point p) { return (p.x==0)&&(p.y==0); } inline bool valid(int v) { return (v>0 && vx,p->y)に結果 bool separate(char *s, Point *p) { char *s2 = s; switch (*s2) { case 'q': p->x=p->y = -1; return true; // 投了 case 'e': p->x=p->y = 0; return true; // 飛び越し終了 default: while (*s2 && *s2 != ' ') s2++; // 空白の検出 if (*s2 == 0) return false; *s2= 0; s2++; p->x = atoi(s); p->y = atoi(s2); return valid(p->x)&&valid(p->y); // 範囲外ならエラー } } // 座標の入力 // 引数 *mes:メッセージ // 戻り値 (p->x,p->y)に入力結果 void input_point(const char *mes, Point *p) { char buf[80]; int x,y; while (1) { printf(mes); fgets(buf,80,stdin); // bufに入力 if (strchr(buf,'\n')==0) // 改行を含まないならば while (fgetc(stdin)!='\n') ; // 改行まで空読み if (separate(buf,p)) return; // 分離成功 printf("error:input format\n"); } } // (飛び越しを含まない)1手分を入力 void input_move_one(Move *mp,const Board *bp) { while (1) { // 始点入力 input_point("from:",&(mp->from)); if (resigned(mp->from)) { *mp = resign; break; } // 終点入力 input_point("to :",&(mp->to)); if (resigned(mp->to)) { *mp = resign; break; } // ルール検査 if (check_rules(mp,bp)) break; printf("error:illegal move\n"); } mp->next = 0; } // 飛び越しを含む入力 void input_move(Move *mp,const Board *bp) { int c=0; // 取られた白石の数 extern const char *turnname[]; printf("%s's turn\n", turnname[bp->turn]); // 1手入力 input_move_one(mp,bp); if (resigned(mp->from)) return; // 石があり、飛び越しである限り繰り返し while (++c < bp->white_leave && isjump(mp->from,mp->to)) { Move *mp2 = (Move*)malloc(sizeof(Move)); mp2->from = mp->to; mp2->next = 0; while (1) { input_point("to :", &(mp2->to)); if (ended(mp2->to)) return; if (isjump(mp2->from,mp2->to)&& getcolor(bp,mp2->to)==c_empty) break; printf("error:illegal move\n"); } mp->next = mp2; mp=mp2; } } // 手の表示 // 引数 *mp: 線形リストの先頭 void show_move(const Move *mp) { printf("move:(%d,%d)", mp->from.x, mp->from.y); for (;mp;mp=mp->next) { printf("->(%d,%d)",mp->to.x, mp->to.y); } printf("\n"); } // 1手入力のテスト void test_input_move_one() { Move m; Board b; init_board(&b); show_board(&b); input_move_one(&m,&b); printf("move:(%d,%d)->(%d,%d)\n", m.from.x, m.from.y, m.to.x, m.to.y); update_board(&m,&b); show_board(&b); } // 盤面更新部 // 引数 *mp: 手の内容 // 引数 *bp 更新前と更新後の盤面 void update_board(const Move *mp, Board *bp) { for (;mp;mp=mp->next) { Color c = getcolor(bp, mp->from); setcolor(bp,mp->from,c_empty); setcolor(bp,mp->to, c); if (c == c_black) { bp->black_pos = mp->to; } if (isjump(mp->from, mp->to)) { Point p = inter(mp->from,mp->to); if (getcolor(bp,p) == c_white) { setcolor(bp,p, c_empty); bp->white_leave--; } } } } // 座標入力のテスト void test_input_point() { Point from, to; input_point("from:",&from); input_point("to :",&to ); printf("(%d,%d)->(%d,%d)\n", from.x, from.y, to.x, to.y); } // 方向名 const char* dirname[] = { "none", "up", "down", "left", "right", 0 }; // 方向検出のテスト void test_getdir() { Point from, to; input_point("from:", &from); input_point("to :", &to ); printf("dir=%s\n", dirname[getdir(from,to)]); } // 盤面更新テストデータ const Move m1 = { {4,4}, {5,4}, 0} ; const Move m2 = { {3,3}, {3,4}, 0} ; const Move m3 = { {5,4}, {5,5}, 0} ; const Move m4 = { {5,3}, {5,4}, 0} ; const Move m6 = { {5,3}, {3,3}, 0} ; const Move m5 = { {5,5}, {5,3}, &m6} ; // 盤面更新部のテスト void test_update_board() { Board b; init_board(&b); // 初期化 show_board(&b); update_board(&m1,&b); // 黒番 show_board(&b); update_board(&m2,&b); // 白番 show_board(&b); update_board(&m3,&b); // 黒番 show_board(&b); update_board(&m4,&b); // 白番 show_board(&b); update_board(&m5,&b); // 黒番 show_board(&b); }