2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

数当てゲームの練習2(Hit&Blow)

Last updated at Posted at 2015-02-20

#問題

これはn桁の数を探すゲームです。
適当な数を入れると桁も数字もあっていれば「Hit」としその個数が、
数字はあっているが桁が異なっていれば「Blow」としてその個数が出力されます。
それを繰り返すことで答えを探すことができます。
このゲームを作成しなさい。
答えの数は乱数を使って毎回別の答えを用意しましょう。

こちらのサイトから引用

#解答

hit_blow.rb
# 桁数を設定(問題の仕様上、最大は10桁)
# 今回は例に従い4桁
DIGIT_NUMBER = 4

# 正解の数を乱数で生成するメソッド
# 正解の数は各桁の数字が異ならなければならない
# 返り値:生成されたn桁の乱数
def make_answer_number
  # 正解の数が生成できたか調べるフラグ
  answer_number_flag = false
  
  # 各桁の数が異なる数が生成されるまで無限ループ
  while !answer_number_flag
    # フラグは最初はtrue
    answer_number_flag = true
    
    # 正解の数を生成
    # 正解の数は10^(n-1)〜(10^n)-1の数
    rand_number = rand((10**(DIGIT_NUMBER - 1))..((10**DIGIT_NUMBER) - 1))
    
    # return用の変数
    return_answer_number = rand_number
    
    # 各桁の数を格納する配列
    rand_number_array = []
    
    # 各桁の数を配列に格納
    DIGIT_NUMBER.times do
      rand_number_array.push(rand_number % 10)
      rand_number /= 10
    end
    
    # 各桁の数が異なっているか調べる
    rand_number_array.each_with_index do |digit_number, index|
      (index + 1).upto(rand_number_array.length - 1) do |upto_times|
        if digit_number == rand_number_array[upto_times]
          answer_number_flag = false
        end
      end
    end
  end
  
  return_answer_number
end

# ゲーム説明を表示するメソッド
def show_rule
  puts "数当てゲームを行います"
  puts "これは#{DIGIT_NUMBER}桁の数を探すゲームです"
  puts "適当な数を入れると桁も数字もあっていれば「hit」としその個数が、"
  puts "数字はあっているが桁が異なっていれば「blow」としてその個数が出力されます"
  puts "それを繰り返すことで答えを探すことができます"
  puts "それではゲームを開始します"
end

# 入力された整数が設定した桁数と等しいか判断するメソッド
# n桁の整数の場合、10^(n-1)〜(10^n)-1の範囲に存在していればよい
# input_number:入力された整数
def input_number_judge(input_number)
  # 正しかったらtrueを、間違っていたらfalseを返す
  if input_number < 10**(DIGIT_NUMBER) && input_number >= 10**(DIGIT_NUMBER - 1)
    true
  else
    puts "入力された数は#{DIGIT_NUMBER}桁ではありません"
    puts "もう一度入力してください"
    false
  end
end

# n桁の整数の各桁の数を順に取り出していくメソッド
# 返り値は要素数nの配列
# number:n桁の整数
def number_to_array(number)
  number_array = []
  DIGIT_NUMBER.times do
    # 桁数の数だけ10で割った余りを配列に追加
    number_array.push(number % 10)
    # より上位の桁を求めるため10で割る
    number /= 10
  end
  
  # 下位の桁から順に入っているため配列を反転してreturn
  number_array.reverse
end

# 正解の数と入力された数を比較するメソッド
# input_number:入力された数
# set_number:正解の数
def input_answer_judge(input_number, set_number)
  # hitとblowの数を数えるための変数
  hit_time  = 0
  blow_time = 0
  
  # 入力された数を配列として取り出し
  input_number_array = number_to_array(input_number)
  # 正解の数を配列として取り出し
  set_number_array   = number_to_array(set_number)
  
  # 正解の数と入力された数の比較
  input_number_array.each_with_index do |current_input_number, input_index|
    # hitかどうか判定
    if current_input_number == set_number_array[input_index]
      hit_time += 1
      # hitしたら次の桁へ
      next
    # hitじゃなかったらblowかどうか判定
    else
      # 正解データと1つずつ比較
      set_number_array.each_with_index do |current_set_number, set_index|
        # 同じ桁は上でhitしていないので異なることは自明なので飛ばす
        next if input_index == set_index
        if current_set_number == current_input_number
          blow_time += 1
          # blowだったらループから抜ける
          break
        end
      end
    end
  end
  
  puts "#{hit_time}hit, #{blow_time}blow"
  
  # hit数が桁数と同じだったら正解と完全一致だからtrueを返す
  # 一致しなかったらfalseを返す
  if hit_time == DIGIT_NUMBER
    true
  else
    false
  end
end

#=========================================================
#                   ここからゲーム開始
#=========================================================

# 正解の数を生成
answer_number = make_answer_number

# ゲーム説明を表示
show_rule

# 正解かどうか判定するフラグ
answer_flag = false

# 不正解の間はずっとループ
while !answer_flag
  print "#{DIGIT_NUMBER}桁の数を入力してください : "
  # 数を入力
  anticipated_number = gets.to_i
  
  # 入力された数の桁数が正しいか判定
  # 正しくなかったらもう一度入力
  redo unless input_number_judge(anticipated_number)
  
  # 入力された数を正解の数と比較する
  answer_flag = input_answer_judge(anticipated_number, answer_number)
end

puts "正解です!"

#結果

数当てゲームを行います
これは4桁の数を探すゲームです
適当な数を入れると桁も数字もあっていれば「hit」としその個数が、
数字はあっているが桁が異なっていれば「blow」としてその個数が出力されます
それを繰り返すことで答えを探すことができます
それではゲームを開始します
4桁の数を入力してください : 999
入力された数は4桁ではありません
もう一度入力してください
4桁の数を入力してください : 10000
入力された数は4桁ではありません
もう一度入力してください
4桁の数を入力してください : 1359
0hit, 0blow
4桁の数を入力してください : 1627
1hit, 1blow
4桁の数を入力してください : 2615
2hit, 0blow
4桁の数を入力してください : 2604
2hit, 2blow
4桁の数を入力してください : 2640
4hit, 0blow
正解です!

#参考

2
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?