beginner11
@beginner11

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

以前アドバイスをいただいて、改良したPythonプログラムに手を加えたい!

今回の質問概要について

以前自分で作り、@shiracamus(しらかみゅ)様からアドバイスを頂いて、改良したPythonのゲームプログラムにさらに手を加えて「武器選択による難易度調整」がしたいと思いまして…。しかし試行錯誤するもなかなか上手くいかず今に至ります。
どなたか解決できそうな方がいらっしゃれば嬉しいのですが…。

発生している問題・エラー

Traceback (most recent call last):
  File "c:\VSCODE Python\battle_game_code1.5.py", line 314, in <module>
    main()
  File "c:\VSCODE Python\battle_game_code1.5.py", line 286, in main
    weapon_select()
  File "c:\VSCODE Python\battle_game_code1.5.py", line 271, in weapon_select
    weapon=Weapon()
           ^^^^^^^^
TypeError: Weapon.__init__() missing 3 required positional arguments: 'name', 'minimum', and 'maximam'

該当するソースコード

battle_game_code1.5.py
import time
import sys
import random
from typing import Callable

class Point:
    #ヒットポイント、マジックポイントなどいろいろステータス

    def __init__(self,point: int) -> None:
        self._remain: int=point
        self._max: int=point
    
    def __str__(self) -> str:
        return str(self._remain)
    
    def use(self,point:int)->bool:
        #point分使えるならTrueを返す、ポイント不足ならFalseを返す
        if self._remain<point:
            return False
        self.damage(point)
        return True
    
    def damage(self,point:int)->None:
        self._remain-=point

    def charge(self,point:int)->None:
        self._remain=min(self._remain+point,self._max)

    def is_full(self)->bool:
        return self._remain == self._max
    
    def is_empty(self)->bool:
        return self._remain<=0
    
class Power:
    #武器攻撃力のクラス
    def __init__(self, minimum: int, maximum: int) -> None:
        self._points: range = range(minimum, maximum + 1)

    def use(self) -> int:
        """力を使う、ポイントを返す"""
        return random.choice(self._points)

class Magic:
    #魔法攻撃のクラス
    def __init__(self, name: str, point: int, power: Power) -> None:
        self._name: str = name # プレイヤー名
        self._point: int = point  # 魔法を使用するのに必要なポイント
        self._power: Power = power #攻撃

    #魔法名格納
    def __str__(self) -> str:
        return self._name

    def use(self, mp: Point) -> int:
        """mpを消費して魔法を使う。攻撃ポイントを返す"""
        if mp.use(self._point):
            return self._power.use()
        else:
            return 0  # mp不足
        
class HealthPosion:

    def __init__(self,remain=1,point=100):
        self._remain=remain
        self._point=point

    def remain(self):
        return self._remain
    
    def use(self,hp: Point):
        #ポーションがあるならhpを回復してTrueを返す、ないならFalseを返す
        if self._remain<=0:
            return False
        self._remain-=1
        hp.charge(self._point)
        return True
    
