質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.23%

ruby, 繰り返しの繰り返し, メソット?クラス?,マーチンゲール法,シミュレーション

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 696

wpx-vv1uZ

score 23

前提・実現したいこと

マーチンゲール法のシミュレーションをrubyでやろうとしています

[1つ目の作業]
所持金・賭ける金額・目標金額を設定します。
所持金が賭ける金額に足りなくなるか、目標金額に達したら処理を終わります

処理が終わった時点で出た所持金を、
・目標金額に達した
・掛け金に足りなくなったが所持金は増えた
・負けた
に分けて、それぞれの回数をカウントします
[2つ目の作業]
上の作業を何回繰り返すか指定します。
最後に
・目標金額に達した
・掛け金に足りなくなったが所持金は増えた
・負けた
の確立をそれぞれ出します

[賭けのルール]
赤と黒のみのルーレットを想定
指定した色なら勝ち、違うなら負け
・勝った場合
掛け金+1000を所持金に足す
掛け金を一番最初の額に戻す
・負けた場合
掛け金を所持金から引く
掛け金を二倍にする

発生している問題・エラーメッセージ

処理の繋げ方が分かりません

該当のソースコード

print "所持金を入力してください:"
x = gets.chomp.to_i
w = x
print "最初の掛け金を入力してください:"
y = gets.chomp.to_i
u = y
print "目標金額を入力してください:"
z = gets.chomp.to_i
print "試行回数を入力してください:"
n = gets.chomp.to_i
a = 0 #目標達成
b = 0 #目標未達成かつ勝ち
c = 0 #負け

  until w < u || w >= z do
    roulette = rand(2)
    i_choice = rand(2)
    if roulette == i_choice
      w += u + 1000
      u = y
    else
      w -= u
      u *= 2
    end
  end
# n.times do 
  if w >= z
    a += 1
  elsif w < z and w > x
    b += 1
  else
    c += 1
  end
# end

  print "目標達成した回数:", a, "\n"
  print "確率:", a/n.to_f, "\n"

  print "目標未達成かつ勝った回数:", b, "\n"
  print "確率:", b/n.to_f, "\n"

  print "負けた回数:", c, "\n"
  print "確率:", c/n.to_f, "\n"

試したこと

defとして2つの作業を作るのかと思いましたが、知識が足りなくて上手くいきませんでした
どのように書けば良いでしょうか?

また、今回のようなケースで参考にしたら良い記事などあれば教えてください
よろしくお願いします

補足情報(FW/ツールのバージョンなど)

=begin[賭けのルール]
赤と黒のみのルーレットを想定
指定した色なら勝ち、違うなら負け
・勝った場合
掛け金+1000を所持金に足す
掛け金を一番最初の額に戻す
・負けた場合
掛け金を所持金から引く
掛け金を二倍にする
=end
class Roulette 
  x = 0
  y = 0
  u = y
  z = 0 
  roulette = rand(2)
  i_choice = rand(2)
  if roulette == i_choice
    x += u + 1000
    u = y
  else
    w -= u
    u *= 2
  end
end

  # 初期設定を入力
x,y,z = gets.split.map(&:to_i)
#x:所持金、y:掛け金、z:目標金額

# 試行回数を入力
n = gets.to_i
#インスタンス変数として掛け金と所持金をもち賭けを実行するメソッド
def roulette.bet
  @u = x
  @v = y
  return do roulette
end
#所持金を返すメソッド
def roulette.money
  return x
end
#続行可能かを判定するメソッド
def roulette.continue?
  return x >= y and x < z
end

結果 = {"目標達成": 0,"増加": 0, "敗北": 0}
n.times{
  roulette = Roulette.new(x, y)  
  roulette.bet while roulette.money < z && roulette.continue?
  if roulette.money >= 目標金額
    結果[:"目標達成"] += 1
  elsif roulette.money >= 所持金
    結果[:"増加"] += 1
  else
    結果[:"敗北"] += 1
  end
}
# 結果を表示して終了
a = 目標達成/n
b = 増加/n 
c = 敗北/n 


回答を参考に考えをまとめました。文法は間違いだらけです
どこから手をつければ良いでしょうか?

print "所持金を入力してください:"
x = gets.chomp.to_i
v = x
print "最初の掛け金を入力してください:"
y = gets.chomp.to_i
u = y
print "目標金額を入力してください:"
z = gets.chomp.to_i

print "試行回数を入力してください:"
n = gets.chomp.to_i

i = 0
a = 0
b = 0
c = 0

