Rプログラミング入門 14回目
これからの数回は、スロットマシンのシミュレーターをRで作成する過程を通じて、
これらを学んでいきます。
- プログラムの設計方法
- 分岐処理の書き方
- 反復処理の書き方
- ルックアップテーブルの作り方、使い方
- S3メソッドの使い方
ちなみに、スロットマシンのモデルはこれ。
Journal of Statistics Education, V3N2: Braun
(本にも記載してありますが、1ドルに対しての払い戻し率に色々とあった模様)
ゴール
play関数を呼ぶと、下の2つが表示される事を目指します。
- シンボル
- 賞金
> play() B 0 BBB $0
プログラムの設計方法
どんなプログラミング言語でも同じですが、ルールや目的など、
プログラミングをする前に、決めないといけません。
スロットマシンが提供するシンボルはこちらです。
> symbols [1] "DD" "7" "BBB" "BB" "B" "C" "0"
スロットマシンは、これらに該当する時に賞金が得られます。
- 同じシンボルが3つ揃った時(ゼロ3つは除く)
- 3つのバー(さまざまな種類のバーが混ざっていても良い)
- 1個以上のチェリー
この時点で、分岐使わないとできない空気を出してきます。
さらに、()内にHogeHoge書いてあるのも嫌なところです。
そして、賞金はシンボルの組み合わせによって決まります。
combos prize 1 DD DD DD 100 2 7 7 7 80 3 BBB BBB BBB 40 4 BB BB BB 20 5 B B B 10 6 C C C 10 7 any Bar Combos 5 8 C C * 5 9 C * C 5 10 * C C 5 11 C * * 5 12 * C * 5 13 * * C 5
また、組み合わせ中にダイヤ(=DD)が含まれていると、賞金が倍になります。
例として、"7 7 7"は80ですが、"7 7 DD"は160、"7 DD DD"は320のような形です。
全て"DD"だと、100の倍、倍、倍なので800です。
これらをプログラミングしていくのですが、Rを用いる場合には
この2種類に分割して考えを進めていけば良さそうです。
- 順次的なステップ
- 並列するケース
順次的なステップ
まず、プログラムの骨子を行わせたい事の順序に沿って決めます。
それから、その骨子部分をより単純な問題に分割することを考えていきます。。
スロットマシンの骨子はこちらです。
- シンボルの生成
- シンボルの表示
- シンボルのスコア計算
それをブログラムにしたのがこちら。
play <- function(){ # ステップ1: シンボルの生成 symbols <- get_symbols() # ステップ2:シンボルの表示 print(symbols) # ステップ3:シンボルのスコア計算 score(symbols) }
play関数内で、呼んでいるget_symbols関数やscore関数はまだ作成していません。
print関数は、ジェネリック関数と呼び、base環境に存在する関数です。
> print function (x, ...) UseMethod("print") <bytecode: 0x00000000126da340> <environment: namespace:base>
get_symbols関数を作成します。
この関数は、シンボルの中からランダムに3種類抽出すれば良いです。
get_symbols <- function(){ wheel <- c("DD","7","BBB","BB","B","C","0") sample(wheel, size = 3, replace = TRUE, prob = c(0.03, 0.03, 0.06,0.1,0.25,0.01,0.52) ) }
sample関数は、過去記事でも触れていますので割愛します。
それぞれのシンボルの確立ですが、実際のスロットマシンと同じ確率が用いられています。
次に、複雑に条件分岐が発生しそうなscore関数に踏み込んでいきます。
並列するケース
score関数は、上に書かれているルールに沿って、賞金を計算します。
ルールをまとめると、こうなります。(それぞれが独立している条件です。)
- 同じ種類のシンボルが3つ:賞金のルックアップ
- すべてバー:5ドル
- 上記以外:チェリーの数を数える
それから上の結果を受けて、ダイヤによる調整を行います。
if文 else文
上の並列するケースを記載するには、if~else文を利用します。
使い方は、C#と同じように、このような形です。
もっぱら、C#ではif文は極力記載しないように逃げます。こいつですね。
Specification pattern in C# - CodeProject
sampleIf <- function(a,b){ if(a > b){ print("A wins!") }else if(a < b){ print("B Wins!") }else{ print("Tie.") } }
> sampleIf(1,1) [1] "Tie." > sampleIf(2,1) [1] "A wins!" > sampleIf(1,2) [1] "B Wins!"
また、Rのif~else文は、ショートサーキットです。
条件式に複数の論理式が結合されている場合、1番目の条件式から評価を行い
条件に該当しない場合は、2番目の条件式を評価しません。
このような関数があったとします。
sampleIf <- function(a,b){ if(a > 10 && a > b){ print("A Wins!") }else{ print("B Wins!") } }
これは、a > b条件を評価することなく、else側に流れます。
> sampleIf(2 , 1) [1] "B Wins!"
これは、a > 10の条件を満たし、a > bを評価しましたがFALSEのため、
else側に流れます。
> sampleIf(11 , 12) [1] "B Wins!"
if~else文の使い方が分かったので、score関数の作成に取り掛かりますが、
それは、次回の記事にします。