【Ruby】確認問題4-☆1:ナインゲームを作ろう

記事内に商品プロモーションを含む場合があります

この記事の練習問題で使用する知識:
基礎文法(レッスン1)比較演算子と論理演算子if文による分岐処理until文による繰り返し処理メソッドの定義と使用例外処理配列の基本配列の操作配列の調査

Rubyのゲームコード一覧はこちら

<<前のページ Ruby記事一覧 次のページ>>

確認問題:ナインゲームを作ろう

ナインゲームはプレイヤーとコンピュータが対戦するゲームです。

プレイヤーとコンピュータは最初に1から9までの9枚の牌を持ち、順番に一つずつ選びます。

大きい数字の牌を出した方にその数字と同じ数の得点が入ります。

両者の持っている牌がなくなるまで勝負を続け、最終的により多くの得点を持っていた方が勝利となります。

この問題の要件

以下の要件に従ったプログラムを作成すること。

  • プレイヤーとコンピュータの得点を初期化する変数を作成すること。
  • プレイヤーとコンピュータの持ち牌を配列として初期化すること。
  • プレイヤーとコンピュータの使用済み牌を格納するための配列を作成すること。
  • ゲームの開始を知らせるメッセージを表示すること。
  • 9回の勝負を繰り返すためのループを作成すること。
  • 各ラウンドの開始時に現在の得点と持ち牌を表示すること。
  • プレイヤーが有効な牌を選択するまで繰り返し入力を求める処理を作成すること。
  • コンピュータがランダムに牌を選択する処理を作成すること。
  • 選択した牌を使用済み牌の配列に追加すること。
  • 選択した牌の数字を比較し、勝者を決定し得点を加算すること。
  • 最終結果を表示し、勝者を決定すること。

ただし、以下のような実行結果となること。

----- ↓出力される結果の例↓ -----

ナインゲームを開始します!

【第1回戦】
プレイヤーの得点 :0点
コンピュータの得点:0点
プレイヤーの持ち牌 ⇒ [1, 2, 3, 4, 5, 6, 7, 8, 9]
コンピュータの持ち牌⇒ [1, 2, 3, 4, 5, 6, 7, 8, 9]
持ち牌の中から出す牌を選択してください > 9
プレイヤーの打牌:9 VS 5:コンピュータの打牌
プレイヤーは9点獲得

【第2回戦】
プレイヤーの得点 :9点
コンピュータの得点:0点
プレイヤーの持ち牌 ⇒ [1, 2, 3, 4, 5, 6, 7, 8, -]
コンピュータの持ち牌⇒ [1, 2, 3, 4, -, 6, 7, 8, 9]
持ち牌の中から出す牌を選択してください > 
...

この問題を解くヒント

1からコードを組み立てることが難しい場合は、以下のヒントを開いて参考にしましょう。

ヒント1【コードの構成を見る】

正解のコードは以下のような構成となっています。

1:プレイヤーとコンピュータの得点を初期化
2:プレイヤーとコンピュータの持ち牌を初期化
3:プレイヤーとコンピュータの使用済み牌を格納する配列を初期化
4:「ナインゲームを開始します!」と出力
5:1から9までの範囲でループを開始
□ 第◯回戦のメッセージを出力
□ 現在の得点を表示
□ 関数display_tilesを定義し、持ち牌の表示をフォーマット
□ プレイヤーとコンピュータの持ち牌を表示
□ 「持ち牌の中から出す牌を選択してください」と出力
□ ユーザーの入力を数値に変換してplayer_choiceに代入
□ プレイヤーが有効な牌を選ぶまで繰り返す
□ □ 無効な選択の場合、再入力を促す
□ コンピュータが未使用の持ち牌からランダムに選択し、computer_choiceに代入
□ プレイヤーとコンピュータの選択した牌を使用済みリストに追加
□ プレイヤーとコンピュータの打牌を表示
□ if文でプレイヤーの選択牌がコンピュータの選択牌より大きいかを判定
□ □ 真の場合、プレイヤーの得点にplayer_choiceを加算し、得点メッセージを出力
□ □ 偽の場合、コンピュータの得点にcomputer_choiceを加算し、得点メッセージを出力
□ □ それ以外は「引き分けです」と出力
6:ゲーム終了後、最終結果を表示
7:if文でプレイヤーとコンピュータの最終得点を比較
□ プレイヤーの得点が高ければ勝利メッセージを出力
□ コンピュータの得点が高ければ敗北メッセージを出力
□ 引き分けの場合は引き分けメッセージを出力

ヒント2【穴埋め問題にする】

以下のコードをコピーし、コメントに従ってコードを完成させてください。

# プレイヤーとコンピュータの得点を初期化
=begin
【穴埋め問題1】
ここでプレイヤーとコンピュータの得点を初期化するコードを書いてください。
=end

