【问题标题】:How do I make my two classes function together?如何让我的两个类一起运行?
【发布时间】:2021-11-23 20:47:06
【问题描述】:

我正在开发一个基于文本的视频游戏并为其创建了一个 GUI,但是,我在让我的两个类一起工作时遇到了问题。我的 GUI 类中有一个文本字段,它接收来自用户的输入,我想将其发送到我的 Player 类,以便它可以比较它并执行适当的方法。我对编程还是很陌生,所以我希望你们中的一些人可以帮助我。请原谅可怕的代码。

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

public class GUI extends Player {
    String input;
    JLabel message;
    public GUI() {
        JFrame frame = new JFrame("SPACE GAME");

        ImageIcon image = new ImageIcon("rocket.png");

        frame.setIconImage(image.getImage());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(1200, 800);
        frame.setLocationRelativeTo(null);
        frame.setFocusable(true);
        frame.getContentPane();


        JPanel panel = new JPanel();
        JTextField commandLine = new JTextField(30);
        JLabel message = new JLabel();

        frame.add(panel);

        panel.setBackground(Color.black);
        panel.setLayout(null);
        panel.setBorder(BorderFactory.createEmptyBorder(1000, 1000 ,1000 ,1000));

        commandLine.setBackground(Color.WHITE);
        commandLine.setBounds(5, 730, 300, 30);
        commandLine.setBorder(BorderFactory.createLineBorder(Color.GRAY, 3));
        commandLine.setFont(new Font("Zig", Font.PLAIN, 18));
        commandLine.setForeground(Color.GREEN);
        commandLine.setBackground(Color.BLACK);
        commandLine.setCaretColor(Color.GREEN);
        commandLine.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {

                String input = commandLine.getText();
            }
        });
        commandLine.setVisible(false);


        message.setForeground(Color.GREEN);
        message.setText("Welcome to SPACE GAME! Press any key to start.");
        message.setBounds(5,665, 1000, 100);
        message.setFont(new Font("Courier", Font.PLAIN, 18));


        panel.add(message);
        panel.add(commandLine);


        frame.setVisible(true);
        frame.addKeyListener(new KeyListener() {

            @Override
            public void keyTyped(KeyEvent e) {

            }

            @Override
            public void keyPressed(KeyEvent e) {
                int keyCode = e.getKeyCode();
                commandLine.setVisible(true);
                commandLine.requestFocusInWindow();
                message.setText("Type \"help\" for help");
            }

            @Override
            public void keyReleased(KeyEvent e) {

            }
        });
    }
    public JLabel getMessage(JLabel message) {
        return message;
    }
}
import javax.swing.*;
import java.util.Scanner;

