読者です 読者をやめる 読者になる 読者になる

type t (* void *)

関数型言語や英語学習の事とか。

OCaml: Tetrisを書いてみる(1)

どうも。ノーマッドと申します。

大学の研究室柄、関数型言語と関わりがあるのですが、特にML系言語が気に入っておりましてReal World OCamlなるものを買って読んでみると、なんだか便利そうなライブラリが使われてるではありませんか。

なんだか友人と一緒に一緒にプログラム書いて競おうぜ、とか言った気がするのでそれを試しにCoreを使って書いてみましょう。

Real World OCaml については http://shop.oreilly.com/product/0636920024743.do

 

 ○何を書くのか

テトリスのシステムから実装と、100個のブロックが落ちてくる問題をよさげに(なるべく点数が高くなるように)解くソルバー。

1.マス目は10×20

2.ネクストのブロックのみ見える(ネクネクは見えない)

3.入力は0から6の数字の文字列txtファイル

数字の対応はウィキペディアにある図 https://ja.wikipedia.org/wiki/%E3%83%86%E3%83%88%E3%83%AA%E3%82%B9

に一致する

4.出力は解いた形がわかるような形式と得点(友人間で任意)

5.得点は

1列 100点

2列 300点

3列 700点

4列 1400点 と決める。面倒なTスピンとかそういうのは存在しない。

6.言語は任意

 

○結果: 途中まで書いた。ただしコードは汚い穢らわしい。

副作用が起きるところと起きないところを分離できていないので凄まじく保守が大変だと思われるがシステム部分をこれ以上いじるつもりはないので良いとする。

気合いが入った時にでも整備しますか…。

 

ソースはこちら https://github.com/tokunomaddojp/tetris

OPAMでインストールしたCore.Stdを用いてプログラミングしております。

 

↓みたいなのがずらずら出力されます このブログのフォントだとレイアウトが崩れてます。

2,1,Box,Std

point:0

__**______

__**______

__@_______

__@_______

__@_______

__@_______

__@_______

__@_______

__@_______

__@_______

__@@______

__@@______

__@_______

__@_______

__@_______

__@_______

__@_______

__@_______

__@_______

__@_______

 

だいたいシステム分かりの処理をモジュールTetrisの集めて、ゲームのルーチンをMainに集めるつもり。で、Solverしか今後触らないつもり。一応自由落下するケースだとテストして動いたからそのつもり。

 

なんだか500行近くソルバーを書く前に書いてしまってヘボプログラマーであることを露呈しているけども、忘れる前にこの戦略を書いておこう。

☆ブロックの表現

基準点を決めて、そこからx,y座標で考えた時にどれくらい距離があるのかをリストで表現。ボックス(2*2のブロック)ならば[(0,0); (1,0); (0,-1); (1,-1)]など

ボックスの場合は回転させても全く形が変わらないが、他のは普通に変わるので、回転させた形それぞれに対してこのような表現を用意する。

ボックスは1種類でいいけど、スティック(1*4)のブロックは2種類、もっと複雑なやつは4種類用意しなきゃいけないんですねめんどくさい。

blockToListでこれを求める。

 

☆置けるかどうかの判定

関数canset で判別している。

1.おこうとしている場所が空

2.その下にあるマス目が少なくともひとつはブロックが存在するか、マス目の端っこ(一番下)

 

ソルバーはまだ書いてないけども、おけるパターンを全列挙するときもこの関数を使おう。

 

☆ソルバーが返すもの

ソルバーは基本的には環境(マス目の状態)、特典、現在のステップ数(何個ブロックを処理したのか)、現在選ばれたブロックを渡して基準点、ブロックとその状態(回転具合)を返す。

この設計だと無理やり3とか渡しても1とかソルバーが無理やり返してしまえばそうなるのでチェックするのを1行加えたほうがいいかもしれないけども。このほうがテストが簡単なのでこのままほっておく。

 

○Core便利・ocamlbuildって?

OCamlの標準ライブラリはむちゃくちゃ貧弱で使い物にならないので汎用的な処理でさえ自分で書く(Or 俺ライブラリを用意する)必要がありましたが、便利ですねこれ。

ただReal World OCamlではビルドするのにocamlbuildを使っていましたが、これの情報がなかなか少なくて困るところ。

実は外からライブラリを持ってきてコンパイルする、というのをOCamlではやったことがないのですがocamlbuild使わなくとも何とかなっちゃうのかしら。makeなら多少勉強したのでそっちが全部片付けば幸せなのですが。

 

次はソルバーを書こう。どうしたものか。