質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Q&A

解決済

2回答

1690閲覧

コードの重複をなくすための方法

takeroyasuhara

総合スコア15

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

0グッド

0クリップ

投稿2015/08/07 05:25

  • PersonクラスのサブクラスであるFighter,Wizard,Priestクラス内の各battleメソッドの重複(ifelsifelse~endあたり)表記をなくしてもう少しすっきり書けないかと考えているのですが、思いつかず、アイデアがあれば教えていただきたいと思っています。

Ruby

1# Personクラス定義 2class Person 3 attr_reader :strength 4 attr_reader :cleverness 5 6 def initialize(st, cl) 7 @strength = st 8 @cleverness = cl 9 end 10 11 def sum 12 strength + cleverness 13 end 14 15 def battle(opponent) 16 judge(self.sum, opponent.sum) 17 end 18 19 private 20 def judge(self_sum, opponent_sum) 21 if self_sum > opponent_sum 22 "勝利" 23 elsif self_sum == opponent_sum 24 "未決着" 25 else 26 "敗北" 27 end 28 end 29end 30 31# Fighterクラス定義 32class Fighter < Person 33 alias base_strength strength 34 def strength 35 base_strength * 1.5 36 end 37 38 alias base_cleverness cleverness 39 def cleverness 40 base_cleverness * 1.0 41 end 42 43 def battle(opponent) 44 if opponent.is_a?(Wizard) 45 sum_revised = self.strength * 0.85 + self.cleverness 46 judge(sum_revised, opponent.sum) 47 elsif opponent.is_a?(Priest) 48 opponent_revised = (opponent.strength * 0.95) + (opponent.cleverness * 0.90) 49 judge(self.sum, opponent_revised) 50 else 51 super 52 end 53 end 54end 55 56# Wizardクラス定義 57class Wizard < Person 58 alias base_strength strength 59 def strength 60 base_strength * 0.5 61 end 62 63 alias base_cleverness cleverness 64 def cleverness 65 base_cleverness * 3.0 66 end 67 68 def battle(opponent) 69 if opponent.is_a?(Priest) 70 sum_revised = self.strength + self.cleverness * 0.75 71 judge(sum_revised, opponent.sum) 72 elsif opponent.is_a?(Fighter) 73 opponent_revised = opponent.strength * 0.85 + opponent.cleverness 74 judge(self.sum, opponent_revised) 75 else 76 super 77 end 78 end 79end 80 81# Priestクラス定義 82class Priest < Person 83 alias base_strength strength 84 def strength 85 base_strength * 1.0 86 end 87 88 alias base_cleverness cleverness 89 def cleverness 90 base_cleverness * 2.0 91 end 92 93 def battle(opponent) 94 if opponent.is_a?(Fighter) 95 sum_revised = self.strength * 0.95 + self.cleverness * 0.90 96 judge(sum_revised, opponent.sum) 97 elsif opponent.is_a?(Wizard) 98 opponent_revised = opponent.strength + opponent.cleverness * 0.75 99 judge(self.sum, opponent_revised) 100 else 101 super 102 end 103 end

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

こんな感じでどうですか?

lang

1module Game 2 TABLE = {}.tap { |hash| 3 hash[[Priest, Wizard]] = { cleverness: 0.75 } 4 hash[[Wizard, Fighter]] = { strength: 0.85 } 5 hash[[Fighter, Priest]] = { strength: 0.95, cleverness: 0.9 } 6 } 7 8 module_function 9 10 def battle(a, b) 11 a_power = calc_power(a, TABLE[[b.class, a.class]]) 12 b_power = calc_power(b, TABLE[[a.class, b.class]]) 13 14 case 15 when a_power > b_power 16 "勝利" 17 when a_power < b_power 18 "敗北" 19 else 20 "未決着" 21 end 22 end 23 24 def calc_power(person, bonus) 25 str = person.strength 26 clv = person.cleverness 27 if bonus != nil 28 if bonus[:strength] 29 str *= bonus[:strength] 30 end 31 if bonus[:cleverness] 32 clv *= bonus[:cleverness] 33 end 34 end 35 str + clv 36 end 37end

lang

1f = Fighter.new(100, 100) 2w = Wizard.new(100, 100) 3p = Priest.new(100, 100) 4 5puts "--- 従来の戦闘計算" 6 7puts f.battle(w) 8puts w.battle(p) 9puts p.battle(f) 10 11puts "--- 新しい戦闘計算" 12 13puts Game.battle(f, w) 14puts Game.battle(w, p) 15puts Game.battle(p, f)

投稿2015/08/07 06:03

編集2015/08/07 06:08
hello-world

総合スコア1342

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

takeroyasuhara

2015/08/07 06:43

