Skip to content

Instantly share code, notes, and snippets.

@gouf
Last active Oct 23, 2019
Embed
What would you like to do?
[Rubyでじゃんけんアプリを作ってみた - Qiita](https://qiita.com/hiro-gen/items/85639c0a8f925e31fbbe) を見たので書いてみた
# 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