リバーシ 06a1056 藤田将義 スライド一覧 リバーシプログラムのメソッド vectorについて メソッド一覧 メソッド名 説明 move Pointで指定された位置に石を打つ pass パスする undo 1つ前の手の状態に戻す init ボードをゲーム開始直後の状態にする isGameOver ゲームが終了しているかどうか調べる getColor 指定した座標の石の色を調べる countDisc 指定された石の個数を返す getCurrentColor 現在の手番の色を返す getUpdate 直前の手で返された石が並んだvectorを返す getMovablePos 石の打てる座標が並んだvectorを返す getTurns 現在の手数を返す checkMobility 指定された座標に石を打てるか、またどの方向に石を 裏返せるか判定 move { if(point.x <= 0 || point.x > BOARD_SIZE) return false; if(point.y <= 0 || point.y > BOARD_SIZE) return false; if(MovableDir[Turns][point.x][point.y] == NONE) return false; flipDiscs(point); Turns++; CurrentColor = -CurrentColor; initMovable(); } return true; 現在の手数、手番の色など更新 石が打てるか判定 flipDiscs int x, y; Disc operation(point.x , point.y, CurrentColor); // 行った操作を表す石 int dir = MovableDir[Turns][point.x][point.y]; std::vector<Disc> update; RawBoard[point.x][point.y] = CurrentColor; update.push_back(operation); // 上 if(dir & UPPER) // 上に置ける { y = point.y; operation.x = point.x; while(RawBoard[point.x][--y] != CurrentColor) { RawBoard[point.x][y] = CurrentColor; operation.y = y; update.push_back(operation); } } flipDiscs ・ ・ ・ // 石の数を更新 int discdiff = update.size(); Discs[CurrentColor] += discdiff; Discs[-CurrentColor] -= discdiff -1; Discs[EMPTY]--; UpdateLog.push_back(update); initMovable Disc disc(0, 0, CurrentColor); int dir; MovablePos[Turns].clear(); for(int x=1; x<=BOARD_SIZE; x++) { disc.x = x; for(int y=1; y<=BOARD_SIZE; y++) { disc.y = y; } } dir = checkMobility(disc); if(dir != NONE) { // 置ける MovablePos[Turns].push_back(disc); } MovableDir[Turns][x][y] = dir; checkMobility // 既に石があったら置けない if(RawBoard[disc.x][disc.y] != EMPTY) return NONE; int x, y; unsigned dir = NONE; // 上 if(RawBoard[disc.x][disc.y-1] == -disc.color) { x = disc.x; y = disc.y-2; while(RawBoard[x][y] == -disc.color) { y--; } if(RawBoard[x][y] == disc.color) dir |= UPPER; } ゲーム終了の判定 (isGameOver) { // 60手に達していたらゲーム終了 if(Turns == MAX_TURNS) return true; // 打てる手があるならゲーム終了ではない if(MovablePos[Turns].size() != 0) return false; //現在の手番と逆の色が打てるかどうか調べる Disc disc; disc.color = -CurrentColor; for(int x=1; x<=BOARD_SIZE; x++) { disc.x = x; for(int y=1; y<=BOARD_SIZE; y++) { disc.y = y; // 置ける箇所が1つでもあればゲーム終了ではない if(checkMobility(disc) != NONE) return false; } } } return true; pass { // 打つ手があればパスできない if(MovablePos[Turns].size() != 0) return false; // ゲームが終了しているなら、パスできない if(isGameOver()) return false; CurrentColor = -CurrentColor; // 空のupdateを挿入しておく UpdateLog.push_back(std::vector<Disc>()); initMovable(); } return true; undo { // ゲーム開始地点ならもう戻れない if(Turns == 0) return false; CurrentColor = -CurrentColor; const std::vector<Disc> &update = UpdateLog.back(); // 前回がパスかどうかで場合分け // 前回はパス if(update.empty()) { // MovablePos及びMovableDirを再構築 MovablePos[Turns].clear(); for(unsigned x=1; x<=BOARD_SIZE; x++) { for(unsigned y=1; y<=BOARD_SIZE; y++) { MovableDir[Turns][x][y] = NONE; } } } // 前回はパスでない else { undo Turns--; // 石を元に戻す RawBoard[x][y] = EMPTY; for(unsigned i=1; i<update.size(); i++) { RawBoard[update[i].x][update[i].y] = -update[i].color; } } // 石数の更新 unsigned discdiff = update.size(); Discs[CurrentColor] -= discdiff; Discs[-CurrentColor] += discdiff -1; Discs[EMPTY]--; // 不要になったupdateを1つ削除 UpdateLog.pop_back(); } return true; init { // 全マスを空きマスに設定 for(int x=1; x <= BOARD_SIZE; x++) { for(int y=1; y <= BOARD_SIZE; y++) { RawBoard[x][y] = EMPTY; } } // 壁の設定 for(int y=0; y < BOARD_SIZE + 2; y++) { RawBoard[0][y] = WALL; RawBoard[BOARD_SIZE+1][y] = WALL; } for(int x=0; x < BOARD_SIZE + 2; x++) { RawBoard[x][0] = WALL; RawBoard[x][BOARD_SIZE+1] = WALL; } init // 初期配置 RawBoard[4][4] RawBoard[5][5] RawBoard[4][5] RawBoard[5][4] = = = = WHITE; WHITE; BLACK; BLACK; // 石数の初期設定 Discs[BLACK] = 2; Discs[WHITE] = 2; Discs[EMPTY] = BOARD_SIZE*BOARD_SIZE - 4; // 手数は0から数える Turns = 0; // 先手は黒 CurrentColor = BLACK; // updateを全て消去 UpdateLog.clear(); } initMovable(); 情報を取得するメソッド unsigned countDisc(Color color) const { return Discs[color]; } Color getColor(const Point& p) const { return RawBoard[p.x][p.y]; } 石の数を数える 指定された位置の色を返す const std::vector<Point>& getMovablePos() const { return MovablePos[Turns]; } 石を打てる座標が 並んだvectorを返す 情報を取得するメソッド std::vector<Disc> getUpdate() const { if(UpdateLog.empty()) return std::vector<Disc>(); else return UpdateLog.back(); } Color getCurrentColor() const { return CurrentColor; } unsigned getTurns() const { return Turns; } 直前の手で打った石と 裏返した石が並んだ vectorを返す 現在の手番の色を返す 現在の手数を返す vectorについて サイズ可変な配列 1手目のupdate 2手目のupdate ・・・・ 3手目のupdate 返された石の座標 ・ ・ ・ ・ n手目のupdate 返された石の座標 新しく置いた石の座標 update 次回の予定 思考ルーチンについて 実際に動かせるようにしていく 参考文献 リバーシのアルゴリズム 著者 Seal Software ご清聴ありがとうございました
© Copyright 2024 ExpyDoc