Rubyでチンチロゲームを作る 　第3回　賭け金の移動

# 1.はじめに
　今回は勝敗結果と役に基づいて賭け金を移動させるメソッドを書きます。カイジのチンチロは役とその倍率は以下のようになっています。

| 役 | 倍率 |
|----|----|
|ピンゾロ (1,1,1)| 5倍づけ|
|ゾロ目 (2~6)| 3倍づけ|
|シゴロ (4,5,6)| 2倍づけ|
|通常の目 (3個中2個がおなじ目)| 1倍づけ|
|目なし | 1倍払い|
|ヒフミ(1,2,3)|2倍払い|

〜づけというのは買った場合に賭け金の◯倍で返ってくるという意味です。〜払いというのは負けた場合にマイナスになります。


# 2. メソッドの作成
　メソッドを作成します。引数は相手と自分の役、賭け金、勝敗結果となります。前回の記事と同様に、クラスのなかにメソッドを作成します。そのため引数は以下のようになります。

```ruby
def transfer_money(opponent,win_or_lose)
 # 相手の役     : opponent.hand
 # 相手の賭け金  : opponent.bet_money
 # 自分の役　　  : @hand 
 # 自分の賭け金　: @bet_money
 # 勝敗結果     : win_or_lose
```

　以下、とりあえず作ってみます。

```ruby
def transfer_money(opponent,win_or_lose)
  
    strength_relationship = [
      'ヒフミ','目なし',
      '通常の目(1)','通常の目(2)','通常の目(3)',
      '通常の目(4)','通常の目(5)','通常の目(6)',
      'シゴロ','ゾロ目','ピンゾロ'
    ]
    dividend_table = [
      -2,-1,
      1,1,1,
      1,1,1,
      2,3,5
    ]
    my_hand_rank = strength_relationship.index(@hand)
    opponent_hand_rank = strength_relationship.index(opponent.hand)
    my_dividend_ratio = dividend_table[my_hand_rank]
    opponent_dividend_ratio = dividend_table[opponent_hand_rank]
    move_money = 0
    
    case win_or_lose
    when '勝ち'
      move_money = my_dividend_ratio * bet_money
    when '引き分け'
      move_money = 0
    when '負け'
      move_money = - opponent_dividend_ratio * opponent.bet_money
    end

    puts <<~TEXT
    自分： #{@hand} / 相手： #{opponent.hand} / #{win_or_lose} ... #{move_money}ペリカ
    TEXT
    move_money

  end
```

　自分と相手の役を調べて、それぞれを`dividend_table`　から持ってきます。勝敗結果に基づいて`move_money`の値を計算します。 負けた場合はマイナスになります。

　ちょっとメソッドを使ってみましょう。クラスの外に以下の内容を書きます。

```ruby
player_A = Player.new(money:1000,bet_money:100,hand:'ピンゾロ',name:'カイジ')
player_B = Player.new(money:3000,bet_money:300,hand:'目なし',name:'班長')
player_A.transfer_money(player_B,'勝ち')
```

　実行します。実行結果は以下のようになります。

```terminal
自分： ピンゾロ / 相手： 目なし / 勝ち ... 500ペリカ
```

　賭け金100ペリカに対して5倍付の500ペリカ。問題ありませんね。それではこれはどうでしょうか。

```ruby
player_A = Player.new(money:1000,bet_money:100,hand:'ヒフミ',name:'カイジ')
player_B = Player.new(money:3000,bet_money:300,hand:'通常の目(2)',name:'班長')
player_A.transfer_money(player_B,'負け')
```

```terminal
自分： ヒフミ / 相手： 通常の目(2) / 負け ... -300ペリカ
```
あれ？2倍払いではなく、3倍払いになっていますね。　さらにこれはどうでしょうか。

```ruby
player_A = Player.new(money:1000,bet_money:100,hand:'ヒフミ',name:'カイジ')
player_B = Player.new(money:3000,bet_money:300,hand:'目なし',name:'班長')
player_A.transfer_money(player_B,'負け')
```

```terminal
自分： ヒフミ / 相手： 目なし / 負け ... 300ペリカ
```
む？　ヒフミで負けたのにペリカがプラスになってしまいますね。


# 3. メソッドの修正（例外処理）
　ヒフミと目なしはちょっと特殊な役なので、相手の役によっては賭け金の計算がふつうのものと異なります。以下に表を書きます。

|自分|相手|勝敗|オッズ|
|---|---|---|---|
|ヒフミ|目なし |負け　|2倍払い |
|ヒフミ|シゴロ |負け　|2倍払い |
|ヒフミ|ゾロ目 |負け　|3倍払い |
|ヒフミ|ピンゾロ |負け　|5倍払い |
|目なし |ヒフミ|勝ち　|2倍づけ |
|シゴロ|ヒフミ |勝ち　|2倍づけ |
|ゾロ目|ヒフミ |勝ち　|3倍づけ |
|ピンゾロ|ヒフミ |勝ち　|5倍づけ |

