ソフトウェアの品質を学びまくる2.0

旧ブログからゆっくり移行中です。http://blog.livedoor.jp/prjmng/

リバーシ(オセロ)を部分的に実装して、ソフトウェア開発関係者であることを証明する ー その1

 ソフトウェアエンジニアならリバーシ(いわゆる、オセロ)の実装くらいできるだろう、というのが話題になっていたので、やってみることにしました。

 8×8マスの情報を保持するための「配列」、マスの状態を一つ一つ見ていく「繰り返し」、石をおける/おけない、返る返らないの「判定」など、プログラミングの基本概念を知っていれば、実装できそうです。
 では、わたしのような者にとって、ここで選ぶべき「言語」は何でしょう。

 そうです、Microsoft Excelですね。
 あ、いいえ、VBAではありません、Excelワークシート関数です。
 何しろワークシートを方眼紙状にすることで、盤面を即、表現できますから。

 といっても、全部やるほどの週末はないので、「そのセルに黒石をおけるかを判定する」部分を作ってみました。

自然言語で表現する

 あるマスに黒石をおくためには、そのマスの上下左右、斜めの計8方向のいずれかについて、以下の条件を満たしていることが必要です。

  1. 対象の位置に、石がない。
  2. 対象の方向に、黒石がある。
  3. 一番近い黒石との間がすべて白石である。

Excel関数で表現する

前提

 白石を「1」、黒石を「10」で表現します。Excelなら条件付き書式が使えるので、色も変えられますね! 薄い青は、石が置かれていないマスを表現しています。

01

条件1

 これは簡単です。たとえばセルD5であれば、

D5=""

で判定します。いやいやそこはISBLANK関数だろ?と思う方もいると思いますが、ISBLANKを使うと後で詰みます。

条件2

 たとえば右方向に「10」があるかどうかを判定するには、MATCH関数を使えばいいですね。 セルD5について判定するには、

=MATCH(10,E5:$J5,0)

とします。対象セルとすぐ右から一番右端までをチェックしています。第3引数を「0」にしておくと、一番最初に見つけた(つまり一番近い)位置を返してくれます。

条件3

 セルのすぐ右隣のセルと、条件1のMATCH関数で得たセルの間が、すべて白であることを確認します。そのために使うのは、OFFSET関数とSUM関数です。

=SUM(OFFSET(D5,0,1,1,MATCH(10,E5:$J5,0)-1))

 OFFSET関数は、基準となるセルから、第2・第3引数で起点を決め、第4・第5引数で高さと幅を決めることで、領域を指定することができます。わかりづらいですが、ここでは「対象セルのすぐ右のセルから、一番近い黒石のすぐ左のセルまでの領域」を指定しています。これはつまり、「黒と黒で囲まれた領域」ですよね。その領域がすべて白(「1」で表現される)であれば、領域の数字のSUMは、領域のセル数に一致するはずです。3マスなら、3。

 つまり以下のような判定がTRUEであれば、黒と黒にはさまれた領域はすべて白です。

SUM(OFFSET(D5,0,1,1,MATCH(10,E5:$J5,0)-1))=1*(MATCH(10,E5:$J5,0)-1

 なお、黒を「0」や「-1」にしていないのは、この「一致」の判定でしくるだろうなと思ったためです。

判定

 条件1~3をANDで結ぶだけですね。

=AND(
D5="",
MATCH(10,E5:$J5,0),
SUM(OFFSET(D5,0,1,1,MATCH(10,E5:$J5,0)-1))=1*(MATCH(10,E5:$J5,0)-1)
)

 とてもシンプルに表現することができました。

右方向を判定した盤面

 先の結果を、判定用の盤面全64マスに適用します。
 元の盤面は、判定用盤面の対応位置の判定が「TRUE」であれば、黄色に塗ることにしましょう。こんな感じになります。

02

 まだ「右方向」しか判定できないので、ちょっとさみしいですね。
 次回は、「上下左方向」をどう実装していくか見ていきましょう。