自作カードゲーム用ライブラリ簡易仕様書兼技術的な説明書

どうも!Aaronです。

また気分転換に(僕の中では)がっつりコーディングをして技術負債を作ったので使い方を書いていきます。

コードはここにあります。→https://repl.it/@takumim97/Card-Game

なおこのコードの実装は一部(RnRSでなく)SRFIで議論されている規格に依存しています。特に本質的なものとしてはランダム関数(random-integer)を仮定していますが、これはRnRSの規格に含まれていません。ちょっと調べたところだとSRFI27をサポートしていれば大丈夫っぽいです。

またSchemeは動的型付き言語ですが、「型注釈はドキュメント」なのでコンパイラじゃなく人間に向けた型注釈(注意すべきことに、即ちそれに違反したからと言って直ちにエラーが出るとは限らない)をつけておきます。

 

1.create-deck関数:usInt{a}->( ()->(Union [0...a] |deck_is_empty!\) )

自然数aを引数に受け取り、0からa-1までの「カード」でできた「デッキ」を生成します。

返り値はクロージャー(関数)です。これをこの記事では便宜上drawと呼びます。

drawは「引数を受け取らずに「生成したデッキから1枚引いた結果」を返す」という挙動をします。このとき一度出たカードはデッキに戻さないものとします。

drawを呼び出したとき、「すでにデッキが空になっていた」場合、すなわち既にa回以上drawを呼んでいた場合、にはdeck_is_empty!というシンボルが返されます。

なお複数のdrawを作った場合でもそれらは互いに相関はないですし、「デッキの残りカード」は外から参照されたり書き換えられたりすることはありません。

これは「デッキの状態」を表現する変数がcreate-deckするたびに独立して確保され、その時作成されたdrawのみから参照されるという環境を作るからです。

 

今回のライブラリーは本質的にはこのcreate-deckとdrawを「うまく使う」ことで動いています。

 

2.card-decode:

(Union Int | deck_is_empty!)->(Union (Product (Union ♠ | ♡ | ♢ | ♣ |) | [1...13]) | Joker | deck_is_empty!)

整数aを1つ受け取り対応する「トランプ」を返すか、deck_is_empty!を受け取りdeck_is_empty!を返します。

0≦a<52ならばジョーカー以外の52枚のいずれかに、この範囲以外のaに対してはジョーカーに変換します。

0≦a<52の値に対しては4で割った余りでスートが、4で割った商(+1)で数が決まります。

 

3.create-trump-deck

:usInt->( ()->(Union (Product (Union ♠ | ♡ | ♢ | ♣ |) | [1...13]) | Joker | deck_is_empty!) )

自然数aを受け取り、ジョーカーがa枚だけ入ったトランプのデッキを作ります。

そのほかの注意事項や使用法はcreate-deckと同じです。

内部的にはcreate-deckで作ったdrawから値を引き出してからcard-decodeをかけているだけです。

(余談ですが「トランプ」というのは和製英語で原義は「切り札」という意味なのは有名ですが「なら英語であの『52枚のカード+ジョーカー』という特定のカードセットは何て呼ぶんじゃい?」というのがわからな過ぎたのでこの関数名になってます。)

 

4.create-TCG-deck:

(List (Product Obj | usInt))->Obj

デッキリスト(入っているカードと枚数内訳)」を受け取り、そのデッキを作る。

そのほかの注意事項や使い方はcreate-deckと同様。

 

内部的には実はcreate-trump-deckとある意味大して変わらず、card-decodeに当たる部分をデッキリストから実行時に生成しているだけだったりします。

5.draw-n-times:((()->Obj)×usInt)->IO()

1,3,4などで生成された引数を取らない関数と自然数aを受け取り、関数をa回試行してその結果を標準出力に投げます。

 

6.play-hand:usInt->IO()

create-trump-deckとdraw-n-timesを利用したテキサス・ホールデム形式のポーカー占い/ハンドシミュレーターです。

希望のジョーカーの枚数を選択すると標準入出力で一人ポーカーが始まります。

最初にハンドが配られ、nextと打つとコールが成立してフロップ→ターン→リバーと続きます。

ハンドが弱かったらfoldでおりましょう。

 

※非技術者の方に向けて

上のplay-handは

(play-hand [希望するジョーカーの枚数])

と打って実行するだけで非技術者の方でも遊べます。

また

(define [デッキ名] '([デッキリスト]))

(draw-n-times [デッキ名] [あなたが好きなTCGの初手の枚数])

 

#デッキリストは[([カード名] . 枚数) ([カード名] . 枚数) ...]という形式です(角括弧は外す)。

と打つとデッキの初手チェッカーとして使えます。