　これを踏まえて例外をメソッドに加えます。

```ruby
    # ....略
    move_money = 0
    if @hand == 'ヒフミ' || opponent.hand == 'ヒフミ' then
      if @hand == 'ヒフミ' && (opponent.hand != 'シゴロ' && opponent.hand != 'ゾロ目' && opponent.hand != 'ピンゾロ') then
        opponent_dividend_ratio = 2
      end
      if @hand == '目なし' && (opponent.hand == 'ヒフミ') then
        my_dividend_ratio = 2
      end
      if (@hand != 'シゴロ' && @hand != 'ゾロ目' && @hand != 'ピンゾロ') && opponent.hand  == 'ヒフミ' then
        opponent_dividend_ratio = 2
        my_dividend_ratio = 2
      end
    end
    
    case win_or_lose
    # ....略
```

これでOK。次にテストをしてみましょう。

# 4.テスト

　テストコードを書きます。

```ruby
require 'minitest/autorun'
require './lib/transfer_money'
class DiceTest < Minitest::Test
  def test_transfer_money
    roll_map = [
      'ヒフミ','目なし',
      '通常の目(1)','通常の目(2)','通常の目(3)',
      '通常の目(4)','通常の目(5)','通常の目(6)',
      'シゴロ','ゾロ目','ピンゾロ'
    ]

    win_lose_map = [
      ['引き分け','負け','負け','負け','負け','負け','負け','負け','負け','負け','負け'],
      ['勝ち','引き分け','負け','負け','負け','負け','負け','負け','負け','負け','負け'],
      ['勝ち','勝ち','引き分け','負け','負け','負け','負け','負け','負け','負け','負け'],
      ['勝ち','勝ち','勝ち','引き分け','負け','負け','負け','負け','負け','負け','負け'],
      ['勝ち','勝ち','勝ち','勝ち','引き分け','負け','負け','負け','負け','負け','負け'],
      ['勝ち','勝ち','勝ち','勝ち','勝ち','引き分け','負け','負け','負け','負け','負け'],
      ['勝ち','勝ち','勝ち','勝ち','勝ち','勝ち','引き分け','負け','負け','負け','負け'],
      ['勝ち','勝ち','勝ち','勝ち','勝ち','勝ち','勝ち','引き分け','負け','負け','負け'],
      ['勝ち','勝ち','勝ち','勝ち','勝ち','勝ち','勝ち','勝ち','引き分け','負け','負け'],
      ['勝ち','勝ち','勝ち','勝ち','勝ち','勝ち','勝ち','勝ち','勝ち','引き分け','負け'],
      ['勝ち','勝ち','勝ち','勝ち','勝ち','勝ち','勝ち','勝ち','勝ち','勝ち','引き分け']
    ]
    bet_map = [
      [0,-2,-2,-2,-2,-2,-2,-2,-2,-3,-5],
      [2,0,-1,-1,-1,-1,-1,-1,-2,-3,-5],
      [2,1,0,-1,-1,-1,-1,-1,-2,-3,-5],
      [2,1,1,0,-1,-1,-1,-1,-2,-3,-5],
      [2,1,1,1,0,-1,-1,-1,-2,-3,-5],
      [2,1,1,1,1,0,-1,-1,-2,-3,-5],
      [2,1,1,1,1,1,0,-1,-2,-3,-5],
      [2,1,1,1,1,1,1,0,-2,-3,-5],
      [2,2,2,2,2,2,2,2,0,-3,-5],
      [3,3,3,3,3,3,3,3,3,0,-5],
      [5,5,5,5,5,5,5,5,5,5,0]
    ]
    player_A = Player.new(money:1000,bet_money:100,hand:'目なし',name:'カイジ')
    player_B = Player.new(money:1000,bet_money:300,hand:'目なし',name:'班長')
    new_bet_map = bet_map.map { |x|
      x.map { |y| 
        if y > 0
          y * player_A.bet_money
        elsif y < 0
          y * player_B.bet_money
        else
          y = 0
        end
      }
    }

    roll_map.each_with_index do |value_1,i|
      player_A.hand = value_1
      roll_map.each_with_index do |value_2,j|
        player_B.hand = value_2
        assert_equal new_bet_map[i][j], player_A.transfer_money(player_B,win_lose_map[i][j])
      end
    end

  end
end

```

 `each_with_index`　を二回重ねることでfor文を二回回すのと同じ構造にしています。また、`map`を二回重ねて二次元配列に賭け金をかけています。

　これでテストが通りました。


# 5. おわりに
　これでチンチロのおおまかな機能をつくることができました。次回はゲーム進行にかかわる諸々の処理をつくります。あと記事2つくらいで終わりそうです！
　
　コードは以下に追記していきます。

https://github.com/kyokucho1989/ruby-game