public class Player {
    //Attributes
    private Room currentRoom;
    Player player;
    JLabel message;
 // Handles player movement and commands
 public void move() {
     player = new Player();
     Map map = new Map();
     GUI gui = new GUI();
     player.currentRoom = map.room1;
     Scanner input = new Scanner(System.in);
     System.out.println("You are in " + player.currentRoom.getName() + ". " + player.currentRoom.getRoomDescription());
     System.out.println("Type \"help\" to get help");

     //Commands
     boolean isGameRunning = true;
     while (isGameRunning) {
         String goMessage = input.nextLine();
         goMessage = goMessage.toLowerCase();
         switch (goMessage) {
             case "go north", "north", "go n", "n": goNorth(); break;
             case "go east", "east", "go e", "e": goEast(); break;
             case "go south", "south", "go s", "s": goSouth(); break;
             case "go west", "west", "go w", "w": goWest(); break;
             case "exit": isGameRunning = false; break;
             case "look":
                 System.out.println(player.currentRoom.getRoomDescription());
                 break;
             case "help":
                 System.out.println("""
                            "go (north, south, east, west)" to choose a direction to go.
                            "look" gives you a description of the room.
                            "exit" stops the game.""");
                 break;
             default:
                 System.out.println("Unknown command");
                 break;
         }
     }
 }
    public void goNorth() {
        if (player.currentRoom.getNorthRoom() != null) {
            player.currentRoom = player.currentRoom.getNorthRoom();
            System.out.println("You are in " + player.currentRoom.getName() + ". " + player.currentRoom.getRoomDescription());
        } else {
            System.out.println("You cannot go that way");
        }
    }
    public void goEast() {
        if (player.currentRoom.getEastRoom() != null) {
            player.currentRoom = player.currentRoom.getEastRoom();
            System.out.println("You are in " + player.currentRoom.getName() + ". " + player.currentRoom.getRoomDescription());
        } else {
            System.out.println("You cannot go that way");
        }
    }
    public void goSouth() {
        if (player.currentRoom.getSouthRoom() != null) {
            player.currentRoom = player.currentRoom.getSouthRoom();
            System.out.println("You are in " + player.currentRoom.getName() + ". " + player.currentRoom.getRoomDescription());
        } else {
            System.out.println("You cannot go that way");
        }
    }
    public void goWest() {
        if (player.currentRoom.getWestRoom() != null) {
            player.currentRoom = player.currentRoom.getWestRoom();
            System.out.println("You are in " + player.currentRoom.getName() + ". " + player.currentRoom.getRoomDescription());
        } else {
            System.out.println("You cannot go that way");
        }
    }
}

【问题讨论】:

  • 对如何让两个类一起工作的问题的简短回答:你。更长的答案:一个程序是线性控制台应用程序,另一个是事件驱动的 GUI,这两种编程范式不能很好地或容易地结合在一起。最好的办法是重写保存程序逻辑的代码(非用户界面状态和行为信息代码),使其可用于任何类型的 UI 范例、线性控制台或事件驱动的 GUI,然后用这个新代码将你的 GUI 网格化。
  • 另外,请看我对this similar question的相关回复。
  • 我明白了。我不确定如何实现这一目标,但我会尝试弄清楚。非常感谢您的回答。 @HovercraftFullOfEels

标签: java swing user-interface


【解决方案1】:

您的代码中有一些优点以及一些可能会妨碍您将 GUI 与当前控制台程序代码混搭的主要问题,其中包括:

  • 您确实将程序逻辑分离为单独的类,例如 Player、Map 和 Room 类,这是一件非常好的事情,但您仍然可以进行更多的逻辑分离,这样做可以简化让您的代码更易于调试和增强。
  • Player 类包含一个 Player 实例,我不知道为什么。外部主类可能应该从 Player 重命名为 Game 类,并且 Player 类应该是一个完全独立的类,它包含 single 播放器实例的状态,并且不应该像你一样创建自己的实例。关键是努力“优化”你的代码,尤其是代码的“模型”部分,即包含非用户界面程序逻辑的代码,使其更加面向对象,因为这会使它变得更加更容易让您将 GUI 或任何其他界面连接到您的模型。
  • 您的模型(再次命名为 Player)中包含用户界面 (UI) 代码:其中包含 Scanner 输入代码和 println 语句。这是有问题的,尤其是现在,因为您想增强程序并使其与 GUI 一起工作。首先,您必须做的最重要的事情是将用户界面代码(即从用户获取输入并将输出显示给用户的代码)分离到模型类之外,该类再次包含程序逻辑。
  • 您的 Player 类有很多非 Player 代码使其混乱。一个基本的 OOP 原则是一个类应该有一个单一的职责(称为“单一职责规则”),因此您的 Player 类应该只包含封装 Player 状态所需的代码(例如 name、Room,也许还有其他属性,例如力量、武器、健康、智力……)和玩家行为(允许玩家与其他职业互动的方法),或多或少。
  • 按照同样的思路,所有程序数据和行为似乎都被硬连接到驱动程序的单个主 Player 类中。这是非常有限的,并且会阻碍您创建一个包含许多房间、房间中的物品以及诸如此类的东西的丰富游戏环境的能力。分而治之 - 从主程序中获取这些信息并将其放入符合 OOP 的类中,包括一个 Room 类,该类具有它可能包含的项目的字段,它知道自己与其他房间的连接。
  • 您的 GUI 程序扩展了 Player 对象。这是一个主要问题,因为这个程序结构没有通过基本的继承测试,即“is-a”测试:从逻辑上讲,GUI 是一种更具体的播放器类型(很像 Dog 是一种更具体的 Animal,a通过“is-a”测试的结构)?不,它不是,虽然这种区别可能看起来很悬疑,但由于这种继承,您可以尝试在 GUI 类中使用 Player 字段,但如果您尝试这样做,代码将无法正常工作。删除此继承,而是尝试通过“组合”连接类,其中一个类包含另一个类的实例,而不是扩展另一个类。因此,例如,GUI 可能会保存一个 Player 变量,而不是从 Player 扩展。

