honapon
@honapon

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

【🔰初心者】Rubyでのじゃんけん・あっち向いてホイアプリの作成

Q&A

Closed

解決したいこと

Rubyにてじゃんけん+あっち向いてホイを行うアプリを作っています。
じゃんけん終了後のあっち向いてホイにおいて以下のようにコードを書こうと考えています。
①じゃんけん勝ち→相手と同じ方向を選択した場合は勝ち。
②じゃんけん負け→相手と同じ方向を選択した場合は負け。
③ ①、②に該当しない場合はあっち向いてホイを繰り返す
 じゃんけん部分で定義した「case_pattern」(勝ち、負けのパターンに分けました)
を用いてあっち向いてホイのコードを書こうと思いましたが、以下のエラーが出てしまいました。
この先のコードの書き方について教えて頂けると嬉しいです。

※(janken)メソッドで定義したものを使おうとしているのが原因なのかな?と思い、変数を工夫した方が良いのか構造を変えたほうが良いのかと考えましたが、解決に辿り着くことができません。

発生している問題・エラー

 undefined local variable or method `case_pattern' for main:Object (NameError)

例)

NameError (uninitialized constant World)

該当するソースコード

  require "csv" 
   puts"------------------------------"
   puts"あっち向いてホイゲームを始めます。"
 def janken
   puts "じゃんけん・・・" 
   puts "0(グー)1(チョキ)2(パー)3(戦わない)"
   select_number = gets.to_i
   random_number = rand(3)
   case_pattern =""

  jankens = ["グー","チョキ","パー","戦わない"]
   puts "あなた:#{jankens[select_number]} 相手:#{jankens[random_number]}"
   puts"------------------------------"

  if  select_number == random_number
    puts "あいこです。もう一度じゃんけんをします。"
   return true
  elsif select_number ==3 || random_number == 3
    puts"じゃんけんが放棄されました。ゲームを終了します。"
   return false
  elsif select_number - random_number = 1 || -2
    puts"じゃんけんに負けました。あっちむいて・・・"
    case_pattern = "じゃんけん負けパターン"
   return false
  elsif select_number - random_number = -1 || 2
    puts "じゃんけんに勝ちました。あっちむいて・・・"
    case_pattern = "じゃんけん勝ちパターン"
   return false
  end
 end

 next_game = true
 while next_game do
 next_game = janken
 end

 puts "0(上)1(下)2(左)3(右)"
 select_number2 = gets.to_i
 random_number2 =rand(3)
 directions = ["上","下","左","右"]
  puts "あなた:#{directions[select_number2]} 相手:#{directions[random_number2]}"
  puts"------------------------------"

# この辺りから間違えていると思います(本当は以下のように条件を作りたいのですが・・・) 
 case case_pattern
 when"じゃんけん勝ちパターン" || select_number == random_number then
  puts "あなたの勝ちです。"
 end
0

1Answer

case_patternは、関数janken内のローカル変数です。関数の外からは参照できません。

def janken
    case_pattern = 1
    puts case_pattern #=> 1
end

# ↓のcase_patternは未定義
puts case_pattern

変数のスコープについて学習することをお勧めします。

と言っても、この場合は勝敗あいこを戻り値にする方が無難だと思います。


また、「=」は代入であり、比較は「==」です。
if select_number - random_number == 1

「||」は「または」という意味として扱われますが、結ぶのは「条件式」です。
if number == 1 || -2
【「number == 1」または「-2」】となります。
正しくは
if number == 1 || number == -2
と書く必要があります。
(「if 数値」はtrueになってしまいます)


細かいところですが、あいこの条件に二人とも放棄した場合もヒットしてしまうので、
放棄とあいこの条件を入れ替えるとベターだと思います。

参考になるかはわかりませんが、別の書き方をしてみました。

require "csv" 
puts"あっち向いてホイゲームを始めます。"

def janken
	puts "じゃんけん・・・" 
	puts "0(グー)1(チョキ)2(パー)3(戦わない)"
	select_number = gets.to_i
	if !(select_number == 0 || select_number == 1 || select_number == 2)
		select_number = 3
	end

	random_number = rand(3)
	case_pattern = 0

	jankens = ["グー","チョキ","パー","戦わない"]
	puts "あなた:#{jankens[select_number]} 相手:#{jankens[random_number]}"
	puts"------------------------------"

	if select_number == 3 || random_number == 3
		puts"じゃんけんが放棄されました。ゲームを終了します。"
		case_pattern = 3
	else
		number = select_number - random_number
		case number
			when 0 then
				puts "あいこです。もう一度じゃんけんをします。"
				case_pattern = janken
			when 1, -2 then
				puts"じゃんけんに負けました。あっちむいて・・・"
				case_pattern = 2
			when -1, 2 then
				puts "じゃんけんに勝ちました。あっちむいて・・・"
				case_pattern = 1
		end
	end
end

if result = janken == 3
	return
end

puts "0(上)1(下)2(左)3(右)"
select_number2 = gets.to_i
random_number2 = rand(3)
directions = ["上","下","左","右"]
puts "あなた:#{directions[select_number2]} 相手:#{directions[random_number2]}"
puts"------------------------------"

# この辺りから間違えていると思います(本当は以下のように条件を作りたいのですが・・・) 
case result
	when "じゃんけん勝ちパターン" || select_number == random_number then
	puts "あなたの勝ちです。"
end	
1Like

Comments

  1. @honapon

    Questioner

    元の考えを生かして丁寧にお答え頂き、本当にありがとうございます!!
    if result = janken == 3 return end の部分について、とても大切なcase_patternについての条件文かと思うのですが、この文が意味することが中々分からずにいます・・・。returnなので戻り値をどこに返しているのか、こちらの意味を教えていただきたいです( ; ; )
  2. @honapon

    Questioner

    あっち向いてホイの不明点が出てきたのですが、そちらについては別に投稿をさせて頂きます^^
  3. rubyの戻り値は実は省略することが可能です。
    「メソッドの最後に記述した式が戻り値になる」というものです。
    この場合、ifで分岐こそしていますが、case_patternが戻り値になります。
    return case_pattern

    if result = janken == 3 についてですが、誤りがあったので
    if (result = janken) == 3 と訂正します。すみません。
    単に代入と評価を一行にしただけですが、行数が減る以外にあまりまとめて書く利点はないので、
    result = janken
    if result == 3
    と分けて書いた方がいいですね。

    正直whileをなくして再帰的にjankenを呼び出したのは趣味の範疇なので、whileでいいと思います。
    case whenとif elsif の使い分けも(今回のように比較値が少ない場合は)好みでいいです。
  4. @honapon

    Questioner

    とても分かりやすく解説して頂き、ありがとうございます!こんな書き方もあるんだと驚きの連続です・・・。いつかこういったコードが書けるようになりたいので、少しずつ前進したいと思います。ありがとうございます♪好みで良い部分があるんですね^^
  5. 「今回の処理は特別重たくなるようなものではないので、細かく気にしなくていい」というレベルのものなので、何万回もループする処理の場合の再帰処理は、処理速度が落ちたり、メモリ不足(OutOfMemoryError)になる可能性が高いです。

    case whenとif elsifも、case(他の言語だとswitch)の方が処理が速いと言われることもあります。
    また、AND条件ならifでいいかもしれませんが、
    if a == 1 || a == 2 || a == 4 || a == 9
    よりは
    case a
    when 1, 2, 4, 9 then
    の方が圧倒的に見やすい等、「可読性」も考えるといいと思います。
    ここでは触れませんでしたが、別の質問の方ではすでに他の方が回答されていた通り、メソッドに分割するというのも可読性です。

Your answer might help someone💌