【Ruby】レッスン4-☆1:ナインゲームを作って配列と得点ロジックを学ぼう

一つ前のページではハッシュについて学習しました。
今回はナインゲームを作ってみましょう。
Lesson1:基礎文法編
Lesson2:制御構造編
Lesson3:メソッド編
Lesson4:コレクション編
・Lesson4-1:配列の基本を理解しよう
・Lesson4-2:配列を操作しよう
・Lesson4-3:配列を調査しよう
・Lesson4-4:配列を並び替えよう
・Lesson4-5:eachメソッドを理解しよう
・Lesson4-6:mapメソッドを理解しよう
・Lesson4-7:filterメソッドを理解しよう
・Lesson4-8:ハッシュを理解しよう
・確認問題4-☆1:ナインゲームを作ろう ◁今回はココ
・確認問題4-☆2:アラビア数字をローマ数字に変換しよう
・確認問題4-☆3:トランプをランダムに配ろう
Lesson5:オブジェクト指向編
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
このヒントを見てもまだ回答を導き出すのが難しいと感じる場合は、先に正解のコードと解説を見て内容を理解するようにしましょう。
この問題の解答例と解説
この問題の正解コードとその解説は以下の通りです。
クリックして開いて確認してください。
- 正解コード
-
# プレイヤーとコンピュータの得点を初期化 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
- 正解コードの解説
-
コードをブロックごとに分割して解説します。
得点と牌の初期化
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_score
とcomputer_score
を0に設定します。これがそれぞれの初期得点になります。牌の初期化
プレイヤーとコンピュータの持ち牌を1から9の配列で初期化します。player_used_tiles
とcomputer_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の文法を学ぶことができます。
ゲーム形式でプログラムを作成することで、楽しく学習が進むでしょう。
このコードを理解したら、自分でルールを変更したり、機能を追加してみるのも良い練習になります。
挑戦を続けて、プログラミングのスキルを磨いていきましょう!