底线: 您将希望在尝试添加 GUI 之前完全“OOP-ify”您的代码

为了使程序能够与 GUI 很好地结合,我建议使您的底层逻辑代码(非用户界面逻辑代码)更加面向对象,并使用所有具有 的类单一职责,易于可测试的类(远离 GUI 或任何用户界面)。从第一原则开始,程序将更容易构建。

因此,例如,可以考虑用于冒险游戏的类包括:

  • Direction 类,或者更好的Direction enum

这将封装“方向”的概念,并将用于让游戏中的对象知道它们要去哪个方向,并能够使用常量而不是字符串将其传达给其他对象。枚举的用户将允许编译器检查方向是否正确使用,因为如果您使用字符串,例如“West”,编译器将不会自动知道您是否输入错误的字符串并使用“Best”代替。

像这样简单的东西,例如:

public enum Direction {
    NORTH, EAST, SOUTH, WEST
}
  • GameRoom 类

这将包含信息,告诉它它在房间网格中的位置,名称和描述属性的字符串,以及游戏玩家字段或游戏玩家的List(如果允许多个),可能包含代码像这样:....

public class GameRoom {
    // map with connections to other game rooms
    private Map<Direction, GameRoom> connections = new HashMap<Direction, GameRoom>();
    
    // location information
    private int x;
    private int y;
    
    // identifying information
    private String roomName;
    private String description;
    
    // holds any player objects that may be in the room
    private List<GamePlayer> playersInRoom = new ArrayList<>();
    

该类将具有适当的构造函数以及 getter 和 setter 方法,并且:

允许游戏将玩家添加到房间的addPlayer(...) 方法:

public void addPlayer(GamePlayer gamePlayer) {
    playersInRoom.add(gamePlayer);
    gamePlayer.setCurrentRoom(this); // we'll get to this later
}

public boolean move(...) 方法将房间中包含的玩家移动到连接房间。它首先检查房间是否真的包含被移动的玩家,然后检查房间是否与请求方向的另一个房间有连接。如果其中任何一个为假,则该方法返回假以让尝试移动失败的调用代码。否则,如果允许移动,则返回 true:

public boolean move(GamePlayer gamePlayer, Direction direction) {
    
    // if the room doesn't currently hold this player
    if (!playersInRoom.contains(gamePlayer)) {
        return false; // invalid move request
    }
    
    // if the room doesn't have a connecting room in the requested direction
    if (!connections.containsKey(direction)) {
        return false;  // invalid move request
    }
    
    // otherwise, we're good
    playersInRoom.remove(gamePlayer);
    connections.get(direction).addPlayer(gamePlayer);
    return true;
}
  • GamePlayer 类

这个类将包含几个属性,例如名称的 String 和当前房间的 GameRoom 字段、构造函数、getter 和 setter 方法。它的声明和字段可能类似于:

public class GamePlayer {
    private String name;
    private GameRoom currentRoom;
    //.... other properties
    

它也应该有一个 move 方法来调用 currentRoom GameRoom 的 move 方法并返回相同的布尔值,该结果告诉调用代码移动是否有效且成功:

public boolean move(Direction direction) {
    return currentRoom.move(this, direction);
}
  • GameModel 类:

这将保存当前游戏的状态、玩家字段、保存所有房间的数据结构。它可以有自己的move方法.....


只有在创建了符合 OOP 的类之后,您才能进行下一步:创建 GUI 或“视图”类/类。这个类可以保存一个 GameModel 实例,并负责 1) 显示游戏的状态(房间及其持有的物品的视觉表示),以及 2) 从用户,并将该输入传递给游戏模型进行处理。