class Character:
    #プレイヤーと敵モンスターのデータの源!

    #ここはキャラクターの雛型
    def __init__(self,name:str,health_point: int, magic_point: int,weapon:Power,shield:Power)->None:
        self._name: str=name
        self._hp:Point=Point(health_point)
        self._mp:Point=Point(magic_point)
        self._weapon:Power=weapon
        self._shield:Power=shield

    #入力した名前を返す
    def __str__(self)->str:
        return str(self._name)
    
    #キャラクターのセリフを出力
    def _message(self,text:str,wait:int=1)->None:
        print(f"{self}:{text}")
        time.sleep(wait)

    #メッセージを出力
    def status(self)->str:
        return f"{self}のHP:{self._hp}、MP:{self._mp}"
    
    def defense(self,point:int)->int:
        #攻撃を防御する
        return self._damage(point//2-self._shield.use()//4)
    
    #ダメージ表示
    def _damage(self,point)->int:
        self._hp.damage(point)
        self._message(f"{point}のダメージ")
        return point
    
    #死亡時の返しの橋渡し
    def is_dead(self)->bool:
        return self._hp.is_empty()

class Weapon(Power):
    def __init__(self,name,minimum,maximam):
        self._name=name
        self._minimum=minimum 
        self._maximam=maximam

class WeaponSelect(Weapon):
    def __init__(self,name,minimum,maximam):
        self._name=name
        self._minimum=minimum 
        self._maximam=maximam
        self._COMMANDS: dict[str,Callable[[Character],bool]]={
            'm':self._master_blade,
            'b':self._big_sword,
            's':self._smart_dagger,
        }

    def weapon_select(self,player:Character)->bool:
        print("------------------------------------------------")
        print("|m:マスターブレード,b:ビッグソード,s:スマートダガー|")
        print("------------------------------------------------")
        while((command:=input("選択>>>"))not in self._COMMANDS or not self._COMMANDS[command](player)):
            pass

    def _master_blade(self)->bool:
        super().__init__("マスターブレード",100,110)
        return True

    def _big_sword(self)->bool:
        super().__init__("ビッグソード",85,90)
        return True

    def _smart_dagger(self)->bool:
        super().__init__("スマートダガー",60,70)
        return True

#プレイヤーのクラス    
class Player(Character):

    def __init__(self,name:str)->None:
        super().__init__(name,300,30,Power(0,0),Power(40,45))
        self._is_guard: bool=False
        self._health_posion: HealthPosion=HealthPosion(5)
        self._COMMANDS: dict[str,Callable[[Character],bool]]={
            'a':self._use_weapon,
            'm':self._use_magic,
            's':self._use_strong_magic,
            'g':self._guard,
            'd':self._heal,
        }

    def status(self)->str:
        return f"{super().status()}、回復薬:{self._health_posion.remain()}"
    
    #防御
    def defense(self,point:int)->int:
        if self._is_guard:
            self._is_guard=False
            if random.random()>=0.1:
                self._message("攻撃を弾いた!")
                return 0
        return super().defense(point)
    
    #攻撃
    def attack(self,monster:Character)->None:
        print("------------------------------------------------------")
        print("|a:攻撃、m:攻撃魔法、s:強力攻撃魔法、g:防御、d:回復薬|")
        print("------------------------------------------------------")
        while((command:=input("選択>>>"))not in self._COMMANDS or not self._COMMANDS[command](monster)):
            pass

    #攻撃
    def _use_weapon(self,monster:Character)->bool:
        self._message(f"「このォ!」")
        monster.defense(self._weapon.use())
        return True
    
    #攻撃魔法
    def _use_magic(self,monster:Character,magic:Magic=Magic("サンダーシュート",5,Power(85,90)))->bool:
        point = magic.use(self._mp)
        if point == 0:
            self._message(f"「MPが足りない!」")
            return False  # 再入力
        self._message(f"{magic}!」", 0)
        monster.defense(point)
        return True

    #強力魔法攻撃
    def _use_strong_magic(self,monster:Character, magic:Magic = Magic("フレイムバースト", 10, Power(105, 110))) -> bool:
        return self._use_magic(monster, magic)
    
    #防御
    def _guard(self,monster)->bool:
        self._is_guard = True
        self._message(f"「盾で防ぐぞ!」")
        return True

    #回復
    def _heal(self,monster:Character) -> bool:
        if self._hp.is_full():
            self._message(f"「今はいらないな」")
            return False #再入力
        if self._health_posion.use(self._hp):
            self._message(f"「力がみなぎって来たぞ!」\nライフが回復した!")
            return True
        else:
            self._message(f"「回復薬が無い!」")
            return False #再入力

#モンスターのクラス
class Monster(Character):

    def __init__(self, name: str, hp: int, mp: int, ap: Power, sp: int, magic: Magic) -> None:
        super().__init__(name, hp, mp, ap, Power(sp, sp))
        self._magic: Magic = magic

    def attack(self, player: Character) -> None:
        if random.random() > 0.3:
            point = self._weapon.use()
            self._message(f"「喰らえ!」", 0)
        else:
            point = self._magic.use(self._mp)
            if point == 0:
                self._message("「MPが足りない!」")
                return
            self._message(f"{self._magic}!」", 0)
        if player.defense(point) == 0:
            self._message("「やるな」")

#モンスターの一覧   
MONSTERS=(
    Monster("ゴーストナイト",200,30,Power(50,55),20,
        Magic("ダークスラッシュ",5,Power(60,65))),
    Monster("ギルドラゴン",270,40,Power(60,65),25,
        Magic("バーンフレイム",5,Power(70,75))),
    Monster("ダークウィザー",220,50,Power(70,75),25,
        Magic("キルストーム",5,Power(60,65))),
    Monster("ネビュラシーザー",300,60,Power(80,85),30,
        Magic("ヘル・デストロイ",5,Power(100,105))),    
)

#タイトル表示
def show_title()->None:
    print("*************************************")
    print("*かんたんクエスト ~勇者よいそげ!~*")
    print("*************************************")

def entry_player()->Player:
    #プレイヤー登場
    name=input("名前を入力してください>>>")
    print(f"勇者{name}よ、行け!")
    return Player(name)

def weapon_select()->WeaponSelect:
    weapon=Weapon()
    print(f'{weapon._name}で行く!')
    return Weapon(Weapon._minimum,Weapon._maximam)

def appear_monster()->Monster:
    #モンスター出現
    monster=random.choice(MONSTERS)
    print(f"{monster}出現!")
    return monster
       
def main()->None:
    #主なゲームの流れ一式
    show_title()
    player=entry_player()
    time.sleep(1)
    weapon_select()
    time.sleep(1)
    monster=appear_monster()
    time.sleep(1)

    while True:
        print()
        print(player.status())
        print(monster.status())
        time.sleep(2)

        print(f"\n***{player}のターン!***")
        player.attack(monster)
        if monster.is_dead():
            print("モンスターを倒した!\n")
            print("************")
            print("*GAME CLEAR*")
            print("************")
            return

        print(f"\n***{monster}のターン!***")
        monster.attack(player)
        if player.is_dead():
            print("{player}は敗れた・・・\n")
            print("GAME OVER")
            return
        
if __name__=="__main__":
    main()

試してみたこと

 様々なWebサイトを調べてみたものの、なかなか決定打となる情報が無いため今なお困っています。
もしかすると、初歩的なミスが最大の原因になっているのではないかとも思うのですが、分からずじまいです。お答えできる方、どうかコメントをお願いします。

0

1Answer

クラスは「名詞」で表現できるモノ・コト(者・物・事)を定義します。
武器を選択するのは「動詞」なので、関数やメソッドにします。
武器はプレイヤーが持つので、選択した武器はプレイヤーに渡すといいですよ。

コードの書き方についてですが、関数、クラス、メソッドの説明は、定義直後に文字列で書いておくと、ヘルプやドキュメント生成に使えるので便利ですよ。
それと、「PEP8: Pythonコードのスタイルガイド」に従って、代入や演算子の前後やカンマ直後には空白を入れましょう。autopep8、flake8、ruffなどの清書コマンドが便利です。IDEにも清書機能があります。

import time
import sys
import random
from typing import Callable


class Point:
    """ヒットポイント、マジックポイントなど"""

    def __init__(self, point: int) -> None:
        self._remain: int = point
        self._max: int = point

    def __str__(self) -> str:
        """表示文字列を返す"""
        return str(self._remain)

    def use(self, point: int) -> bool:
        """point分使えるならTrueを返す、ポイント不足ならFalseを返す"""
        if self._remain < point:
            return False
        self.damage(point)
        return True

    def damage(self, point: int) -> None:
        self._remain -= point

    def charge(self, point: int) -> None:
        self._remain = min(self._remain+point, self._max)

    def is_full(self) -> bool:
        return self._remain == self._max

    def is_empty(self) -> bool:
        return self._remain <= 0


class Power:
    """武器攻撃力"""

    def __init__(self, minimum: int, maximum: int) -> None:
        self._points: range = range(minimum, maximum + 1)

    def use(self) -> int:
        """力を使う、ポイントを返す"""
        return random.choice(self._points)


class Magic:
    """魔法攻撃"""

    def __init__(self, name: str, point: int, power: Power) -> None:
        self._name: str = name  # プレイヤー名
        self._point: int = point  # 魔法を使用するのに必要なポイント
        self._power: Power = power  # 攻撃

    def __str__(self) -> str:
        """表示文字列を返す"""
        return self._name

    def use(self, mp: Point) -> int:
        """mpを消費して魔法を使う。攻撃ポイントを返す"""
        if mp.use(self._point):
            return self._power.use()
        else:
            return 0  # mp不足


class HealthPosion:
    """回復薬"""

    def __init__(self, remain=1, point=100) -> None:
        self._remain: int = remain
        self._point: int = point

    def remain(self) -> int:
        return self._remain

    def use(self, hp: Point) -> bool:
        """ポーションがあるならhpを回復してTrueを返す、ないならFalseを返す"""
        if self._remain < 1:
            return False
        self._remain -= 1
        hp.charge(self._point)
        return True


class Character:
    """プレイヤーと敵モンスターの共通部分"""

    def __init__(self, name: str, health_point: int, magic_point: int, weapon: Power, shield: Power) -> None:
        self._name: str = name
        self._hp: Point = Point(health_point)
        self._mp: Point = Point(magic_point)
        self._weapon: Power = weapon
        self._shield: Power = shield

    def __str__(self) -> str:
        """表示文字列を返す"""
        return str(self._name)

    def _message(self, text: str, wait: int = 1) -> None:
        """メッセージを出力して時間待ちする"""
        print(f"{self}:{text}")
        time.sleep(wait)

    def status(self) -> str:
        """ステータスを返す"""
        return f"{self}のHP:{self._hp}、MP:{self._mp}"

    def defense(self, point: int) -> int:
        """攻撃を防御する"""
        return self._damage(point//2-self._shield.use()//4)

    def _damage(self, point) -> int:
        """ダメージ処理"""
        self._hp.damage(point)
        self._message(f"{point}のダメージ")
        return point

    def is_dead(self) -> bool:
        """死亡していたらTrueを返す"""
        return self._hp.is_empty()


class Weapon(Power):

    def __init__(self, name, minimum, maximum) -> None:
        self._name = name
        super().__init__(minimum, maximum)

    def __str__(self) -> str:
        """表示文字列を返す"""
        return self._name


class Player(Character):

    def __init__(self, name: str, weapon) -> None:
        super().__init__(name, 300, 30, Power(0, 0), Power(40, 45))
        self._weapon: Weapon = weapon
        self._message(f"{weapon}で行く!")
        self._is_guard: bool = False
        self._health_posion: HealthPosion = HealthPosion(5)
        self._COMMANDS: dict[str, Callable[[Character], bool]] = {
            "a": self._use_weapon,
            "m": self._use_magic,
            "s": self._use_strong_magic,
            "g": self._guard,
            "d": self._heal,
        }

    def status(self) -> str:
        return f"{super().status()}、回復薬:{self._health_posion.remain()}"

    def defense(self, point: int) -> int:
        """防御する"""
        if self._is_guard:
            self._is_guard = False
            if random.random() >= 0.1:
                self._message("攻撃を弾いた!")
                return 0
        return super().defense(point)

    def attack(self, monster: Character) -> None:
        """攻撃する"""
        print("------------------------------------------------------")
        print("|a:攻撃、m:攻撃魔法、s:強力攻撃魔法、g:防御、d:回復薬|")
        print("------------------------------------------------------")
        while ((command := input("選択>>>"))not in self._COMMANDS or not self._COMMANDS[command](monster)):
            pass

    def _use_weapon(self, monster: Character) -> bool:
        """武器を使って攻撃する"""
        self._message("「このォ!」")
        monster.defense(self._weapon.use())
        return True

    def _use_magic(self, monster: Character, magic: Magic = Magic("サンダーシュート", 5, Power(85, 90))) -> bool:
        """魔法を使って攻撃する"""
        point = magic.use(self._mp)
        if point <= 0:
            self._message("「MPが足りない!」")
            return False  # 再入力
        self._message(f"{magic}!」", 0)
        monster.defense(point)
        return True

    def _use_strong_magic(self, monster: Character, magic: Magic = Magic("フレイムバースト", 10, Power(105, 110))) -> bool:
        """強力魔法を使って攻撃する"""
        return self._use_magic(monster, magic)

    def _guard(self, monster) -> bool:
        """盾を使って防御する"""
        self._is_guard = True
        self._message("「盾で防ぐぞ!」")
        return True

    def _heal(self, monster: Character) -> bool:
        """生命力を回復する"""
        if self._hp.is_full():
            self._message("「今はいらないな」")
            return False  # 再入力
        if self._health_posion.use(self._hp):
            self._message("「力がみなぎって来たぞ!」\nライフが回復した!")
            return True
        else:
            self._message("「回復薬が無い!」")
            return False  # 再入力


class Monster(Character):

    def __init__(self, name: str, hp: int, mp: int, ap: Power, sp: int, magic: Magic) -> None:
        super().__init__(name, hp, mp, ap, Power(sp, sp))
        self._magic: Magic = magic

    def attack(self, player: Character) -> None:
        if random.random() > 0.3:
            point = self._weapon.use()
            self._message("「喰らえ!」", 0)
        else:
            point = self._magic.use(self._mp)
            if point <= 0:
                self._message("「MPが足りない!」")
                return
            self._message(f"{self._magic}!」", 0)
        if player.defense(point) == 0:
            self._message("「やるな」")


# モンスターの一覧
MONSTERS = (
    Monster("ゴーストナイト", 200, 30, Power(50, 55), 20,
            Magic("ダークスラッシュ", 5, Power(60, 65))),
    Monster("ギルドラゴン", 270, 40, Power(60, 65), 25,
            Magic("バーンフレイム", 5, Power(70, 75))),
    Monster("ダークウィザー", 220, 50, Power(70, 75), 25,
            Magic("キルストーム", 5, Power(60, 65))),
    Monster("ネビュラシーザー", 300, 60, Power(80, 85), 30,
            Magic("ヘル・デストロイ", 5, Power(100, 105))),
)

# 武器の一覧
WEAPONS = {
    "m": Weapon("マスターブレード", 100, 110),
    "b": Weapon("ビッグソード", 85, 90),
    "s": Weapon("スマートダガー", 60, 70),
}


def show_title() -> None:
    """タイトル表示"""
    print("*************************************")
    print("*かんたんクエスト ~勇者よいそげ!~*")
    print("*************************************")


def select_weapon() -> Weapon:
    """武器選択"""
    print("\n" + ", ".join(f"{key}:{weapon}" for key, weapon in WEAPONS.items()))
    while (key := input("武器を選択してください>>>")) not in WEAPONS:
        pass
    return WEAPONS[key]


def entry_player() -> Player:
    """プレイヤー登場"""
    name = input("名前を入力してください>>>")
    weapon = select_weapon()
    print(f"\n勇者{name}よ、行け!")
    return Player(name, weapon)


def appear_monster() -> Monster:
    """モンスター出現"""
    monster = random.choice(MONSTERS)
    print(f"{monster}出現!")
    return monster


def main() -> None:
    """主なゲームの流れ"""
    show_title()
    player = entry_player()
    time.sleep(1)
    print()
    monster = appear_monster()
    time.sleep(1)

    while True:
        print()
        print(player.status())
        print(monster.status())
        time.sleep(2)

        print(f"\n***{player}のターン!***")
        player.attack(monster)
        if monster.is_dead():
            print("モンスターを倒した!\n")
            print("************")
            print("*GAME CLEAR*")
            print("************")
            return

        print(f"\n***{monster}のターン!***")
        monster.attack(player)
        if player.is_dead():
            print(f"{player}は敗れた・・・\n")
            print("GAME OVER")
            return


if __name__ == "__main__":
    main()
1Like

Comments

  1. @beginner11

    Questioner

    しらかみゅさん、再びアドバイスありがとうございます。
    何度もお時間を割いてしまって申し訳ございません…。

Your answer might help someone💌