Skip to content

sapporocpp/othello-battler

Repository files navigation

2015.10.17 Sapporo.cpp 第9回勉強会 お題「オセロ」

作:H.Hiro main@hhiro.net

ファイル構成

  • Makefile
    • Unix系OS向けのMakefileです。デフォルトでは othello_runnerothello_sample を生成します。
  • othello_lib.hpp
    • 共通の挙動を定義するヘッダです。
  • othello_runner.cpp
    • 対戦状況を管理するプログラムです。
  • othello_sample.cpp
    • 指す手を決めるプログラムです。これに相当するプログラムを皆様に作成していただくことになります。

なお、C++11で新規に規格化された機能も利用しているため、対応したコンパイラの用意をお願いします。

動かしてみる

Makefile を使う場合

makeでビルドができたら、

./othello_runner ./othello_sample ./othello_sample
(Windows環境では./は不要)

として実行します。これは、対戦状況を管理するプログラムであるothello_runnerが、黒プレイヤーをothello_sample、白プレイヤーをothello_sampleとして対戦させることを意味します。

Cloud9 IDE を使う場合

指す手を決める方法

概説

プログラムの例については othello_sample.cpp を見てください。これは、盤面の各場所について、石をルール上置いてよい場所であるか確かめ、それができるならその場所に置く(置いてよいと最初にわかった場所に置く)というものです。

皆様に作成していただくプログラムの挙動は、プログラムを1回実行するごとに「現在の盤面が与えられ、次に指す1手を選んで出力する」ものとなります。

より具体的には、

  • othello_runnerがこのプログラムに対し、コマンドライン引数を通じて盤面の情報を与えます(どんな引数が来るのかは気にしなくてよいです。othello_lib.hpp側で処理します)。
  • 皆様はそれを受け、どの手を次に指すかを決定し標準出力に出力します(出力方法についてはAPIがあります)。これがothello_runnerに引き渡されます。
  • 上記手順を繰り返し、対戦を進めます。

改良の方針

最初、何から手を付けてよいか分からないという場合は、例えばothello_sample.cppを以下のように改良してみるとよいでしょう:othello_sample.cppでは「ルール上置ける場所が1か所見つかればその場所に置く」としていたところを、「置ける場所をすべて調べ、その中で一番多く石を裏返せる場所に置く」とする。

もちろんこれだけでは、相手から反撃を受けてしまうこともあるでしょう。その先は皆様のアイデア次第です。

また、上記のサンプルプログラムを動かしてみるとわかるのですが、先手・後手の1手の差でかなり結果が大きく変わります。作成したプログラムを試す際は、先手・後手の両方で、また色々な相手と試してみるようにしましょう。

ルール

  • 各プログラムの2回総当たり(先手後手を1回ずつ持つ)とします。
  • 「時間をかければよい手を指せる方法」もあるわけですが、1手に何分とかを許可しても対局が長くなりすぎるので、1手3秒未満でお願いします。それを超えると失格となります。(1手を決めるのにかかった時間はプログラム実行時に表示されるので、参考にしてください。)

API

盤面情報の取得や結果の出力は、othello_lib.hpp内のnamespace Othello{ ... }内に定義されています。具体的な利用例はothello_sample.cppを参照してください。

enum class Othello::Piece;

石を表す列挙型です。

  • Piece BLACK; // 黒石を表す定数
  • Piece WHITE; // 白石を表す定数
  • Piece EMPTY; // 石は置かれていない
  • Piece INVALID; // 無効な座標を指定した場合などの値

class Othello::Placement;

石の配置を表すクラスです。

  • Placement::Placement();
    // コンストラクタ。石が何もない状態。
  • Placement::Placement(true);
    // コンストラクタ。初期状態の石の配置。
  • Placement::Placement(const Placement & other);
    // コンストラクタ。他のPlacementインスタンスをコピーする。
  • bool Placement::put(int i, int j, Piece piece);
    // 座標(i, j)に石pieceがある状態にする(裏返す操作まではしない)。
  • Piece Placement::get(int i, int j) const;
    // 座標(i, j)の石を取得する。
  • void Placement::display(void) const;
    // 盤面を表示する。
  • void Placement::display(int i, int j) const;
    // 上記と似るが、座標(i, j)を強調表示する。
    // othello_runner.cppでは最後に指された手を表示するのに利用している。

class Othello::Board;

盤面情報(石の配置+次はどちらのプレイヤーの手番か+nonce)を表すクラスです。

コマンドライン引数をこのクラスに変換したのち、指す手を決める処理を行います。

  • Placement Board::placement(void);
    // 石の配置を取得する。
    // 上記のPlacementクラスとして得られる。
  • void Board::put(int i, int j);
  • void Board::put(void);
    // 座標(i, j)に石を置くことを表す出力を行う。
    // 1回のプログラム実行につき1回だけ呼ぶこと。
    // どこにも石が置けない場合、引数なしの put() を呼ぶ。
  • Piece Board::my_color(void);
  • Piece Board::opponent_color(void);
    // それぞれ、自分の色ならびに相手の色。

補足

  • 結果は標準出力を使って受け渡されるので、何かデバッグ出力をしたい場合は標準エラーを使ってください。