我喜欢使用 MVC 程序结构,它代表“模型-视图-控制器”,其中程序逻辑和 GUI 尽可能分开,并且可能有一个或多个控制器类帮助绑定模型和一起来看。我尝试遵循的另一个原则是使 GUI 尽可能“愚蠢”。愚蠢,我的意思是它应该从用户那里获得输入,也许做最基本的输入验证,并且应该显示模型的状态,但仅此而已。程序的几乎所有“大脑”都应该由模型本身而不是视图来控制。


概念验证示例:

我上面描述的一个不完整但正在运行的“概念验证”示例如下所示。您应该复制整个程序,将其粘贴到您的 IDE 中,并将其粘贴到名为 VideoGame.java 的单个文件中,然后应该能够运行它。它使用了一些您可能还不熟悉的概念,包括使用键绑定从 GUI 获取用户输入以及使用 PropertyChangeListeners 和 PropertyChangeSupport 对象来允许对象之间的干净通信(如果 state 通知侦听器 模型对象之一已更改)。该程序应该响应箭头键的按下:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.swing.*;
import javax.swing.event.SwingPropertyChangeSupport;

public class VideoGame {
    private static final int[][] ROOM_GRID_KEY = { 
            {  1,  0,  0,  2,  0,  0,  3,  4 }, 
            {  5,  6,  7,  8,  9, 10, 11,  0 },
            {  0, 12,  0, 13,  0,  0,  0,  0 }, 
            {  0, 14,  0,  0,  0,  0, 15, 16 }, 
            { 17, 18,  0, 19,  0,  0, 20,  0 },
            { 21, 22, 23, 24, 25, 26, 27, 28 } 
        };

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            GameModel gameModel = new GameModel(ROOM_GRID_KEY);
            GameView gameView = new GameView();
            
            new GameController(gameModel, gameView);

            JFrame frame = new JFrame("Video Game");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.add(gameView);
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        });
    }
}
class GameController {
    private GameModel gameModel;
    private GameView gameView;

    public GameController(GameModel gameModel, GameView gameView) {
        this.gameModel = gameModel;
        this.gameView = gameView;
        
        ModelListener modelListener = new ModelListener();
        
        gameView.setModel(gameModel);
        gameModel.addPropertyChangeListener(modelListener);
    }
    
    private class ModelListener implements PropertyChangeListener {
        @Override
        public void propertyChange(PropertyChangeEvent evt) {
            gameView.modelChange(evt);
        }
    }

}
@SuppressWarnings("serial")
class DisplayPanel extends JPanel {
    private JPanel[][] panelGrid;
    private int gridCellSize;
    private GameModel gameModel;
    private GameRoom[][] roomGrid;
    
    public DisplayPanel(int gridCellSize) {
        this.gridCellSize = gridCellSize;       
    }
    
