Last active
October 23, 2019 04:08
-
-
Save gouf/ceeb8d442915abf60c9d7c87a16b4bff to your computer and use it in GitHub Desktop.
[Rubyでじゃんけんアプリを作ってみた - Qiita](https://qiita.com/hiro-gen/items/85639c0a8f925e31fbbe) を見たので書いてみた
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# frozen_string_literal: true | |
# じゃんけんゲームで出せる手の種類 | |
module Hands | |
HANDS = %i[rock scissors paper].freeze | |
HANDS_LABEL = %w[グー チョキ パー].freeze | |
private_constant :HANDS, :HANDS_LABEL | |
end | |
# じゃんけんゲームの開始・終了、状況を管理 | |
class JankenGame | |
include Hands | |
def initialize(player:, computer:) | |
@player = player | |
@computer = computer | |
end | |
def start | |
puts 'じゃんけんゲーム!!' | |
puts '' | |
loop do | |
@player.hand = ask_hand(@player) | |
@computer.hand = ask_hand(@computer) | |
game_result = judge_game | |
break if game_end?(game_result) | |
end | |
end | |
private | |
def judge_game | |
show_players_hand | |
puts '' | |
if @player.won?(@computer) | |
puts 'あなたの勝利!!' | |
:won | |
elsif @player.draw?(@computer) | |
puts '引き分け! もう一回!!' | |
puts '' | |
:draw | |
elsif @player.lose?(@computer) | |
puts 'あなたの負け...' | |
:lose | |
end | |
end | |
# 勝敗が決したらゲーム終了 | |
def game_end?(game_result) | |
%i[won lose].include?(game_result) | |
end | |
def show_players_hand | |
puts '' | |
puts "プレイヤー : #{@player.hand_as_label}" | |
puts "コンピュータ: #{@computer.hand_as_label}" | |
end | |
def ask_hand(player) | |
return player.generated_hand_choose if player.is_computer? | |
puts 'あなたの出す手は?' | |
puts(HANDS_LABEL.map.with_index { |label, i| "[#{i}] #{label}" }) | |
hand_choose = gets.chomp | |
raise_if_validate_error(hand_choose) | |
HANDS.at(hand_choose.to_i) | |
rescue TypeError, RuntimeError | |
puts '' | |
puts 'エラー!! 選択肢にある数字を入力してね!' | |
puts '' | |
retry | |
end | |
# 数字入力を期待し、それ以外は例外とする | |
def raise_if_validate_error(hand_choose) | |
raise TypeError unless hand_choose.match?(/\d+/) | |
raise RuntimeError if HANDS.at(hand_choose.to_i).nil? | |
raise RuntimeError if hand_choose.to_i.negative? | |
end | |
end | |
# Rubocop のルールよりも見た目と位置揃えを優先したいので一時的に無効化 | |
# rubocop:disable Layout/SpaceInsideArrayPercentLiteral, Layout/AlignHash | |
# じゃんけんゲームの出した手を勝敗パターンテーブルとして保持 | |
module GameJudgeTable | |
JUDGE_TABLE = { | |
# 自分が勝つパターン | |
%i[rock scissors] => :me, | |
%i[scissors paper] => :me, | |
%i[paper rock] => :me, | |
# 相手が勝つパターン | |
%i[rock paper] => :other, | |
%i[scissors rock] => :other, | |
%i[paper scissors] => :other, | |
# 引き分けパターン | |
%i[rock rock] => :draw, | |
%i[scissors scissors] => :draw, | |
%i[paper paper] => :draw | |
}.freeze | |
private_constant :JUDGE_TABLE | |
end | |
# rubocop:enable Layout/SpaceInsideArrayPercentLiteral, Layout/AlignHash | |
# じゃんけんゲームのプレイヤー | |
class Player | |
include GameJudgeTable | |
include Hands | |
attr_reader :is_computer, :hand | |
alias is_computer? is_computer | |
def initialize(is_computer: false) | |
@is_computer = is_computer | |
end | |
# @hand に保持される値は Hand::HANDS と同じ %i[rock scissors paper] の3種を期待 | |
def hand=(hand) | |
raise TypeError unless HANDS.include?(hand) | |
@hand = hand | |
end | |
# 勝敗パターンを「勝ち」「負け」「引き分け」の true/false 応答に変換 | |
[ | |
%i[won? me], | |
%i[lose? other], | |
%i[draw? draw] | |
].each do |method_name, refer_value| | |
define_method(method_name) do |other_player| | |
JUDGE_TABLE[[@hand, other_player.hand]].eql?(refer_value) | |
end | |
end | |
# プレイヤーがコンピュータ側の場合があるので、選ぶ手を自動選択できるようにした | |
def generated_hand_choose | |
HANDS.sample | |
end | |
def hand_as_label | |
index = HANDS.index(@hand) | |
HANDS_LABEL.at(index) | |
end | |
end | |
# ============================== | |
player = Player.new | |
computer = Player.new(is_computer: true) | |
janken_game = JankenGame.new(player: player, computer: computer) | |
janken_game.start |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment