【问题标题】:Java Beginner: Letting one class know that another has finishedJava初学者:让一个类知道另一个类已经完成
【发布时间】:2012-12-04 00:55:35
【问题描述】:

我正在制作一个具有主类、战斗类、怪物类、玩家类等的 Java 游戏......我在主类框架上显示了统计信息。按下按钮会创建一个新的战斗框架,其中还会显示统计数据。战斗结束后,统计数据有所不同(例如,玩家的生命值低于被怪物击中前的值)。我需要在战斗框架消失后将这些统计数据的变化反映在主框架上。

告诉主要职业战斗结束并刷新统计数据的最佳方式是什么?代码如下。显然,这是一项正在进行的工作,还有一些其他不相关的类。

开始战斗的主类部分(即,创建一个新的战斗对象,它是一个 JFrame):

public class DarkWorld extends JFrame implements ActionListener
{
    ...
    public DarkWorld()
    {
        ...
    public void createInfoLabel()
    {
        infoLabel.setText("<html>Player: " + DarkWorld.user.getPlayerName()
            + "<br>Health: " + DarkWorld.user.getHealth()
            + "<br>Attack Damage: " + DarkWorld.user.getAttackDamage()
            + "<br>Level: " + DarkWorld.user.getLevel()
            + "<br>Experience: " + DarkWorld.user.getExperience());
    }
    ...
        if(source == monsterButton)
        {

            BattleFrame battle = new BattleFrame();
            final int WIDTH = 700;
            final int HEIGHT = 500;
            battle.setSize(WIDTH, HEIGHT);
            battle.setVisible(true);
        }
        ...
}

部分战斗课:

...


public class BattleFrame extends JFrame implements ActionListener
{
    Monster newMonster = new Monster();
    ...
    public BattleFrame()
    ...
    public void displayStats()
    {
        monsterLabel.setText("<html>Type: " + newMonster.getMonsterName()
                + "<br>Health: " + newMonster.getHealth()
                + "<br>Attack: " + newMonster.getAttackName()
                + "<br>Attack Damage: " + newMonster.getAttackDamage());
        playerLabel.setText("<html>Player: " + DarkWorld.user.getPlayerName()
                + "<br>Health: " + DarkWorld.user.getHealth()
                + "<br>Attack Damage: " + DarkWorld.user.getAttackDamage()
                + "<br>Level: " + DarkWorld.user.getLevel()
                + "<br>Experience: " + DarkWorld.user.getExperience());
    }
    ...
            if(newMonster.getHealth() <= 0)
            {
                ...
                JOptionPane.showMessageDialog(null, "You killed the monster! You found a " + newItem.getItemName()
                        + ". It has been added to your inventory.");
                dispose();
            }
            if(DarkWorld.user.getHealth() <= 0)
            {
                //if player dies (health reaches zero), the game is over - need to make game end
                displayStats();
                JOptionPane.showMessageDialog(null, "The monster killed you!");
                dispose();
            }
        }
        ...
}

编辑:试图在这里简化代码,以便更清楚我在问什么。

【问题讨论】:

  • 我怀疑这是一个术语问题,但 ivaonic 是对的。你的意思是main 函数吗?在这种情况下,程序在完成时结束,您无能为力。
  • 我不确定你的意思,抱歉。主类应该一直存在,并在按下按钮时调用战斗类。
  • @ivanovic 可能被GC处置是他的意思?
  • 对不起,是的,主类(称为 DarkWorld)在按下按钮时会调用 Battle。战斗结束后,战斗架被放置。再次按下按钮后会创建新的战斗。
  • 那是一大堆代码。 (尝试在您的问题中包含简化示例,其中仅包含与您面临的问题相关的代码。)

标签: java


【解决方案1】:

为什么不在主类中创建一个方法:

public void updateStats() { /*update the stats*/ }

然后,在您的 Battle 类中,当战斗结束时,您只需调用该方法。另外,我认为您可能会发现在您的项目中实现单例模式很有用,因为听起来好像始终只有一个战斗课程。

您可能还想将所有的战斗逻辑放到一个类中。我得到的最好的编程建议是将逻辑与 GUI 分开。

或者,您可能只想忽略我所说的一切,因为我只有 13 岁,并且我使用 C# 编程,而不是 Java。

【讨论】:

  • 好的,你是说在需要开始战斗时从主类中调用这个方法来创建一个新的战斗对象,然后在战斗类之后再次调用这个相同的方法战斗结束了?另外,也许我没有完全理解我自己的代码。在我看来,战斗对象与开始的战斗一样多,每次按下按钮时都会有一个新对象,但一次只有一个。也就是说,dispose() 方法不是消除了战斗对象吗?
  • 既然您已经简化了代码,我对您的代码理解得更好了。
  • 因为一次只有一个战斗类,你可以使用单例模式来访问那个战斗类。 Singleton 类将有一个名为 resetBattle() 的方法,每当战斗结束时都会调用该方法。
  • 我喜欢这个主意。但现在我有一个新问题。我在主类中有一个 updateStats() 方法:private static JLabel infoLabel = new JLabel(""); ... public static void updateStats() { infoLabel.setText( /* stats updated */); validate(); } 我将 JLabel 和方法设为静态 - 否则我无法从战斗类中调用它们。但是我仍然无法调用该方法,因为 validate() 方法不能在静态方法中。我需要在可以从另一个类调用的主类中的方法中包含 validate() 方法。这可能吗?
  • 当然。使该方法非静态。将 DarkWorld 字段添加到其他类。在他们的构造函数中,请求一个 DarkWorld 参数 darkworld 并设置 this.darkworld = darkworld; 然后,在那个 if 语句中调用 darkworld.updateStats();
【解决方案2】:

我可以建议你不要这样做,而是让统计显示屏幕收听 到主要播放器对象。当主要玩家对象的其中一项统计数据发生变化时 然后统计屏幕可以自行更新。

...
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeEvent;
...

public class User {

    private List<PropertyChangeListener> propertyListeners;

    ... add, and remove listener methods ...        


    public void setHitPoints(int newValue){
       PropertyChangeEvent event = new PropertyChangeEvent(this, "hitPoints", myHitpoints, newValue);
       myHitpoints = newValue;
       for (PropertyChangeListener listener : propertyListeners){
          listener.propertyChange(event);
       }
    }

【讨论】:

  • 哦,是的,这是一个更好的解决方案。
  • Eclipse 在这一行给我一个错误:private List&lt;PropertyChangeListener&gt; propertyListeners; 错误说“PropertyChangeListener 无法解析为一个类型”。我以前没有使用过 PropertyChangeListener 或 PropertyChangeEvent。我需要创建这些东西才能使用吗?感谢您的反馈。
  • 您要导入它吗?导入 java.beans.PropertyChangeListener;导入 java.beans.PropertyChangeEvent;
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-28
  • 1970-01-01
相关资源
最近更新 更多