ボドゲ制作するときに使えそうな「3枚のカードの組合せ全網羅リスト」を取得できるプログラムを書きました
セットコレクションのメカニクスを持つゲームを作っていると、任意のカード3枚の全組合せを網羅したリストが欲しくなりませんか? 「別に欲しくない」という人の方が多い気がしますが僕は欲しかったので続けます。
経緯
今作っているゲームは3枚のカードの組合せで戦うのですが、「役」の強さはカードに記載された数字の合計で、3枚の色を揃えているとボーナス点が入るような仕組みになっています。カードは15枚全てがユニークです。
どれくらいの強さの役がどの程度の頻度で出現するかは、通常ならばカードをパターン分けして、高校の数学で習う「場合の数」なんかを駆使してスマートに出したりするのでしょう。けれど、パターン自体が一定以上多くなってくるともはや絶対間違える全パターン作って出現率を弾いた方が楽だったりします。(※表計算ソフトが扱える程度のパターン数であれば)
全パターンが手に入ってしまえば、それぞれのカードのパラメータを展開して前述のボーナスなどを加味した点数を計算するのは楽勝です。今回は15C3=455パターンしかないことも分かっているので安心です。
結果
というわけで早速書いたコードがこちら。
1年振りくらいにコーディングしましたhttps://t.co/VOkPbweKme https://t.co/gRjh0VwSjZ pic.twitter.com/dA25aGiwCH
— かく🎲遊陽ゲームズ (@SusabiG) 2020年7月20日
コピペできるようにコードも貼っておきます。このコードはそのまま Go Playground で実行して結果を取得できます。
また、A~O の文字列がカード一枚一枚に対応しています。この要素リストを増減させればカードの総枚数(種類数)を調整できます。
package main import ( "fmt" "sort" ) func main() { // 結果を格納する連想配列 result := make(map[string]int,0) // 15個数の要素のリスト list := [...] string{"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O"} // 1枚目のドロー for i, _ := range [15]int{} { // 2枚目のドロー for j, _ := range [15]int{} { // 1枚目と2枚目が同じならスキップ if (i==j) { continue } // 3枚目のドロー for k, _ := range [15]int{} { // 1枚目と3枚目、2枚目と3枚目が同じならスキップ if (k==i || k==j) { continue } // 文字列をソート arr := [] string { list[i], list[j], list[k] } sort.Slice(arr, func(l, n int) bool { return arr[l] < arr[n] }) // 文字列を結合 str := arr[0] + arr[1] + arr[2] // 連想配列に入れる if _, ok := result[str]; ok { // 既に入っていたら抜ける continue } result[str] = 1 } } } // 結果出力 fmt.Printf("要素数: %d\n",len(result)) fmt.Println("===== 以下、生成結果 =====") for key, _ := range result { fmt.Println(key) } }
出力結果が以下のように三文字のアルファベットで出るので、予め作っておいたアルファベットとカードの対応表を使えばデータを加工していけます。
エクセルやスプレッドシートで頑張る場合
実はプログラム書く前に一度スプレッドシートを駆使して欲しいリストを得ることができていました。
15枚のユニークカードから3枚選ぶ15C3パターンのリストを作った。
— かく🎲遊陽ゲームズ@ゲムマ秋両日 (@SusabiG) 2020年7月19日
①15枚に15進数の各値を割り振る
➁15x15x15パターンの総当たりリストを作成
③リストの文字列を1文字ずつ分解して昇順ソート
④3文字中2文字が同値の行削除
⑤重複パターンを削除
無事455行を抽出。
参考 https://t.co/JOs4rxElM8
何やらテクニカルなことをしてリストを生成していますが、説明は省きます。ちなみにデータの加工がすごくめんどくさかったのでオススメしません。
まとめ
3枚の組合せ全網羅リストを取得するプログラムを作りました。15枚のユニークカードを前提としたプログラムになっていますが、要素リストの行を書き換えることで枚数は調整できます。
3枚のセットコレクションはかなりたくさんのゲームで使われている仕組みですし、今後もそういうゲームが多く生まれるのではないでしょうか。そんなゲームを作るときには、このブログ記事を思い出して前述のプログラムをぶん回してもらえば良いかと思います。
一応、個人利用の範囲内で使って頂き、使ってお役に立てたならこの記事についてツイートしたりメンションくれたりするとぼくが喜びます。