# プレイヤーとコンピュータの持ち牌を初期化
=begin
【穴埋め問題2】
ここでプレイヤーとコンピュータの持ち牌を初期化するコードを書いてください。
=end

# プレイヤーとコンピュータの使用済み牌を格納する配列
=begin
【穴埋め問題3】
ここでプレイヤーとコンピュータの使用済み牌を初期化するコードを書いてください。
=end

# ゲーム開始のメッセージ
puts "ナインゲームを開始します!"

# 9回の勝負を行う
(1..9).each do |round|
  puts "\n【第#{round}回戦】"
  
  # 現在の得点を表示
=begin
【穴埋め問題4】
ここでプレイヤーとコンピュータの得点を表示するコードを書いてください。
=end

  # 現在の持ち牌を表示
  def display_tiles(tiles, used_tiles)
    =begin
    【穴埋め問題5】
    ここで持ち牌の配列を処理し、使用済みの牌を「-」で表示するコードを書いてください。
    =end
  end
  
=begin
【穴埋め問題6】
ここでプレイヤーとコンピュータの持ち牌を表示するコードを書いてください。
=end

  # プレイヤーが出す牌を選択
=begin
【穴埋め問題7】
ここでプレイヤーが出す牌を選択し、有効な選択になるまで繰り返し入力を促すコードを書いてください。
=end

  # コンピュータがランダムに牌を選択
=begin
【穴埋め問題8】
ここでコンピュータがランダムに牌を選択するコードを書いてください。
=end

  # 選択した牌を使用済み牌に追加
=begin
【穴埋め問題9】
ここでプレイヤーとコンピュータの選択した牌を使用済みリストに追加するコードを書いてください。
=end

  # 選択した牌を表示
=begin
【穴埋め問題10】
ここでプレイヤーとコンピュータが選択した牌を表示するコードを書いてください。
=end

  # 勝者を決定し、得点を追加
=begin
【穴埋め問題11】
ここでプレイヤーとコンピュータの選択した牌を比較し、得点を追加するコードを書いてください。
=end
end

# 最終得点を表示し、勝者を決定
=begin
【穴埋め問題12】
ここで最終結果を表示し、勝者を決定するコードを書いてください。
=end

この問題の穴埋めコードは以上です。

Rubyのナインゲームの正解コードと解説

この問題の一つの正解例とそのコードの解説を以下に示します。

正解コードの例

例えば以下のようなプログラムが考えられます。

# プレイヤーとコンピュータの得点を初期化
player_score = 0
computer_score = 0

# プレイヤーとコンピュータの持ち牌を初期化
player_tiles = (1..9).to_a
computer_tiles = (1..9).to_a

# プレイヤーとコンピュータの使用済み牌を格納する配列
player_used_tiles = []
computer_used_tiles = []

# ゲーム開始のメッセージ
puts "ナインゲームを開始します!"

# 9回の勝負を行う
(1..9).each do |round|
  puts "\n【第#{round}回戦】"
  
  # 現在の得点を表示
  puts "プレイヤーの得点 :#{player_score}点"
  puts "コンピュータの得点:#{computer_score}点"

  # 現在の持ち牌を表示
  def display_tiles(tiles, used_tiles)
    tiles.map do |tile|
      if used_tiles.include?(tile)
        '-'
      else
        tile
      end
    end.join(', ')
  end
  
  puts "プレイヤーの持ち牌 ⇒ [#{display_tiles(player_tiles, player_used_tiles)}]"
  puts "コンピュータの持ち牌⇒ [#{display_tiles(computer_tiles, computer_used_tiles)}]"
  
  # プレイヤーが出す牌を選択
  print "持ち牌の中から出す牌を選択してください > "
  player_choice = gets.to_i

  # プレイヤーが有効な牌を出すまで繰り返す
  until (player_tiles - player_used_tiles).include?(player_choice)
    print "無効な選択です。もう一度選択してください > "
    player_choice = gets.to_i
  end
  
  # コンピュータがランダムに牌を選択
  computer_choice = (computer_tiles - computer_used_tiles).sample
  
  # 選択した牌を使用済み牌に追加
  player_used_tiles << player_choice
  computer_used_tiles << computer_choice
  
  # 選択した牌を表示
  puts "プレイヤーの打牌:#{player_choice} VS #{computer_choice}:コンピュータの打牌"
  
  # 勝者を決定し、得点を追加
  if player_choice > computer_choice
    player_score += player_choice
    puts "プレイヤーは#{player_choice}点獲得"
  elsif computer_choice > player_choice
    computer_score += computer_choice
    puts "コンピュータは#{computer_choice}点獲得"
  else
    puts "引き分けです"
  end
end

# 最終得点を表示し、勝者を決定
puts "\n最終結果"
puts "プレイヤーの得点 :#{player_score}点"
puts "コンピュータの得点:#{computer_score}点"

