プログラミング初心者のためのクラス図入門 - ポケモンで学ぶオブジェクト指向
目次
- はじめに
- 1. クラスとは何か?
- 2. クラス図の基本構造
- 3. 具体的なポケモンクラス図
- 4. 継承関係を表現する
- 5. 具体的なポケモンたち
- 6. 関連関係を表現する
- 7. 実際の設計での活用
- まとめ
- 次のステップ
はじめに
詳細設計書でクラス図を作る必要があるけれど、そもそも「クラス」って何?という方のために、ポケモンを例にしてクラス図の基本を分かりやすく解説します。
1. クラスとは何か?
クラスは、同じような特徴や機能を持つものの「設計図」や「型」のことです。
ポケモンで例えると:
- ポケモンクラス = すべてのポケモンが持つ共通の設計図
- ピカチュウ、フシギダネ、ヒトカゲ = その設計図から作られた具体的なポケモン(インスタンス)
2. クラス図の基本構造
クラス図は3つの部分に分かれています:
2.1 クラス名
一番上の部分。クラスの名前を書きます。
2.2 属性(フィールド)
真ん中の部分。そのクラスが持つデータ(特徴)を書きます。
2.3 メソッド(操作)
一番下の部分。そのクラスができること(機能)を書きます。
3. 具体的なポケモンクラス図
属性の説明:
-
name
: ポケモンの名前(例:ピカチュウ) -
type
: ポケモンのタイプ(例:でんき) -
level
: レベル(例:25) -
hp
: 体力(例:100) -
attack_power
: 攻撃力(例:55)
メソッドの説明:
-
getName()
: 名前を取得する -
attack()
: 他のポケモンを攻撃する -
takeDamage()
: ダメージを受ける -
levelUp()
: レベルアップする -
isAlive()
: 生きているかチェックする
Pythonコード例
Python版ポケモンクラス
class Pokemon:
def __init__(self, name: str, pokemon_type: str, level: int = 1, hp: int = 100, attack_power: int = 50):
self._name = name
self._type = pokemon_type
self._level = level
self._hp = hp
self._max_hp = hp
self._attack_power = attack_power
def get_name(self) -> str:
return self._name
def get_type(self) -> str:
return self._type
def attack(self, target: 'Pokemon') -> None:
damage = self._attack_power
print(f"{self._name}の攻撃! {target.get_name()}に{damage}のダメージ!")
target.take_damage(damage)
def take_damage(self, damage: int) -> None:
self._hp -= damage
if self._hp < 0:
self._hp = 0
print(f"{self._name}の残りHP: {self._hp}")
def level_up(self) -> None:
self._level += 1
self._hp += 10
self._max_hp += 10
self._attack_power += 5
print(f"{self._name}がレベルアップ! レベル{self._level}になった!")
def is_alive(self) -> bool:
return self._hp > 0
def __str__(self) -> str:
return f"{self._name}(Lv.{self._level}, HP:{self._hp}/{self._max_hp})"
Javaコード例
Java版ポケモンクラス
public class Pokemon {
private String name;
private String type;
private int level;
private int hp;
private int maxHp;
private int attackPower;
public Pokemon(String name, String type, int level, int hp, int attackPower) {
this.name = name;
this.type = type;
this.level = level;
this.hp = hp;
this.maxHp = hp;
this.attackPower = attackPower;
}
public String getName() {
return name;
}
public String getType() {
return type;
}
public int getLevel() {
return level;
}
public int getHp() {
return hp;
}
public void attack(Pokemon target) {
int damage = this.attackPower;
System.out.println(this.name + "の攻撃! " + target.getName() + "に" + damage + "のダメージ!");
target.takeDamage(damage);
}
public void takeDamage(int damage) {
this.hp -= damage;
if (this.hp < 0) {
this.hp = 0;
}
System.out.println(this.name + "の残りHP: " + this.hp);
}
public void levelUp() {
this.level++;
this.hp += 10;
this.maxHp += 10;
this.attackPower += 5;
System.out.println(this.name + "がレベルアップ! レベル" + this.level + "になった!");
}
public boolean isAlive() {
return this.hp > 0;
}
@Override
public String toString() {
return name + "(Lv." + level + ", HP:" + hp + "/" + maxHp + ")";
}
}
4. 継承関係を表現する
ポケモンには様々なタイプがあります。継承を使って表現してみましょう。
継承の意味:
-
ElectricPokemon
FirePokemon
GrassPokemon
はPokemon
の特徴をすべて持っている - さらに、でんきタイプ特有の技や属性を追加で持っている
-
<|--
の矢印は「継承」を表す
Pythonコード例
Python版ポケモン継承
class ElectricPokemon(Pokemon):
def __init__(self, name: str, level: int = 1, hp: int = 100, attack_power: int = 50):
super().__init__(name, "でんき", level, hp, attack_power)
self._electric_power = 30
def thunderbolt(self, target: Pokemon) -> None:
damage = self._attack_power + self._electric_power
print(f"{self._name}の10まんボルト! {target.get_name()}に{damage}のダメージ!")
target.take_damage(damage)
def spark(self, target: Pokemon) -> None:
damage = self._attack_power + (self._electric_power // 2)
print(f"{self._name}のスパーク! {target.get_name()}に{damage}のダメージ!")
target.take_damage(damage)
class FirePokemon(Pokemon):
def __init__(self, name: str, level: int = 1, hp: int = 100, attack_power: int = 50):
super().__init__(name, "ほのお", level, hp, attack_power)
self._fire_power = 35
def flamethrower(self, target: Pokemon) -> None:
damage = self._attack_power + self._fire_power
print(f"{self._name}のかえんほうしゃ! {target.get_name()}に{damage}のダメージ!")
target.take_damage(damage)
def ember(self, target: Pokemon) -> None:
damage = self._attack_power + (self._fire_power // 2)
print(f"{self._name}のひのこ! {target.get_name()}に{damage}のダメージ!")
target.take_damage(damage)
class GrassPokemon(Pokemon):
def __init__(self, name: str, level: int = 1, hp: int = 100, attack_power: int = 50):
super().__init__(name, "くさ", level, hp, attack_power)
self._grass_power = 25
def vine_whip(self, target: Pokemon) -> None:
damage = self._attack_power + self._grass_power
print(f"{self._name}のつるのムチ! {target.get_name()}に{damage}のダメージ!")
target.take_damage(damage)
def razor_leaf(self, target: Pokemon) -> None:
damage = self._attack_power + (self._grass_power // 2)
print(f"{self._name}のはっぱカッター! {target.get_name()}に{damage}のダメージ!")
target.take_damage(damage)
Javaコード例
Java版ポケモン継承
public class ElectricPokemon extends Pokemon {
private int electricPower;
public ElectricPokemon(String name, int level, int hp, int attackPower) {
super(name, "でんき", level, hp, attackPower);
this.electricPower = 30;
}
public void thunderbolt(Pokemon target) {
int damage = super.attackPower + this.electricPower;
System.out.println(super.getName() + "の10まんボルト! " + target.getName() + "に" + damage + "のダメージ!");
target.takeDamage(damage);
}
public void spark(Pokemon target) {
int damage = super.attackPower + (this.electricPower / 2);
System.out.println(super.getName() + "のスパーク! " + target.getName() + "に" + damage + "のダメージ!");
target.takeDamage(damage);
}
protected void setElectricPower(int electricPower) {
this.electricPower = electricPower;
}
protected int getElectricPower() {
return electricPower;
}
}
public class FirePokemon extends Pokemon {
private int firePower;
public FirePokemon(String name, int level, int hp, int attackPower) {
super(name, "ほのお", level, hp, attackPower);
this.firePower = 35;
}
public void flamethrower(Pokemon target) {
int damage = super.attackPower + this.firePower;
System.out.println(super.getName() + "のかえんほうしゃ! " + target.getName() + "に" + damage + "のダメージ!");
target.takeDamage(damage);
}
public void ember(Pokemon target) {
int damage = super.attackPower + (this.firePower / 2);
System.out.println(super.getName() + "のひのこ! " + target.getName() + "に" + damage + "のダメージ!");
target.takeDamage(damage);
}
protected void setFirePower(int firePower) {
this.firePower = firePower;
}
protected int getFirePower() {
return firePower;
}
}
public class GrassPokemon extends Pokemon {
private int grassPower;
public GrassPokemon(String name, int level, int hp, int attackPower) {
super(name, "くさ", level, hp, attackPower);
this.grassPower = 25;
}
public void vineWhip(Pokemon target) {
int damage = super.attackPower + this.grassPower;
System.out.println(super.getName() + "のつるのムチ! " + target.getName() + "に" + damage + "のダメージ!");
target.takeDamage(damage);
}
public void razorLeaf(Pokemon target) {
int damage = super.attackPower + (this.grassPower / 2);
System.out.println(super.getName() + "のはっぱカッター! " + target.getName() + "に" + damage + "のダメージ!");
target.takeDamage(damage);
}
protected void setGrassPower(int grassPower) {
this.grassPower = grassPower;
}
protected int getGrassPower() {
return grassPower;
}
}
5. 具体的なポケモンたち
考え方:
-
ElectricPokemon
はPokemon
を継承して宣言している -
Pikachu
Raichu
はElectricPokemon
を継承して宣言している
Pythonコード例
Python版具体的なポケモンクラス
class Pikachu(ElectricPokemon):
def __init__(self, level: int = 25):
super().__init__("ピカチュウ", level, 100, 55)
self._electric_power = 40 # ピカチュウは電気技が得意
def pika_pika(self) -> None:
print("ピカピカ〜!")
class Raichu(ElectricPokemon):
def __init__(self, level: int = 30):
super().__init__("ライチュウ", level, 120, 65)
self._electric_power = 50 # ライチュウはより強力
def rai_rai(self) -> None:
print("ライライ〜!")
class Charmander(FirePokemon):
def __init__(self, level: int = 5):
super().__init__("ヒトカゲ", level, 80, 45)
def char_char(self) -> None:
print("ヒトカゲ〜!")
class Bulbasaur(GrassPokemon):
def __init__(self, level: int = 5):
super().__init__("フシギダネ", level, 90, 40)
def bulba_bulba(self) -> None:
print("フシギダネ〜!")
Javaコード例
Java版具体的なポケモンクラス
public class Pikachu extends ElectricPokemon {
public Pikachu() {
this(25); // デフォルトレベル25
}
public Pikachu(int level) {
super("ピカチュウ", level, 100, 55);
super.setElectricPower(40); // ピカチュウは電気技が得意
}
public void pikaPika() {
System.out.println("ピカピカ〜!");
}
@Override
public void thunderbolt(Pokemon target) {
System.out.println("ピカチュウの必殺技!");
super.thunderbolt(target);
}
}
public class Raichu extends ElectricPokemon {
public Raichu() {
this(30); // デフォルトレベル30
}
public Raichu(int level) {
super("ライチュウ", level, 120, 65);
super.setElectricPower(50); // ライチュウはより強力
}
public void raiRai() {
System.out.println("ライライ〜!");
}
@Override
public void thunderbolt(Pokemon target) {
System.out.println("ライチュウの強力な電撃!");
super.thunderbolt(target);
}
}
public class Charmander extends FirePokemon {
public Charmander() {
this(5); // デフォルトレベル5
}
public Charmander(int level) {
super("ヒトカゲ", level, 80, 45);
}
public void charChar() {
System.out.println("ヒトカゲ〜!");
}
@Override
public void flamethrower(Pokemon target) {
System.out.println("ヒトカゲの炎攻撃!");
super.flamethrower(target);
}
}
public class Bulbasaur extends GrassPokemon {
public Bulbasaur() {
this(5); // デフォルトレベル5
}
public Bulbasaur(int level) {
super("フシギダネ", level, 90, 40);
}
public void bulbaBulba() {
System.out.println("フシギダネ〜!");
}
@Override
public void vineWhip(Pokemon target) {
System.out.println("フシギダネの草攻撃!");
super.vineWhip(target);
}
}
6. 関連関係を表現する
ポケモンとトレーナーの関係も表現できます。
関連の読み方:
- トレーナーは1〜6匹のポケモンを持っている
- トレーナーは複数のモンスターボールを使用する
Pythonコード例
Python版ポケモンとトレーナーの関連クラス
from typing import List, Optional
class Trainer:
def __init__(self, name: str):
self._name = name
self._pokemons: List[Pokemon] = []
self._badges = 0
self._pokeballs: List['PokeBall'] = []
def get_name(self) -> str:
return self._name
def catch_pokemon(self, pokemon: Pokemon, pokeball: 'PokeBall') -> bool:
if len(self._pokemons) >= 6:
print(f"{self._name}は既に6匹のポケモンを持っています!")
return False
if pokeball.catch_pokemon(pokemon):
self._pokemons.append(pokemon)
print(f"{self._name}は{pokemon.get_name()}を捕まえた!")
return True
else:
print(f"{pokemon.get_name()}は逃げてしまった...")
return False
def send_pokemon(self, index: int = 0) -> Optional[Pokemon]:
if 0 <= index < len(self._pokemons):
pokemon = self._pokemons[index]
print(f"{self._name}は{pokemon.get_name()}を繰り出した!")
return pokemon
return None
def use_pokeball(self, pokeball_type: str = "モンスターボール") -> Optional['PokeBall']:
for ball in self._pokeballs:
if ball.get_type() == pokeball_type:
self._pokeballs.remove(ball)
return ball
return None
def add_pokeball(self, pokeball: 'PokeBall') -> None:
self._pokeballs.append(pokeball)
def battle_with(self, other_trainer: 'Trainer') -> None:
print(f"{self._name} VS {other_trainer.get_name()}のバトル開始!")
my_pokemon = self.send_pokemon(0)
enemy_pokemon = other_trainer.send_pokemon(0)
if my_pokemon and enemy_pokemon:
my_pokemon.attack(enemy_pokemon)
def get_pokemon_count(self) -> int:
return len(self._pokemons)
def __str__(self) -> str:
pokemon_names = [p.get_name() for p in self._pokemons]
return f"トレーナー {self._name} (バッジ: {self._badges}, ポケモン: {pokemon_names})"
class PokeBall:
def __init__(self, ball_type: str = "モンスターボール"):
self._type = ball_type
self._catch_rate = self._get_catch_rate(ball_type)
def _get_catch_rate(self, ball_type: str) -> float:
rates = {
"モンスターボール": 0.7,
"スーパーボール": 0.8,
"ハイパーボール": 0.9,
"マスターボール": 1.0
}
return rates.get(ball_type, 0.7)
def get_type(self) -> str:
return self._type
def catch_pokemon(self, pokemon: Pokemon) -> bool:
import random
success = random.random() < self._catch_rate
print(f"{self._type}を投げた!")
return success
Javaコード例
Java版ポケモンとトレーナーの関連クラス
import java.util.*;
public class Trainer {
private String name;
private List<Pokemon> pokemons;
private int badges;
private List<PokeBall> pokeballs;
public Trainer(String name) {
this.name = name;
this.pokemons = new ArrayList<>();
this.badges = 0;
this.pokeballs = new ArrayList<>();
}
public String getName() {
return name;
}
public boolean catchPokemon(Pokemon pokemon, PokeBall pokeball) {
if (pokemons.size() >= 6) {
System.out.println(name + "は既に6匹のポケモンを持っています!");
return false;
}
if (pokeball.catchPokemon(pokemon)) {
pokemons.add(pokemon);
System.out.println(name + "は" + pokemon.getName() + "を捕まえた!");
return true;
} else {
System.out.println(pokemon.getName() + "は逃げてしまった...");
return false;
}
}
public Pokemon sendPokemon() {
return sendPokemon(0);
}
public Pokemon sendPokemon(int index) {
if (index >= 0 && index < pokemons.size()) {
Pokemon pokemon = pokemons.get(index);
System.out.println(name + "は" + pokemon.getName() + "を繰り出した!");
return pokemon;
}
return null;
}
public PokeBall usePokeball(String ballType) {
for (Iterator<PokeBall> it = pokeballs.iterator(); it.hasNext();) {
PokeBall ball = it.next();
if (ball.getType().equals(ballType)) {
it.remove();
return ball;
}
}
return null;
}
public void addPokeball(PokeBall pokeball) {
pokeballs.add(pokeball);
}
public void battleWith(Trainer otherTrainer) {
System.out.println(name + " VS " + otherTrainer.getName() + "のバトル開始!");
Pokemon myPokemon = sendPokemon(0);
Pokemon enemyPokemon = otherTrainer.sendPokemon(0);
if (myPokemon != null && enemyPokemon != null) {
myPokemon.attack(enemyPokemon);
}
}
public int getPokemonCount() {
return pokemons.size();
}
public List<Pokemon> getPokemons() {
return new ArrayList<>(pokemons); // 防御的コピー
}
@Override
public String toString() {
List<String> pokemonNames = new ArrayList<>();
for (Pokemon p : pokemons) {
pokemonNames.add(p.getName());
}
return "トレーナー " + name + " (バッジ: " + badges + ", ポケモン: " + pokemonNames + ")";
}
}
public class PokeBall {
private String type;
private double catchRate;
private static final Random random = new Random();
public PokeBall() {
this("モンスターボール");
}
public PokeBall(String type) {
this.type = type;
this.catchRate = getCatchRate(type);
}
private double getCatchRate(String ballType) {
switch (ballType) {
case "モンスターボール":
return 0.7;
case "スーパーボール":
return 0.8;
case "ハイパーボール":
return 0.9;
case "マスターボール":
return 1.0;
default:
return 0.7;
}
}
public String getType() {
return type;
}
public boolean catchPokemon(Pokemon pokemon) {
System.out.println(type + "を投げた!");
boolean success = random.nextDouble() < catchRate;
if (success) {
System.out.println("やったー! " + pokemon.getName() + "を捕まえた!");
} else {
System.out.println("あー! " + pokemon.getName() + "は逃げてしまった...");
}
return success;
}
}
7. 実際の設計での活用
7.1 要件からクラスを抽出する
「ポケモンバトルシステムを作る」という要件から:
- 名詞を探す → ポケモン、トレーナー、技、アイテム
- 動詞を探す → 攻撃する、回復する、捕まえる
- 名詞がクラス、動詞がメソッドになる
7.2 完成したクラス図例
Pythonコード例
Python版クラス例
from typing import List
from enum import Enum
class SkillType(Enum):
ELECTRIC = "でんき"
FIRE = "ほのお"
GRASS = "くさ"
NORMAL = "ノーマル"
class Skill:
def __init__(self, name: str, power: int, skill_type: SkillType):
self._name = name
self._power = power
self._type = skill_type
def get_name(self) -> str:
return self._name
def get_power(self) -> int:
return self._power
def get_type(self) -> SkillType:
return self._type
def execute(self, user: Pokemon, target: Pokemon) -> None:
damage = self._power
print(f"{user.get_name()}の{self._name}!")
print(f"{target.get_name()}に{damage}のダメージ!")
target.take_damage(damage)
class BattleSystem:
def __init__(self):
self._current_battle = None
def start_battle(self, trainer1: Trainer, trainer2: Trainer) -> None:
print("=" * 50)
print(f"ポケモンバトル開始!")
print(f"{trainer1.get_name()} VS {trainer2.get_name()}")
print("=" * 50)
pokemon1 = trainer1.send_pokemon(0)
pokemon2 = trainer2.send_pokemon(0)
if pokemon1 and pokemon2:
self._battle_loop(pokemon1, pokemon2)
def _battle_loop(self, pokemon1: Pokemon, pokemon2: Pokemon) -> None:
turn = 1
while pokemon1.is_alive() and pokemon2.is_alive():
print(f"\n--- ターン {turn} ---")
# ポケモン1の攻撃
if pokemon1.is_alive():
pokemon1.attack(pokemon2)
# ポケモン2の攻撃
if pokemon2.is_alive():
pokemon2.attack(pokemon1)
turn += 1
# 10ターンで強制終了
if turn > 10:
print("バトルは引き分けに終わった...")
break
self.end_battle(pokemon1, pokemon2)
def end_battle(self, pokemon1: Pokemon, pokemon2: Pokemon) -> None:
print("\n" + "=" * 50)
if pokemon1.is_alive() and not pokemon2.is_alive():
print(f"{pokemon1.get_name()}の勝利!")
elif pokemon2.is_alive() and not pokemon1.is_alive():
print(f"{pokemon2.get_name()}の勝利!")
else:
print("引き分け!")
print("=" * 50)
# 使用例
def main():
# ポケモンを作成
pikachu = Pikachu(25)
raichu = Raichu(30)
charmander = Charmander(5)
# トレーナーを作成
satoshi = Trainer("サトシ")
shigeru = Trainer("シゲル")
# モンスターボールを作成
pokeball1 = PokeBall("スーパーボール")
pokeball2 = PokeBall("ハイパーボール")
# トレーナーにモンスターボールを渡す
satoshi.add_pokeball(pokeball1)
shigeru.add_pokeball(pokeball2)
# ポケモンを捕まえる
satoshi.catch_pokemon(pikachu, pokeball1)
shigeru.catch_pokemon(raichu, pokeball2)
# トレーナー情報を表示
print(satoshi)
print(shigeru)
# バトルシステムでバトル開始
battle_system = BattleSystem()
battle_system.start_battle(satoshi, shigeru)
# 技を使ってみる
print("\n--- 特別技のデモ ---")
pikachu.thunderbolt(charmander)
charmander.flamethrower(pikachu)
if __name__ == "__main__":
main()
Java版クラス例
import java.util.*;
public enum SkillType {
ELECTRIC("でんき"),
FIRE("ほのお"),
GRASS("くさ"),
NORMAL("ノーマル");
private final String typeName;
SkillType(String typeName) {
this.typeName = typeName;
}
public String getTypeName() {
return typeName;
}
}
public class Skill {
private String name;
private int power;
private SkillType type;
public Skill(String name, int power, SkillType type) {
this.name = name;
this.power = power;
this.type = type;
}
public String getName() {
return name;
}
public int getPower() {
return power;
}
public SkillType getType() {
return type;
}
public void execute(Pokemon user, Pokemon target) {
int damage = this.power;
System.out.println(user.getName() + "の" + this.name + "!");
System.out.println(target.getName() + "に" + damage + "のダメージ!");
target.takeDamage(damage);
}
}
public class Pokemon {
private String name;
private String type;
private int level;
private int hp;
private int maxHp;
private int attackPower;
private List<Skill> skills;
public Pokemon(String name, String type, int level, int hp, int attackPower) {
this.name = name;
this.type = type;
this.level = level;
this.hp = hp;
this.maxHp = hp;
this.attackPower = attackPower;
this.skills = new ArrayList<>();
}
public String getName() {
return name;
}
public String getType() {
return type;
}
public int getLevel() {
return level;
}
public int getHp() {
return hp;
}
public void attack(Pokemon target) {
int damage = this.attackPower;
System.out.println(this.name + "の攻撃! " + target.getName() + "に" + damage + "のダメージ!");
target.takeDamage(damage);
}
public void takeDamage(int damage) {
this.hp -= damage;
if (this.hp < 0) {
this.hp = 0;
}
System.out.println(this.name + "の残りHP: " + this.hp);
}
public void levelUp() {
this.level++;
this.hp += 10;
this.maxHp += 10;
this.attackPower += 5;
System.out.println(this.name + "がレベルアップ! レベル" + this.level + "になった!");
}
public boolean isAlive() {
return this.hp > 0;
}
public void addSkill(Skill skill) {
if (skills.size() < 4) {
skills.add(skill);
System.out.println(name + "は" + skill.getName() + "を覚えた!");
} else {
System.out.println(name + "は既に4つの技を覚えています!");
}
}
public void useSkill(int skillIndex, Pokemon target) {
if (skillIndex >= 0 && skillIndex < skills.size()) {
Skill skill = skills.get(skillIndex);
skill.execute(this, target);
} else {
System.out.println("その技は覚えていません!");
}
}
public List<Skill> getSkills() {
return new ArrayList<>(skills);
}
@Override
public String toString() {
return name + "(Lv." + level + ", HP:" + hp + "/" + maxHp + ")";
}
}
public class Trainer {
private String name;
private List<Pokemon> pokemons;
private int badges;
public Trainer(String name) {
this.name = name;
this.pokemons = new ArrayList<>();
this.badges = 0;
}
public String getName() {
return name;
}
public void addPokemon(Pokemon pokemon) {
if (pokemons.size() < 6) {
pokemons.add(pokemon);
System.out.println(name + "は" + pokemon.getName() + "を手持ちに加えた!");
} else {
System.out.println(name + "は既に6匹のポケモンを持っています!");
}
}
public Pokemon sendPokemon() {
return sendPokemon(0);
}
public Pokemon sendPokemon(int index) {
if (index >= 0 && index < pokemons.size()) {
Pokemon pokemon = pokemons.get(index);
System.out.println(name + "は" + pokemon.getName() + "を繰り出した!");
return pokemon;
}
return null;
}
public void battleWith(Trainer otherTrainer) {
System.out.println(name + " VS " + otherTrainer.getName() + "のバトル開始!");
Pokemon myPokemon = sendPokemon(0);
Pokemon enemyPokemon = otherTrainer.sendPokemon(0);
if (myPokemon != null && enemyPokemon != null) {
myPokemon.attack(enemyPokemon);
}
}
public int getPokemonCount() {
return pokemons.size();
}
public List<Pokemon> getPokemons() {
return new ArrayList<>(pokemons);
}
@Override
public String toString() {
List<String> pokemonNames = new ArrayList<>();
for (Pokemon p : pokemons) {
pokemonNames.add(p.getName());
}
return "トレーナー " + name + " (バッジ: " + badges + ", ポケモン: " + pokemonNames + ")";
}
}
public class BattleSystem {
private boolean currentBattle;
public BattleSystem() {
this.currentBattle = false;
}
public void startBattle(Trainer trainer1, Trainer trainer2) {
System.out.println("=".repeat(50));
System.out.println("ポケモンバトル開始!");
System.out.println(trainer1.getName() + " VS " + trainer2.getName());
System.out.println("=".repeat(50));
Pokemon pokemon1 = trainer1.sendPokemon(0);
Pokemon pokemon2 = trainer2.sendPokemon(0);
if (pokemon1 != null && pokemon2 != null) {
currentBattle = true;
battleLoop(pokemon1, pokemon2);
}
}
private void battleLoop(Pokemon pokemon1, Pokemon pokemon2) {
int turn = 1;
while (pokemon1.isAlive() && pokemon2.isAlive() && turn <= 10) {
System.out.println("\n--- ターン " + turn + " ---");
// ポケモン1の攻撃
if (pokemon1.isAlive()) {
pokemon1.attack(pokemon2);
}
// ポケモン2の攻撃
if (pokemon2.isAlive()) {
pokemon2.attack(pokemon1);
}
turn++;
}
endBattle(pokemon1, pokemon2);
}
public void endBattle(Pokemon pokemon1, Pokemon pokemon2) {
System.out.println("\n" + "=".repeat(50));
if (pokemon1.isAlive() && !pokemon2.isAlive()) {
System.out.println(pokemon1.getName() + "の勝利!");
} else if (pokemon2.isAlive() && !pokemon1.isAlive()) {
System.out.println(pokemon2.getName() + "の勝利!");
} else {
System.out.println("引き分け!");
}
System.out.println("=".repeat(50));
currentBattle = false;
}
public boolean isInBattle() {
return currentBattle;
}
}
// 使用例とメインクラス
public class PokemonBattleSystem {
public static void main(String[] args) {
// ポケモンを作成
Pokemon pikachu = new Pokemon("ピカチュウ", "でんき", 25, 100, 55);
Pokemon charmander = new Pokemon("ヒトカゲ", "ほのお", 20, 80, 50);
Pokemon bulbasaur = new Pokemon("フシギダネ", "くさ", 18, 90, 45);
// スキルを作成
Skill thunderbolt = new Skill("10まんボルト", 90, SkillType.ELECTRIC);
Skill flamethrower = new Skill("かえんほうしゃ", 85, SkillType.FIRE);
Skill vineWhip = new Skill("つるのムチ", 70, SkillType.GRASS);
Skill tackle = new Skill("たいあたり", 40, SkillType.NORMAL);
// ポケモンにスキルを覚えさせる
pikachu.addSkill(thunderbolt);
pikachu.addSkill(tackle);
charmander.addSkill(flamethrower);
charmander.addSkill(tackle);
bulbasaur.addSkill(vineWhip);
bulbasaur.addSkill(tackle);
// トレーナーを作成
Trainer satoshi = new Trainer("サトシ");
Trainer shigeru = new Trainer("シゲル");
// トレーナーにポケモンを渡す
satoshi.addPokemon(pikachu);
satoshi.addPokemon(charmander);
shigeru.addPokemon(bulbasaur);
// トレーナー情報を表示
System.out.println(satoshi);
System.out.println(shigeru);
// バトルシステムでバトル開始
BattleSystem battleSystem = new BattleSystem();
battleSystem.startBattle(satoshi, shigeru);
// スキル使用のデモ
System.out.println("\n=== スキル使用デモ ===");
pikachu.useSkill(0, charmander); // 10まんボルト
charmander.useSkill(0, bulbasaur); // かえんほうしゃ
bulbasaur.useSkill(0, pikachu); // つるのムチ
}
}
まとめ
クラス図は以下の手順で作成できます:
- 要件を分析して、登場する「もの」(名詞)を見つける
- クラス名を決める
- 属性(そのクラスが持つデータ)を決める
- メソッド(そのクラスができること)を決める
- クラス間の関係(継承、関連)を決める