    public void setModel(GameModel gameModel) {
        this.gameModel = gameModel;
        this.roomGrid = gameModel.getRoomGrid();
        
        int rows = roomGrid.length;
        int cols = roomGrid[0].length;
        
        setBackground(Color.BLACK);
        setLayout(new GridLayout(rows, cols, 1, 1));
        setBorder(BorderFactory.createLineBorder(Color.BLACK));
        
        panelGrid = new JPanel[rows][cols];
        for (int r = 0; r < panelGrid.length; r++) {
            for (int c = 0; c < panelGrid[r].length; c++) {
                JPanel panel = new JPanel(new GridBagLayout());
                panelGrid[r][c] = panel;
                panel.setPreferredSize(new Dimension(gridCellSize, gridCellSize));
                if (roomGrid[r][c] == null) {
                    panel.setBackground(Color.BLACK);
                } else {
                    panel.setBackground(Color.PINK);
                    if (roomGrid[r][c].getPlayersInRoom().size() > 0) {
                        GamePlayer gamePlayer = roomGrid[r][c].getPlayersInRoom().get(0);
                        String name = gamePlayer.getName();
                        JLabel label = new JLabel(name);
                        panel.add(label);
                    }
                }
                add(panel);
                
            }
        }
        
        // key bindings code
        addBindings(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0), Direction.SOUTH);
        addBindings(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), Direction.NORTH);
        addBindings(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), Direction.WEST);
        addBindings(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), Direction.EAST);
    }

    private void addBindings(KeyStroke keyStroke, Direction direction) {
        int condition = WHEN_IN_FOCUSED_WINDOW;
        InputMap inputMap = getInputMap(condition);
        ActionMap actionMap = getActionMap();
        
        Action action = new AbstractAction() {
            
            @Override
            public void actionPerformed(ActionEvent e) {
                gameModel.move(direction);
            }
        };
        
        inputMap.put(keyStroke, keyStroke.toString());
        actionMap.put(keyStroke.toString(), action);
    }

    public void modelChange(PropertyChangeEvent evt) {
        for (int r = 0; r < panelGrid.length; r++) {
            for (int c = 0; c < panelGrid[r].length; c++) {
                JPanel panel = panelGrid[r][c];
                if (roomGrid[r][c] != null) {
                    if (roomGrid[r][c].getPlayersInRoom().size() > 0) {
                        GamePlayer gamePlayer = roomGrid[r][c].getPlayersInRoom().get(0);
                        String name = gamePlayer.getName();
                        JLabel label = new JLabel(name);
                        panel.add(label);
                    } else {
                        panel.removeAll();
                    }
                }
            }
        }
        revalidate();
        repaint();
    }
    
    public GameModel getGameModel() {
        return gameModel;
    }
}
class GameView extends JPanel {
    private static final int CELL_SIZE = 80;
    private DisplayPanel displayPanel = new DisplayPanel(CELL_SIZE);
    private GameModel gameModel;
    // private JTextField textField = new JTextField();
    
    public GameView() {
        setLayout(new BorderLayout());
        
        add(displayPanel);
        // add(textField, BorderLayout.PAGE_END);
    }

    public void setModel(GameModel gameModel) {
        this.gameModel = gameModel;
        displayPanel.setModel(gameModel);
    }

    public void modelChange(PropertyChangeEvent evt) {
        displayPanel.modelChange(evt);
    }

    public GameModel getGameModel() {
        return gameModel;
    }

}
class GameModel {
    public static final String GAME_MODEL = "game model";
    private SwingPropertyChangeSupport pcSupport = new SwingPropertyChangeSupport(this);
    private GameRoom[][] roomGrid;
    private GamePlayer player = new GamePlayer("Fred");

