ayaka-k
@ayaka-k (あやか)

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

Ruby ループ処理中の合計値の増減

Q&A

Closed

Ruby スロットゲーム作成 ループ処理中の合計値の増減

Rubyにてスロットゲームを作成しています。
2ループ目以降のコインの合計値を表示させたいです。

現状、1ループごとの計算にしかなっていません。
「残りのコイン数: 100コイン - 入れたコイン数 + 獲得したコイン」

2ループ目以降、前のコイン数を元にした合計値にするためには、
どのようにしたらよいでしょうか?

アドバイスお願い致します。

問題の箇所

puts "-------------"
puts "残りのコイン数:100"

loop do

  select = [5,10,20,"やめとく"]

  #中略(下部に全文記載)

  if ( num2 == 7 ) || ( num5 == 7 )  || ( num8 == 7 )
    puts "-------------"
    puts "おめでとう!真ん中に7の数字があります!"
    puts "100コイン獲得!"
    coin = 100 + 100 - select[putin]
    puts "残りのコイン数:#{coin}"     ←ここで2ループ以降のコイン合計値を表示したい
  elsif (num2 == num5) || (num5 == num8) 
    puts "-------------"
    puts "おめでとう!真ん中が2つが同じ数字になりました!"
    puts "50コイン獲得!"
    coin = 100 + 50 - select[putin]
    puts "残りのコイン数:#{coin}"     ←ここで2ループ以降のコイン合計値を表示したい
  else
    puts "-------------"
    puts "残念!もう一回挑戦しよう!"
    coin = 100 - select[putin]
    puts "残りのコイン数:#{coin}"     ←ここで2ループ以降のコイン合計値を表示したい
  end
end

書いているコード全文

puts "-------------"
puts "残りのコイン数:100"

loop do

  select = [5,10,20,"やめとく"]
  num1 = rand(9)
  num2 = rand(9)
  num3 = rand(9)
  num4 = rand(9)
  num5 = rand(9)
  num6 = rand(9)
  num7 = rand(9)
  num8 = rand(9)
  num9 = rand(9)

  puts "何コイン入れますか?"
  puts "0(5コイン),1(10コイン),2(20コイン),3(やめとく),"
  puts "-------------"
  putin = gets.to_i

  if putin == 3
    puts "またチャレンジしてね!"
    break
  end

  puts "エンターを3回押して数字を揃えよう!" 
  puts = gets
  puts "-------------"
  puts "|#{num1}| | |"
  puts "|#{num2}| | |"
  puts "|#{num3}| | |"
  puts = gets
  puts "-------------"
  puts "|#{num1}|#{num4}| |"
  puts "|#{num2}|#{num5}| |"
  puts "|#{num3}|#{num6}| |"
  puts = gets
  puts "-------------"
  puts "|#{num1}|#{num4}|#{num7}|"
  puts "|#{num2}|#{num5}|#{num8}|"
  puts "|#{num3}|#{num6}|#{num9}|"

  if ( num2 == 7 ) || ( num5 == 7 )  || ( num8 == 7 )
    puts "-------------"
    puts "おめでとう!真ん中に7の数字があります!"
    puts "100コイン獲得!"
    coin = 100 + 100 - select[putin]
    puts "残りのコイン数:#{coin}"
  elsif (num2 == num5) || (num5 == num8) 
    puts "-------------"
    puts "おめでとう!真ん中が2つが同じ数字になりました!"
    puts "50コイン獲得!"
    coin = 100 + 50 - select[putin]
    puts "残りのコイン数:#{coin}"
  else
    puts "-------------"
    puts "残念!もう一回挑戦しよう!"
    coin = 100 - select[putin]
    puts "残りのコイン数:#{coin}"
  end

end
0

3Answer

loop の前に coin = 100 のように,初期値を入れておくのはどうでしょうか?

それと増減の部分も,現在の値を使うように,
coin = coin + 50 - select[putin]
などのような処理にすると良さそうです.

1Like

Comments

  1. @ayaka-k

    Questioner

    初期値をloop の前に入れ、coin = coin +... としたら、
    解決することができました!
    アドバイスありがとうございます!

@atm-snag さんが書かれている通りなのですが、少し補足します。

残りのコインの合計数を変数 coin で表現したいのですよね。

loop do ... enddo ... end はブロックです。ブロック内の変数のスコープは特殊で、ブロックの中で宣言された変数はブロックの中だけで有効です。しかも、ループする場合、ブロックを評価するたびに新しい変数が作られるため、直前の変数の値を保持することができません。

