【问题标题】:Using a player's stats in multiple different classes在多个不同类别中使用玩家的统计数据
【发布时间】:2017-07-10 01:13:07
【问题描述】:

我正在制作一款文字冒险RPG游戏,你可以在其中进入一场战斗,并跟随一个半开放世界的故事。我创建了一个玩家类,我用它来保存所有玩家的统计数据。

public class Player {

    // Generic Stats
    int playerLevel = 1;
    int playerHealth = 20;
    int EXP = 0;
    long money = 0;
    String name = "";
    String homeland = "";

    // Skills
    int fighting = 5;
    int block = 5;
    int doctor = 5;
    int speech = 5;

    // Attributes
    int damage = fighting * 2;

    // Prints the player's stats
    public void printStats() {          
        System.out.println();
        System.out.println("Level: " + playerLevel);
        System.out.println("EXP: " + EXP);
        System.out.println("HP: " + playerHealth);
        System.out.println("Money: " + money);
        System.out.println("Name: " + name);
        System.out.println("Homeland: " + homeland );
        System.out.println("Skills: Fighting: " + fighting + " Block: " + block + "Doctor: " + doctor + " Speech: " + speech);
        System.out.println();
    }

    // Changes the player's level
    public void changeLevel(int newLevel) {         
        playerLevel = newLevel;
    }

    // Levels up the player
    public void levelUp() {
        playerLevel++;
        EXP = 0;
    }

    // Give the player health
    public void addHealth(int addedHealth) {
        playerHealth = playerHealth + addedHealth;
    }

    // Remove the player's health
    public void removeHealth(int removedHealth) {
        playerHealth = playerHealth - removedHealth;
    }

    // Give the player money
    public void giveMoney(int givenMoney) {
        money = money + givenMoney;
    }

    // Give the player EXP
    public void giveEXP(int addedEXP) {
        EXP = EXP + addedEXP;
    }

    // Change the player's homeland
    public void changeHomeland(String newHomeland) {
        homeland = newHomeland;
    }

    // Change the player's name
    public void changeName(String newName) {
        name = newName;
    }

    // Increase Fighting
    public void increaseFightingSkill(int amountAdded) {
        fighting = fighting + amountAdded;
    }

    // Decrease Fighting
    public void decreaseFightingSkill(int amountdecreased) {
        fighting = fighting - amountdecreased;
    }

    // Increase Block
    public void increaseBlockSkill(int amountAdded) {
        block = block + amountAdded;
    }

    // Decrease Block
    public void decreaseBlockSkill(int amountdecreased) {
        block = block - amountdecreased;
    }

    // Increase Doctor
    public void increaseDoctorSkill(int amountAdded) {
        doctor = doctor + amountAdded;          
    }

    // Decrease Doctor
    public void decreaseDoctorSkill(int amountdecreased) {
        doctor = doctor - amountdecreased;
    }

    // Increase Speech
    public void increaseSpeechSkill(int amountAdded) {
        speech = speech + amountAdded;
    }

    // Decrease Speech
    public void decreaseSpeechSkill(int amountdecreased) {
        speech = speech - amountdecreased;
    }

}

如您所见,您还可以在此处更改玩家的统计数据。我正在创建一个主类,我只是在其中初始化玩家,并在玩家做出决定、赢得战斗等时修改他们的统计数据。我在主类中初始化玩家。

Player player = new Player();

现在它已经初始化了,我创建了一个“Battle”类。这个概念是我想简单地初始化战斗,修改战斗的内容并完成它(就像一个战斗模板,我可以放入代码中)。有点像这样:

battle.enemySetHealth() // example modifier
battle.start() // simply run through the battle

问题是,我想在战斗类中使用玩家的统计数据,而不是真正定义另一个玩家,我想使用相同的玩家对象,因为我将在主类中修改玩家的统计数据,如果我定义了一个新的,它将在战斗类中有不同的统计数据,把整个事情搞砸了。我将使用战斗类中的玩家统计数据来确定攻击伤害,阻止来袭攻击的机会等。这是战斗类:

import java.util.Random;
import java.util.Scanner;