n.times do
until v < u || v >= z do
  i += 1
  roulette = rand(2)
  i_choice = rand(2)
  if roulette == i_choice
    v += u + 1000
    u = y
  else
    v -= u
    u *= 2
  end
end

if v >= z
  a += 1
elsif v < u and v >= x
  b += 1
else
  c += 1
end
end

puts [a,b,c]


最初に書いたコードがこれでした
このコードだと、[a,b,c]のどれか1つに試行結果がいってしまうので何か間違いがあるのはわかるのですが、具体的な所が分かりません。
何がいけないのでしょうか?

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+1

とりあえず、考え方だけ

まず

[賭けのルール]
赤と黒のみのルーレットを想定
指定した色なら勝ち、違うなら負け
・勝った場合
掛け金+1000を所持金に足す
掛け金を一番最初の額に戻す
・負けた場合
掛け金を所持金から引く
掛け金を二倍にする

は、ちょっと複雑な状態を持っているので
クラスとして実装するとよいでしょう。

インスタンス変数として掛け金と所持金をもち
賭けを実行するメソッド
続行可能かを判定するメソッド
所持金を返すメソッド
が必要かな

そうすると

# 初期設定を入力
所持金,賭け金,目標金額 = gets.split.map(&:to_i)

# 試行回数を入力
試行回数= gets.to_i

結果 = {"目標達成": 0,"増加": 0, "敗北": 0}
試行回数.times{
  roulette = Roulette.new(所持金, 賭け金)  
  roulette.bet while roulette.money < 目標金額 && roulette.continue?
  if roulette.money >= 目標金額
    結果[:"目標達成"] += 1
  elsif roulette.money >= 所持金
    結果[:"増加"] += 1
  else
    結果[:"敗北"] += 1
  end
}
# 結果を表示して終了

ざっとこんな感じ
Rouletteクラスは自分で実装してみてください


ルーレットクラスを実装すると

# [賭けのルール]
# 赤と黒のみのルーレットを想定
# 指定した色なら勝ち、違うなら負け
# ・勝った場合
# 掛け金+1000を所持金に足す
# 掛け金を一番最初の額に戻す
# ・負けた場合
# 掛け金を所持金から引く
# 掛け金を二倍にする
class Roulette
  # 初期化
  def initialize(初期所持金, 初期掛け金)
    @money = 初期所持金
    @initial_bet = @bet = 初期掛け金
  end

  # 現在の所持金
  # 省略すると、「attr_reader :money」だけになる
  def money
    @money
  end

  # 賭けが続けられるか判定する
  def continue?
    @money >= @bet
  end

  # 賭けを実行する
  def bet
    mychoice = [:red, :black].sample
    roulette = [:red, :black].sample

    if mychoice == roulette
      @money += @bet+1000
      @bet = @initial_bet
    else
      @money -= @bet
      @bet *= 2
    end
  end
end

まぁこんなん

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/05/24 23:08

    回答ありがとうございます
    頑張って考えてみます

    キャンセル

  • 2019/05/24 23:49

    不躾ですみません
    自分が知識不足なだけなのですが、まだ勉強を始めたばかりでdefやclassの作り方をあまりわかっていません。
    もう少し詳しい回答を頂けないでしょうか。
    お時間があればよろしくお願いします

    キャンセル

  • 2019/05/25 00:57

    回答ありがとうございます
    class,def,インスタンス変数,グローバル変数,など知らない知識も多いのでこれから勉強していこうと思います
    お付き合い頂きありがとうございました

    キャンセル

0

print "所持金を入力してください:"
x = gets.chomp.to_i
v = x
print "最初の掛け金を入力してください:"
y = gets.chomp.to_i
u = y
print "目標金額を入力してください:"
z = gets.chomp.to_i

print "試行回数を入力してください:"
n = gets.chomp.to_i

i = 0
a = 0
b = 0
c = 0

n.times do
until v < u || v >= z do
  i += 1
  roulette = rand(2)
  i_choice = rand(2)
  if roulette == i_choice
    v += u + 1000
    u = y
  else
    v -= u
    u *= 2
  end
end

if v >= z
  a += 1
elsif v < u and v >= x
  b += 1
else
  c += 1
end
  v = x
  u = y
end


puts [a,b,c]


最後に使った変数v,u,の初期化を忘れていました
これで合っているでしょうか?

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/05/25 01:58

    あっているような気はします。
    1週間後の自分が読んだ時に悩まない程度の変数名をつけるとよいでしょう。

    キャンセル

  • 2019/05/25 08:43

    コメントありがとうございます
    そのようにしようと思います

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.23%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る