アプリ版:「スタンプのみでお礼する」機能のリリースについて

rubyでじゃんけんのプログラムを作っています。
ベースは出来たのですが、最終的には”3回勝負にして2回勝った方の勝利”というプログラムを目標としています。
3回は確実に繰り返し、結果をCSVファイルに付足し保存していき上記の機能を追加したいです。
どのように付け加えれば良いでしょうか。お答えいただけると非常に助かります

「rubyでじゃんけんのプログラムを作って」の質問画像

質問者からの補足コメント

  • 現時点での結果はこの様な状態です。

    「rubyでじゃんけんのプログラムを作って」の補足画像1
      補足日時:2020/12/17 23:52

A 回答 (1件)

あー、良く書けてますよ。


まぁ、CSVの方はどういう仕様にしたいのか全然書かれてないんで、取り敢えずは置いておきますが・・・・・・。

さて。
ちょっと重要な話をします。
実はプログラムの基本はインタプリタです。
Rubyにもirbと言うインタプリタが付属していますが、ユーザーからの入力を受け付け、中で解釈し、そして結果を表示する。今、irbと言う(Ruby)言語インタプリタを例に出したんですが、貴方が書こうとしているプログラムも実は構造的にはインタプリタと同じです。
インタプリタ、と言うと「プログラミング言語」と密接に関係あるように聞こえるんで、別の単語を導入します。REPLと言う単語ですね。
REPLと言うのはRead-Eval-Print Loopの頭文字を取った表現ですが、そのまま、読み込み-評価-印字ループと言う事ですね。実はインタプリタや全てのソフトウェア(スクリプトを除く)の基本です。ここを押さえておかないとならない。
ちと難しいように聞こえるかもしれませんが、基本は簡単です。例えば、今、jankenと言う1引数を取る評価用のプログラムがあったとして、たったこれだけで実装出来ます。