// Battle Scene
public class Battle {
    //Variables
    String enemyName = "Unnamed Enemy";
    int enemyHealth = 20;
    int enemyAttack = 5;
    int enemyDefense = 5;
    int enemyDisposition = 0;
    int attackDamage;
    // Sets up tools
    clear clear = new clear();
    Scanner sc = new Scanner(System.in);
    Random rand = new Random();

    // Allows changing of enemy name
    public void enemyName(String newEnemyName) {
        enemyName = newEnemyName;
    }

    // Sets a new disposition for the enemy to start the fight with
    public void enemyStartingDisposition(int newStartingDisposition) {
        enemyDisposition = newStartingDisposition;
    }

    // Sets a new amount of health for the enemy to start with
    public void enemyStartingHealth(int newStartingHealth) {
        enemyHealth = newStartingHealth;
    }

    // Sets a new defense for the enemy to start with
    public void enemyStartingDefense(int newEnemyDefense) {
        enemyDefense = newEnemyDefense;
    }

    // Sets a new attack for the enemy to start with
    public void enemyStartingAttack(int newEnemyAttack) {
        enemyAttack = newEnemyAttack;
    }

    // Starts the battle
    public void startFight() throws InterruptedException {
        System.out.println("Woah! " + enemyName + " jumped out of nowhere!!!");
        System.out.println("(Attack)");
        System.out.println("(Talk)");
        System.out.println("(Run)");
        while (true) {
            System.out.print("What should you do? : ");
            String userInput = sc.nextLine();
            if (userInput.equals("Attack")) {
                // hopefully put in a way to attack based on your stats
            } if (userInput.equals("Talk")) {
                // a way to use speech to talk your way out of the fight
            } if (userInput.equals("Run")) {
                //ability to run away based on agility/speed 
            } else {
                System.out.println();
                System.out.println("Invalid Answer!");
                Thread.sleep(2000);
                clear.Screen();
            }   
        }
        //Break here
    }
}

我还想在最后修改玩家的统计数据,例如获得的金钱和经验。那么我该怎么做呢?它变得非常混乱。

【问题讨论】:

  • 请重新格式化您的代码以提高可读性。为什么这很重要?好吧,如果您是唯一一个阅读和研究代码的人并不重要,但是一旦您将代码发布到由志愿者组成的网站上,情况就会改变,因为现在它在 您的中有兴趣帮助您尽可能容易地理解和阅读您的代码。所有嵌套块应缩进 4 个空格。同一块上的所有代码都应具有相同的缩进。一行中的空白行不应超过一个....您对此的帮助将不胜感激。
  • A Battle 应该采用 2 个玩家作为参考,或者一个玩家和一个敌人,具体取决于您的目标,以及敌人是否与普通玩家不同。

标签: java oop methods


【解决方案1】:

您可以将 Player 实体作为实际参数传递给 Battle 类的方法,并将当前实体作为参数返回。 示例代码如下:

战斗类代码:

public class Battle {
    //battle win function
    public Player winBattle(Player player){
        /**
         * win rules
         */
        player.setStatus("dead");
        return player;
    }

}

播放器类代码:

Player player = new Player();
Battle battle=new Battle();
player=battle.run(player);

【讨论】:

  • 所以我基本上是通过玩家来进行战斗的?
  • 为什么需要退回播放器?
  • @CuriousMan 你可以在你的业务逻辑或者main方法中同时初始化这两个实体~
【解决方案2】:

您要做的是将您在主类中创建的玩家对象传递给战斗类中的 startfight() 方法。然后,在开始战斗中,您将能够访问所有玩家的统计数据,而无需重新定义它们。创建一个 Enemy 类来代表游戏中的敌人也可能很有用。这样你就不需要在战斗类中定义敌人的统计数据了。此外,由于 Player 和 Enemy 共享一些统计数据(如伤害和名称),因此创建一个将伤害和名称作为实例变量的 superclass 可能很有用,以避免代码重复。因为玩的玩家总是一样的,我们可以让玩家作为战斗的实例变量(因为您只想使用战斗类的一个实例)话虽如此,这里是您的代码,其中包含我提出的更改。

GameUnit.java

/**
 * Represents a game unit - a Player or an Enemy because they both share common stats
 */
public class GameUnit {
    int attackDamage;// your "damage" in the player class and "enemyAttack" in the battle class
    int health = 5;// "playerHealth" in the player class and "enemyHealth" in the battle class
    int defense = 5;