    public GameModel(int[][] roomGridKey) {
        roomGrid = new GameRoom[roomGridKey.length][roomGridKey[0].length];
        // fill room grid with rooms if 1 in grid key array, with null if 0
        for (int y = 0; y < roomGridKey.length; y++) {
            for (int x = 0; x < roomGridKey[0].length; x++) {
                roomGrid[y][x] = roomGridKey[y][x] != 0 ? new GameRoom("Some Room", "Some Description", x, y) : null;
            }
        }

        // make room connections:
        for (int y = 0; y < roomGrid.length; y++) {
            for (int x = 0; x < roomGrid[0].length; x++) {
                GameRoom thisRoom = roomGrid[y][x];

                // if no room present, don't
                if (thisRoom == null) {
                    continue;
                }

                if (x > 0) {
                    GameRoom otherGameRoom = roomGrid[y][x - 1];
                    if (otherGameRoom != null) {
                        thisRoom.putConnection(Direction.WEST, otherGameRoom);
                    }
                }
                if (x < roomGrid[0].length - 1) {
                    GameRoom otherGameRoom = roomGrid[y][x + 1];
                    if (otherGameRoom != null) {
                        thisRoom.putConnection(Direction.EAST, otherGameRoom);
                    }
                }

                if (y > 0) {
                    GameRoom otherGameRoom = roomGrid[y - 1][x];
                    if (otherGameRoom != null) {
                        thisRoom.putConnection(Direction.NORTH, otherGameRoom);
                    }
                }
                if (y < roomGrid.length - 1) {
                    GameRoom otherGameRoom = roomGrid[y + 1][x];
                    if (otherGameRoom != null) {
                        thisRoom.putConnection(Direction.SOUTH, otherGameRoom);
                    }
                }

            }
        }

        // put player in top left room
        GameRoom currentRoom = roomGrid[0][0];
        if (currentRoom == null) {
            // some big error occurred
            System.err.println("Current room at 0, 0 is null. Exiting");
            System.exit(-1);
        }

        player.setCurrentRoom(currentRoom);
        currentRoom.addPlayer(player);
        player.addPropertyChangeListener(pce -> pcSupport.firePropertyChange(GAME_MODEL, null, player));

    }

    public boolean move(Direction direction) {
        boolean success = player.move(direction);
        return success;
    }

    public GamePlayer getPlayer() {
        return player;
    }

    public GameRoom[][] getRoomGrid() {
        return roomGrid;
    }

    public void addPropertyChangeListener(PropertyChangeListener listener) {
        pcSupport.addPropertyChangeListener(GAME_MODEL, listener);
    }

}
class GamePlayer {
    public static final String GAME_PLAYER = "game player";
    private SwingPropertyChangeSupport pcSupport = new SwingPropertyChangeSupport(this);
    private String name;
    private GameRoom currentRoom;

    public GamePlayer(String name) {
        super();
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public boolean move(Direction direction) {
        boolean success = currentRoom.move(this, direction);
        return success;
    }

    public void setCurrentRoom(GameRoom currentRoom) {
        GameRoom oldValue = this.currentRoom;
        GameRoom newValue = currentRoom;
        this.currentRoom = currentRoom;
        pcSupport.firePropertyChange(GAME_PLAYER, oldValue, newValue);
    }

    public GameRoom getCurrentRoom() {
        return currentRoom;
    }

    @Override
    public String toString() {
        return "GamePlayer [name=" + name + ", currentRoom=" + currentRoom + "]";
    }

    public void addPropertyChangeListener(PropertyChangeListener listener) {
        pcSupport.addPropertyChangeListener(GAME_PLAYER, listener);
    }

}
class GameRoom {
    // map with connections to other game rooms
    private Map<Direction, GameRoom> connections = new HashMap<Direction, GameRoom>();
    
    // location information
    private int x;
    private int y;
    
    // identifying information
    private String roomName;
    private String description;
    
    // holds any player objects that may be in the room
    private List<GamePlayer> playersInRoom = new ArrayList<>();

    public GameRoom(String roomName, String description, int x, int y) {
        this.roomName = roomName;
        this.description = description;
        this.x = x;
        this.y = y;
    }

    public boolean move(GamePlayer gamePlayer, Direction direction) {
        
        // if the room doesn't currently hold this player
        if (!playersInRoom.contains(gamePlayer)) {
            return false; // invalid move request
        }
        
        // if the room doesn't have a connecting room in the requested direction
        if (!connections.containsKey(direction)) {
            return false;  // invalid move request
        }
        
        // otherwise, we're good
        playersInRoom.remove(gamePlayer);
        connections.get(direction).addPlayer(gamePlayer);
        return true;
    }

