列挙:SimplestAIPlayer

SimplestAIPlayer は最も単純なAIプレーヤーです。

リバーシ盤を左上から順に調べて、打てる場所が見つかればそこに打ちます。
打てる場所が1つも見つからなければ、パスを宣言します。

SimplestAIPlayer はリバーシ盤を左上から順に走査します。

とても単純ですね。しかし、侮るなかれ! すべての可能性を順番にピックアップして調べ上げるというのは、色々な処理の基本となる考え方です。アルゴリズムの基本中の基本ですので、十分、手に馴染ませておきましょう!

余談:常に左上から調べるのは効率が悪いかもしれません。より良い方法はないでしょうか?
あるいは、たとえば将棋の SimplestAIPlayer を作るとしたら「すべての可能性」をどのようにピックアップしたらよいでしょうか??
考えてみると面白いかもしれません。

さて、SimplestAIPlayer はソースコードもとてもシンプルです。

ただ、上のソースコードでは Java8 で導入された Stream やラムダ式、Optional クラスを利用しているので、少しわかりにくいかもしれません。

上記のコードと同じ振る舞いをする代替実装例をいくつか挙げてみます。
上記のコードが分かりにくいと感じる方は、順を追って見ていくと理解しやすいかもしれません。

代替実装例1

次のコードは正規のコードと同じ結果を返します。

Point#of は位置 (i, j) を表す Point オブジェクトを返します。
Rule#canPutAt は指定された位置に石を打てるかを返します。
詳細は javadoc を参照してください。

代替実装例2

次の例では、代替実装例1の (i, j) によるループの代わりに、Java 5 で導入された拡張 for 文(for-each ループ)を利用しています。

Point#values は、すべての Point オブジェクトを格納した配列(Point[])を返します。

代替実装例1と比べるとループの方法を変えただけですが、随分すっきりしましたね。

代替実装例3

さて、いよいよ Stream、ラムダ式、Optional クラスを導入します。
代替実装例1, 2とはガラッと変わります。

ステップごとに行を分けましたが、これを連結すると冒頭に挙げた正規のコードになります。

代替実装例1, 2が「どのような手順で処理を行うか」という手続き指向のコードなのに対して、正規のコードや代替実装例3は「何をしたいのか」「どのような結果が欲しいのか」という、いわば目的指向のコードになっています。
そのため、Stream やラムダ式、Optional クラスなどを使いこなすと、とても読みやすく理解しやすいコードになります。

しかし、従来のコードとはかなり異なる概念を把握する必要があり、バグを含まない安全なコードを実装するためには、そこそこの知識が必要になります。

そのため、個人的には、Java 初級者の人が無理に利用しようとする必要はないと思います。代替実装例2のコードをすらすら書けるようになれば、まずは十分でしょう。

スポンサーリンク
reversi_main 336*280
reversi_main 336*280

フォローする