    String name = "unnamed game unit";

    public void printStats() {
        System.out.println();
        System.out.println("Game Unit attackDamage: " + attackDamage);
        System.out.println("Game Unit health: " + health);
        System.out.println("GameUnit defense: " + defense);
    }

    // Give the unit health
    public void addHealth(int addedHealth) {
        health = health + addedHealth;
    }

    public void setHealth(int newHealth) {
        health = newHealth;
    }

    // Remove the player's health
    public void removeHealth(int removedHealth) {
        health = health - removedHealth;
    }

    // Change the unit's name
    public void changeName(String newName) {
        name = newName;
    }

    public void setAttackDamage(int attackDamage) {
        this.attackDamage = attackDamage;
    }

    // Increase Block
    public void increaseBlockSkill(int amountAdded) {
        defense = defense + amountAdded;
    }

    // Decrease Block
    public void decreaseBlockSkill(int amountdecreased) {
        defense = defense - amountdecreased;
    }

    public void setDefense(int defense) {
        this.defense = defense;
    }
}

Player.java

public class Player extends GameUnit {
    int level = 1;
    // health is now in GameUnit because enemy needs health too
    int EXP = 0;
    long money = 0;
    String homeland = "";

    int fighting = 5;
    //block is defense in GameUnit
    int doctor = 5;
    int speech = 5;

    // Constructor that sets name from "unnamed game unit" to Player
    public Player() {
        name = "Player";// Set the name declared in the GameUnit class to player because this instance is the player
        attackDamage = fighting * 2;
    }

    // Override printStats in GameUnit to print the remaining player stats
    public void printStats() {
        super.printStats();// Prints attack damage and health
        System.out.println("Player level: " + level);
        System.out.println("Health: " + health);
        System.out.println("EXP: " + EXP);
        System.out.println("money " + money);
        System.out.println("Homeland: " + homeland);
        System.out.println("Skills: Fighting: " + fighting + "Doctor: " + doctor + " Speech: " + speech);
        System.out.println();
    }


    // Changes the player's level
    public void changeLevel(int newLevel) {

        level = newLevel;
    }

    // Levels up the player
    public void levelUp() {
        level++;
        EXP = 0;
    }// Give the player money
    public void giveMoney(int givenMoney) {
        money = money + givenMoney;
    }

    // Give the player EXP
    public void giveEXP(int addedEXP) {
        EXP = EXP + addedEXP;
    }

    // Change the player's homeland
    public void changeHomeland(String newHomeland) {
        homeland = newHomeland;
    }

    // Increase Fighting
    public void increaseFightingSkill(int amountAdded) {
        fighting = fighting + amountAdded;
    }

    // Decrease Fighting
    public void decreaseFightingSkill(int amountdecreased) {
        fighting = fighting - amountdecreased;
    }

    // Increase Doctor
    public void increaseDoctorSkill(int amountAdded) {
        doctor = doctor + amountAdded;

    }

    // Decrease Doctor
    public void decreaseDoctorSkill(int amountdecreased) {
        doctor = doctor - amountdecreased;
    }

    // Increase Speech
    public void increaseSpeechSkill(int amountAdded) {
        speech = speech + amountAdded;
    }

    // Decrease Speech
    public void decreaseSpeechSkill(int amountdecreased) {
        speech = speech - amountdecreased;
    }
}

Enemy.java

public class Enemy extends GameUnit {
    //enemyHealth is health in GameUnit
    //enemyAttack is attackDamage in GameUnit
    int enemyDisposition = 0;

    //No need for setEnemy name because changeName does the perfect thing in GameUnit

    //Set health does the job of enemyStartingHealth
    public void setEnemyDisposition(int enemyDisposition) {
        this.enemyDisposition = enemyDisposition;
    }

}

Battle.java

import java.util.*;

public class Battle {
    private Player player;
    private Enemy enemy;

    private Clear clear = new Clear();// Remember Java classes are supposed to start with upper cases
    private Scanner sc = new Scanner(System.in);
    private Random rand = new Random();

    public Battle(Player thePlayer) {// Pass our only instance of player
        player = thePlayer;// Because objects are passed by reference in Java,
        // player will be the same instance of Player. In other words, when
        // you modify the player object in main, the instance variables in this
        // player reference will change accordingly because player in this class
        // and player in main both point to the same object
    }