具体的な事例をご提示いただきありがとうございました。非常にわかりやすくて参考になりました。 一点だけ、以下のコードについて、どういった処理をされているのか理解できず追加でご質問させていただきたいと思っております。 ```Ruby TABLE = {}.tap { |hash| hash[[Priest, Wizard]] = { cleverness: 0.75 } hash[[Wizard, Fighter]] = { strength: 0.85 } hash[[Fighter, Priest]] = { strength: 0.95, cleverness: 0.9 } } ``` TABLEという定数に対し、以下のようなハッシュデータを入れているというものだと理解したのですが、認識あっておりますでしょうか? ```Ruby { [Priest, Wizard]: { cleverness: 0.75 }, [Wizard, Fighter]: { strength: 0.85 }, [Fighter, Priest]: { strength: 0.95, cleverness: 0.9 } } ```
hello-world

2015/08/07 06:52 編集

はい。定数を編集するコードが気持ち悪いのでこう書きましたが、 TABLE = {}.tap { |hash|  hash[[Priest, Wizard]] = { cleverness: 0.75 }  hash[[Wizard, Fighter]] = { strength: 0.85 }  hash[[Fighter, Priest]] = { strength: 0.95, cleverness: 0.9 } } と TABLE = {} TABLE[[Priest, Wizard]] = { cleverness: 0.75 } TABLE[[Wizard, Fighter]] = { strength: 0.85 } TABLE[[Fighter, Priest]] = { strength: 0.95, cleverness: 0.9 } は等価です。
takeroyasuhara

2015/08/07 06:59

ご回答ありがとうございました。大変勉強になりました!
guest

0

Person に十分な汎用性をもたせ、 Fighter, Wizard, Priest に実装をほとんど書かずに済ませてみました。
game.rb

ruby

1# coding: utf-8 2# Personクラス定義 3 4# 基本の強さの係数 5MIG = { 6 Person: { st: 1.0, cl: 1.0 }, 7 Fighter: { st: 1.5, cl: 1.0 }, 8 Wizard: { st: 0.5, cl: 3.0 }, 9 Priest: { st: 1.0, cl: 2.0 } 10}.freeze 11 12# 対戦相手タイプ事の戦闘力の係数 13REL = { 14 Fighter: {Fighter: { st: 1.00, cl: 1.00 }, 15 Wizard: { st: 0.85, cl: 1.00 }, 16 Priest: { st: 0.95, cl: 0.90 }}, 17 18 Wizard: {Fighter: { st: 1.0/0.85, cl: 1.00 }, 19 Wizard: { st: 1.00, cl: 1.00 }, 20 Priest: { st: 1.00, cl: 0.75 }}, 21 22 Priest: {Fighter: { st: 1.0/0.95, cl: 1.0/0.90 }, 23 Wizard: { st: 1.00, cl: 1.0/0.75 }, 24 Priest: { st: 1.00, cl: 1.00 }} 25}.freeze 26 27class Person 28 attr_reader :strength 29 attr_reader :cleverness 30 31 def initialize(st = 1.0, cl = 1.0) 32 type = self.class.to_s.to_sym 33 @strength = st * MIG[type][:st] 34 @cleverness = cl * MIG[type][:cl] 35 end 36 37 def sum 38 strength + cleverness 39 end 40 41 # 対戦相手タイプとの相対的な強さを計算する 42 def sum_vs_type(type) 43 my_type = self.class.to_s.to_sym 44 REL[my_type][type][:st] * @strength + REL[my_type][type][:cl] * @cleverness 45 end 46 47 def battle(opponent) 48 my_sum = sum_vs_type(opponent.class.to_s.to_sym) 49 # opp_sum = opponent.sum_vs_type(self.class.to_s.to_sym) 50 opp_sum = opponent.sum # 質問文のコードでの 相手の強さの計算 51 judge(my_sum, opp_sum) 52 end 53 54 private 55 def judge(self_sum, opponent_sum) 56 if self_sum > opponent_sum 57 "勝利" 58 elsif self_sum == opponent_sum 59 "未決着" 60 else 61 "敗北" 62 end 63 end 64end 65 66# Fighterクラス定義 67class Fighter < Person 68end 69 70# Wizardクラス定義 71class Wizard < Person 72end 73 74# Priestクラス定義 75class Priest < Person 76end

sample.rb

ruby

1require './game.rb' 2 3f = Fighter.new(1, 1) 4w = Wizard.new(1, 1) 5 6p "Fighter v.s Wizard #{f.battle(w)}" 7p "Wizard v.s Fighter #{w.battle(f)}"

実行例;

$ ruby sample.rb "Fighter v.s Wizard 敗北" "Wizard v.s Fighter 勝利"

投稿2015/08/08 01:36

katoy

総合スコア22324

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問