while true
 puts(janken(gets.to_i)
end

これがインタプリタ、そして全てのプログラムの基本、です。簡単でしょ?
まあ、実際これをそのまま使うと無限ループになっちゃうんですが、取り敢えずこれを基本として押さえて下さい。入力を受け取り、そいつを評価用プログラムの引数にぶち込み、何らかの結果(この場合は文字列)を計算してそのまままた出力メソッドに手渡す。それだけ、です。

さて、上の例だと無限ループになっちゃうんですが、今回は"3回勝負に"したい、との事なんで、単純に上のメソッドにcounterを付け加えてみます。

counter = 3
while counter != 0
 puts(janken(gets.to_i)
 i -= 1
end

counterが0になったらプログラムは終了、です。簡単ですね。
どうせなんで、ここもメソッドにします。後でちと改造が必要ですが、取り敢えずメソッドのカタチにして落ち着かせましょう。

def main()
 counter = 3
 puts "*半角で該当の数字を入力してね*\n最初はグーじゃんけん..."
 while counter != 0
  puts(janken(gets.to_i)
  counter -= 1
 end
end

REPLはもう一度言いますが、読み込み->評価->印字のサイクルが順番なんで、こう言う風に最初にイントロダクションを用意して表示したい場合は、そこだけ先に印字しておいて、それからREPLを始めるようにします。

さて、ここまで書き上げたら、次は心臓部、jankenの改造です。これを一引数のメソッドとして定義します。まずは次のように書き始める。

def janken(p)

オリジナルだとjankenは無引数で、内部にgets.to_iを持ってましたが、今はREPLで入力部は括りだしてるんで、このカタチがベストです。
そして、この辺は趣味なんですが、定形の「データを書き換えないブツ」、つまり参照用のデータですね。この辺はグローバル変数として外に置いた方がプログラムはスッキリする、と思いますね。例えばプログラムに頻出の文字列とか。
グローバル変数はあまり使うべきではない、って話もあるんですが、一般に、「データを書き換える目的」の場合はその通りなんですが、「データは単に参照用」の場合はその限りじゃないです。また、特に文字列なんですが、プログラム本体に埋め込まない方が、例えば英語版じゃんけんプログラムとか(笑)、作りたいな、って場合改造が容易です。文字列だけ置き換えちゃえば良いわけですしね。
まぁ、そういうわけで、個人的な趣味として、次の2つをjankenの外部に置きます。

$jankens = ["グー", "チョキ", "パー"]
$judge = {0 => "あいこで", 1 => "あなたの負けです", 2 => "あなたの勝ちです"}

グローバル変数$jankensは配列、もう一つの$judgeは・・・ちょっとしたトリックの為にハッシュを用いています。
さて、この2つを利用すると、jankenメソッドは基本的には次のように書くことが出来ます。

def janken(p)
 com = rand(3)
 result = (p - com + 3) % 3
 "あなたの手:#{$jankens[p]}, 相手の手:#{$jankens[com]}\n" + $judge[result]
end

これは「3すくみ」を解くアルゴリズム使って短く仕上げたモノです。「じゃんけんの結果」、つまりresultは実は(p - com + 3) % 3で計算出来ます。0の時はあいこ、1の時は負け、2の時は勝ちになる。この計算結果を用いて、ハッシュから文字列を引っこ抜いて来て、貴方が作った文字列と連結します。
基本はこれだけ、ですね。ただ、例えば2以上が入力されるとか0以下が入力される場合のエラーチェックはしてません。原版もしてないから、まぁいいでしょう。
この時点でのソースは次のようになります(Linuxで書いてるので、冒頭にシェバングあったり、ケツにスクリプトとしての実行用コードがあるけど、無視して良いです)。

#!/usr/bin/env ruby

$jankens = ["グー", "チョキ", "パー"]
$judge = {0 => "あいこで", 1 => "あなたの負けです", 2 => "あなたの勝ちです"}

def janken(p)
 com = rand(3)
 result = (p - com + 3) % 3
 "あなたの手:#{$jankens[p]}, 相手の手:#{$jankens[com]}\n" + $judge[result]
end

def main()
 counter = 3
 puts "*半角で該当の数字を入力してね*\n最初はグーじゃんけん..."
 while counter != 0
  puts(janken(gets.to_i))
  counter -= 1
 end
end


if __FILE__ == $0
main
end

ただ、これだと、あいこが出ようと、キッカリ3回で終わっちゃうんですね。その辺どうしましょうか?
慣れたRubyプログラマだと、恐らく例外処理使って、じゃんけんの結果が0の場合、強制的に巻き戻してもう一回勝負するようにするかもしれません。ただ、今回メンド臭いんで(笑)、Rubyの「多値」と言う機能を使います(Rubyを使い続けるなら、例外処理もなるたけ早く覚えた方が良いかもしれません)。
Rubyはなかなかイカした機能を持っていて、Rubyのメソッドは単一の値だけじゃなくって複数の値を返す事が出来ます。これを利用して、jankenを次のように改造します。

def janken(p)
 com = rand(3)
 result = (p - com + 3) % 3
 return result, "あなたの手:#{$jankens[p]}, 相手の手:#{$jankens[com]}\n" + $judge[result]
end

問題は「あいこ」の場合なんで、いずれにせよ、result自体も情報として返せば良い。Rubyではreturn文を用いて複数の値を返せるので、resultと文字列を両方返しちゃいます。
そして、mainメソッドの方も多値を受け取る前提で、REPLの部分をちょっと改造する。

def main()
 counter = 3
 puts "*半角で該当の数字を入力してね*\n最初はグーじゃんけん..."
 while counter != 0
  a, b = janken(gets.to_i) # 結果をa と b、2つの変数へと代入
  puts(b) # b は文字列なんでそのまま出力
  if a != 0
   counter -= 1 # 結果があいこじゃなかったらカウンターを1減らす
  end
 end
end

これで大まかには完成ですね。

> 最終的には”3回勝負にして2回勝った方の勝利”というプログラムを目標としています。

どっかに変数を作って、記録を取っていくように改造してみれば良いと思います。
    • good
    • 0
この回答へのお礼

ありがとう

ここまでご丁寧に詳しく教えて下さりありがとうございました!なんとか3回勝負のシステムまではできました。

お礼日時:2020/12/18 20:32

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!