藤田将義

リバーシ
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
ご清聴ありがとうございました