if player_score > computer_score
  puts "プレイヤーの勝利です!"
elsif computer_score > player_score
  puts "コンピュータの勝利です!"
else
  puts "引き分けです!"
end

正解のコードの解説

このプログラムは「ナインゲーム」と呼ばれるシンプルなゲームを実装したものです。

プレイヤーとコンピュータが1から9の牌を順番に出し合い、大きい数字を出した方がその数字分の得点を獲得します。

最終的な得点で勝者が決まります。

得点と牌の初期化

player_score = 0
computer_score = 0
player_tiles = (1..9).to_a
computer_tiles = (1..9).to_a
player_used_tiles = []
computer_used_tiles = []
  • 得点の初期化
    player_scorecomputer_scoreを0に設定します。これがそれぞれの初期得点になります。
  • 牌の初期化
    プレイヤーとコンピュータの持ち牌を1から9の配列で初期化します。player_used_tilescomputer_used_tilesは使用済みの牌を記録する配列です。

ゲーム開始メッセージ

puts "ナインゲームを開始します!"

プログラムの冒頭でゲーム開始を知らせるメッセージを表示します。

各ラウンドの処理

(1..9).each do |round|
  puts "\n【第#{round}回戦】"
  • ループ構造
    (1..9)は1から9までの範囲を表し、9回の勝負をループで処理します。roundは現在のラウンド番号を示します。

現在の得点を表示

puts "プレイヤーの得点 :#{player_score}点"
puts "コンピュータの得点:#{computer_score}点"

現在の得点をプレイヤーとコンピュータそれぞれで表示します。

持ち牌の表示

def display_tiles(tiles, used_tiles)
  tiles.map do |tile|
    if used_tiles.include?(tile)
      '-'
    else
      tile
    end
  end.join(', ')
end

puts "プレイヤーの持ち牌 ⇒ [#{display_tiles(player_tiles, player_used_tiles)}]"
puts "コンピュータの持ち牌⇒ [#{display_tiles(computer_tiles, computer_used_tiles)}]"
  • display_tilesメソッド
    このメソッドは持ち牌の配列を受け取り、使用済みの牌を「-」で表示します。
  • 持ち牌の表示
    現在の持ち牌がどれかをプレイヤーとコンピュータそれぞれに表示します。

プレイヤーの打牌選択

print "持ち牌の中から出す牌を選択してください > "
player_choice = gets.to_i

until (player_tiles - player_used_tiles).include?(player_choice)
  print "無効な選択です。もう一度選択してください > "
  player_choice = gets.to_i
end
  • プレイヤーの選択
    プレイヤーに未使用の牌を選択させます。有効な選択になるまで繰り返します。

コンピュータの打牌選択

computer_choice = (computer_tiles - computer_used_tiles).sample
  • コンピュータの選択
    コンピュータは未使用の牌からランダムに1つ選びます。

使用済み牌の更新

player_used_tiles << player_choice
computer_used_tiles << computer_choice

プレイヤーとコンピュータの選択した牌を使用済みリストに追加します。

打牌の表示

puts "プレイヤーの打牌:#{player_choice} VS #{computer_choice}:コンピュータの打牌"

プレイヤーとコンピュータが選択した牌を表示します。

勝敗の判定

if player_choice > computer_choice
  player_score += player_choice
  puts "プレイヤーは#{player_choice}点獲得"
elsif computer_choice > player_choice
  computer_score += computer_choice
  puts "コンピュータは#{computer_choice}点獲得"
else
  puts "引き分けです"
end
  • プレイヤーの牌が大きい場合、プレイヤーの得点にその牌の値を加算します。
  • コンピュータが勝った場合も同様に得点を加算します。
  • 引き分けの場合は何も加算されません。

最終結果の表示

puts "\n最終結果"
puts "プレイヤーの得点 :#{player_score}点"
puts "コンピュータの得点:#{computer_score}点"

if player_score > computer_score
  puts "プレイヤーの勝利です!"
elsif computer_score > player_score
  puts "コンピュータの勝利です!"
else
  puts "引き分けです!"
end

各ラウンドでの得点を集計し、最終的な勝敗を判定して結果を表示します。

まとめ

このコードでは配列やループ、条件分岐などの基本的なRubyの文法を学ぶことができます。

ゲーム形式でプログラムを作成することで、楽しく学習が進むでしょう。

このコードを理解したら、自分でルールを変更したり、機能を追加してみるのも良い練習になります。

挑戦を続けて、プログラミングのスキルを磨いていきましょう!

Rubyのゲームコード一覧はこちら

<<前のページ Ruby記事一覧 次のページ>>

この記事への質問・コメント

この記事を作成するにあたりAIを活用しています。

問題ないことは確認していますが、もし間違いや表現の違和感などありましたら、ご指摘頂けると大変助かります。






    Rubyテキスト&問題集へ戻る
    トップページへ戻る