元のコードでは、coin はブロックの中で宣言されているので、繰り返しの後の cion は 直前の coin とは見かけは同じでも別の変数なので、直前のコインの数を保持することができません。

他方で、ブロックの外で宣言された変数は、ブロックの中でも有効です。しかも、ループでブロックを繰り返し評価する場合でも、ブロックの外で宣言された変数は破棄されることがないので、ループ直前の値を保持し続けます。

ブロックの外(loop の前)で coin を宣言すると、変数 coin はループによりブロックを何度評価しても、直前のコインの数をを保持し続けるので、新たな値を足して合計の値を求めることができるのです。

1Like

Comments

  1. @ayaka-k

    Questioner

    補足ありがとうございます!
    loopの前で変数宣言すると、直前の数も含めて計算してくれるのですね。
    非常にわかりやすく理解できたので、別の場面でも使っていきます!

スロットマシーンよくわかりませんが、(5コイン)(10コイン)(20コイン)どれを入れても当たり結果に違いがないのは多く入れるほど損じゃないですか?

slot_machine.rb
class SlotMachine
  WINS = OpenStruct.new(big: :big_win, small: :small_win)
  NUMBER_OF_REELS = 3
  NUMBERS_ON_REEL = 3
  HR = "-" * 10

  def pull
    @reels = []

    NUMBER_OF_REELS.times do
      gets # スロットボタン押下
      @reels << reel_numbers
      display
    end

    return WINS.big if big_win?
    WINS.small if small_win?
  end

  def display
    puts HR
    number_rows.each { |numbers_in_line| puts "|#{numbers_in_line.join("|")}|" }
    puts HR
  end

  private

  attr_reader :reels

  def reel_numbers
    (1..9).to_a.shuffle.take(NUMBERS_ON_REEL)
  end

  def number_rows
    @reels.transpose
  end

  def center_row
    number_rows[1]
  end

  def big_win?
    center_row == [7, 7, 7]
  end

  def small_win?
    center_row.tally.any? { |key, value| value > 1 }
  end
end
game.rb
class Game
  class InputError < StandardError; end
  class ExitError < StandardError; end

  WINS = { SlotMachine::WINS.big => 100, SlotMachine::WINS.small => 50 }
  HR = "-" * 10

  class << self
    def play!(balance = 100)
      game = new(balance)
      slot = SlotMachine.new

      puts HR
      puts "残りのコイン数: #{game.balance}"

      loop do
        begin
          puts "何コイン入れますか?"
          puts game.play_guide_message
          puts "残りのコイン数:#{game.balance}"

          game.play do
            puts "エンターを3回押して数字を揃えよう!"
            slot.pull.tap do |result|
              case result
              when SlotMachine::WINS.big
                puts ""
                puts "おめでとう!真ん中に7の数字があります!"
              when SlotMachine::WINS.small
                puts ""
                puts "おめでとう!真ん中が2つが同じ数字になりました!"
              end

              puts "#{WINS[result]}コイン獲得!" if WINS[result]
              puts ""
            end
          end
        rescue InputError
          retry
        end
      end
    rescue ExitError
      puts "またチャレンジしてね!"
    end
  end

  attr_reader :balance

  def initialize(balance)
    @balance = balance
  end

  def play
    value = choice
    raise ExitError if exit_value?(value)
    raise InputError unless value

    @balance -= value
    @balance += WINS[yield].to_i
  end

  def play_guide_message
    CHOICES
      .collect do |key, value|
        exit_value?(value) ? "#{key}(やめとく)" : "#{key}(#{value}コイン)"
      end
      .join(", ")
  end

  private

  CHOICES = { "0" => 5, "1" => 10, "2" => 20, "3" => :exit }

  def choice
    CHOICES[gets.strip]
  end

  def exit_value?(value)
    value == :exit
  end
end
how_to_play.rb

require "./slot_machine"
require "./game"

Game.play!
1Like

Comments

  1. @ayaka-k

    Questioner

    とても参考になります!
    おっしゃる通り、いくつコインを入れても結果が同じなのは、わたしも気持ち悪いなと思っていました。
    Rubyを学んで1ヶ月程度なので、ここまでで満足してましたが、github 0013さんのようなコードが書ける様にもっと勉強しなければと奮起させられました!
    細かく書いていただいて、とても嬉しいです。
    ありがとうございます!

Your answer might help someone💌