    public void setEnemy(Enemy newEnemy) {
        enemy = newEnemy;
    }

    // Starts the battle
    public void startFight() {

        System.out.println("Woah! " + enemy.name + " jumped out of nowhere!!!");
        System.out.println("(Attack)");
        System.out.println("(Talk)");
        System.out.println("(Run)");
        boolean won = false;
        while (true) {

            if (enemy.health <= 0) {// enemy is dead
                won = true;
                break;
            }

            if (player.health <= 0) {// player is dead
                won = false;
                break;
            }

            System.out.print("What should you do? : ");
            String userInput = sc.nextLine();
            if (userInput.equals("Attack")) {
                enemy.removeHealth(player.attackDamage);// hurt the enemy or whatever
                // hopefully put in a way to attack based on your stats
            }
            if (userInput.equals("Talk")) {
                if (player.speech > 10) {
                    // ...
                }

            }
            if (userInput.equals("Run")) {
                // ability to run away based on agility/speed

            } else {
                System.out.println();
                System.out.println("Invalid Answer!");
                try {
                    Thread.sleep(2000);
                } catch (Exception e) {
                    // ignore all exceptions
                }
                clear.screen();// and methods are supposed to use lower camel case so the first word (screen) is lowercase
            }
        }
        if (won) {
            player.money += 1000;
            player.giveEXP(10);
            if (player.EXP > 100) {
                player.levelUp();
            }
        } else {
            player.money -= 500;
        }
        // Break here

    }

}

Main.java

public class Main {

    public static void main(String[] args) {

        Player player = new Player();

        Battle battle = new Battle(player);// Pass player to battle

        Enemy firstEnemy = new Enemy();
        firstEnemy.changeName("First Enemy");

        battle.setEnemy(firstEnemy);
        battle.startFight();
        // ...do other battles, create new enemies with random stats etc...
    }
}

Java 库也使用层次结构:link

如果这种层级业务没有意义,那么在继续您的游戏之前稍微提高您的 Java 技能可能会有所帮助。一旦你有信心,我的设置可能不会封装你想要如何表示你的游戏对象(玩家和敌人),所以你可能想要绘制一个 UML diagram 来显示玩家和敌人的共同点(健康、阻挡),但是玩家可能拥有一些敌人现在可能拥有的东西(等级、经验等)。有了这些知识,您可以重新构建层次结构,这样您就不必担心所有内容的存储方式,并且可以不间断地处理内容。

良好的继承/层次结构示例here

【讨论】:

    【解决方案3】:

    接受的答案已经足够了,但我认为值得注意的是,如果你在整个游戏中只有一个玩家,你应该在你的主类中创建一个public static Player,如下所示:

    public class Main {
    
    public static Player player;
    
    public static void main(String args[]) {
    player = new Player();
    //...
    battle.start();
    }
    
    }
    

    然后在Battle类中,当你想奖励玩家exp(或其他东西)时,你可以简单地:

    Main.player.rewardExp(25);
    

    Main.player.exp += 25;
    

    我个人觉得这对你的游戏来说更具有技术意义,但如果你要添加更多玩家或敌人,这样处理它会更有意义:

    Battle b = new Battle(player, enemy);
    battle.start();
    

    传递玩家和敌人的参数,然后将它们存储为每个战斗实例的变量,这样战斗就可以轻松访问它们。

    **编辑:**您可能还想考虑创建一个实体类。 玩家的某些变量(特征、统计数据),例如生命值、力量等,也是敌人拥有的统计数据。

    为了防止重复编写相同的代码,您可以创建一个--SUPERCLASS--,其中包含HPPOWEREXP 等变量。

    然后,只需拥有您的 Player 类和 Enemy 类 extends Entity,您就可以将这些统计信息用于两者,而无需在这两个类中编写它们。 您甚至可以预设die()giveExp()loseHp()等方法。

    希望我解释得足够好。

    【讨论】:

      猜你喜欢
      • 2023-03-22
      • 2015-03-01
      • 1970-01-01
      • 2018-11-26
      • 2019-11-10
      • 2017-01-27
      • 2018-01-06
      • 2019-07-09
      • 2010-10-09
      相关资源
      最近更新 更多