    public void addPlayer(GamePlayer gamePlayer) {
        playersInRoom.add(gamePlayer);
        gamePlayer.setCurrentRoom(this);
    }

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }
    
    public String getRoomName() {
        return roomName;
    }
    
    public String getDescription() {
        return description;
    }

    public List<GamePlayer> getPlayersInRoom() {
        return playersInRoom;
    }

    public Map<Direction, GameRoom> getConnections() {
        return connections;
    }

    public void putConnection(Direction direction, GameRoom otherGameRoom) {
        connections.put(direction, otherGameRoom);
    }

    @Override
    public String toString() {
        return "GameRoom [x=" + x + ", y=" + y + "]";
    }

}
enum Direction {
    NORTH, EAST, SOUTH, WEST
}

再次,编译并运行此代码,并使用箭头键在网格中移动“Fred”。


更完整的程序会将数据完全从代码中分离出来,并允许文件 I/O 将房间网格中的数据读入程序,可能通过创建一个或多个 CSV 文件来保存房间信息,或者如果预计数据会增长并变得更复杂,然后是关系数据库,例如使用一种 SQL 风格的数据库。

【讨论】:

  • 哇,这是金子。我从没想过任何答案会像这样超越。如果我有足够的声誉,我会赞成你的回答。我一定会详细查看您的答案。非常感谢
【解决方案2】:

既然您已经让 GUI 扩展了播放器,您需要做的就是从输入字段上的 ActionListener 调用所需的函数。

    commandLine.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            String input = commandLine.getText();

            if (input == "go north") {
                GoNorth();                
            }
            // .....

        }
    });

但是,事情非常混乱。对于初学者来说,GUI 没有真正的理由来扩展播放器。我建议您将 GUI 类与 Player 分开。这样,您就不需要使用扫描仪或打印,而是在 GUI 类中收集所有 GUI 功能。

例如:

public void goNorth() {
    if (player.currentRoom.getNorthRoom() != null) {
        player.currentRoom = player.currentRoom.getNorthRoom();
        
        gui.print("You are in " + player.currentRoom.getName() + ". " + player.currentRoom.getRoomDescription())
    } else {
        gui.print("You cannot go that way");
    }
}

您需要在 GUI 类中实现一个打印功能,该功能会在消息框中添加一行文本,但我确定您一开始就计划这样做。

在 GUI 类中,您将获得对播放器的引用,因此读取输入字段将如下所示:

commandLine.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        String input = commandLine.getText();
        switch(input) {
            case "go north":
                player.goNorth();
                break;
            ...
        }


    }
});

【讨论】:

  • if (input == "go north") {?!?
  • 为了简单起见,我只是使用了他们在 Player 类中使用的任何语法。显然有更好的方式来实现命令行。
  • 你的答案是错误的,在几个方面。首先,UI 的结构不能像您建议的那样网格化,您可能希望考虑在您的答案中显示一个有效的 minimal reproducible example 示例。另一方面,基本 Java 告诉您永远不要使用 == 比较字符串。请改用equals(...)equalsIgnoreCase(...) 方法。了解== 检查两个 对象引用 是否相同,这不是您感兴趣的。另一方面,这些方法检查两个字符串是否以相同的顺序具有相同的字符,这就是这里的重点。
  • 原发帖者从未使用== 来比较他们自己代码中的字符串,所以你为什么建议Java新手这样做是不合逻辑的。
  • 不,我不是在拖钓,事实上,我是认真的。面向对象的问题是在尝试将 GUI 硬塞到程序上之前必须解决的第一个问题。对 OP 来说,这似乎有点过头了,但如果他们想要任何运行良好、可测试和可配置的东西,他们需要从第一原则开始。这就是为什么这个问题很难回答的原因,因为目前 OP 本末倒置:他们正试图将 GUI 添加到不完整的程序中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-05-17
  • 1970-01-01
  • 2022-10-05
  • 2016-01-28
  • 1970-01-01
  • 2012-12-05
  • 1970-01-01
相关资源
最近更新 更多