Java-OOP与swinggui

Java-OOP与swinggui,java,swing,oop,Java,Swing,Oop,最近,我一直在做一个叫做Factman的简单小游戏。它一开始是在控制台窗口中的一个基于文本的游戏,但我想扩展它,使用swing制作一个GUI。我让它工作,但我知道我打破了OOP的一些规则。据我所知,我从使用MVC大纲的在线教程中获得的有限知识出发,尝试重新开始,并以正确的方式进行 因此,我向So社区提出的问题是,我如何将这个程序划分为单独的GUI类、游戏逻辑类和控制器类,以将两个ie的用户输入传递给逻辑,并将修改后的游戏参数传递给GUI 这是我的错误代码: package games; imp

最近,我一直在做一个叫做Factman的简单小游戏。它一开始是在控制台窗口中的一个基于文本的游戏,但我想扩展它,使用swing制作一个GUI。我让它工作,但我知道我打破了OOP的一些规则。据我所知,我从使用MVC大纲的在线教程中获得的有限知识出发,尝试重新开始,并以正确的方式进行

因此,我向So社区提出的问题是,我如何将这个程序划分为单独的GUI类、游戏逻辑类和控制器类,以将两个ie的用户输入传递给逻辑,并将修改后的游戏参数传递给GUI

这是我的错误代码:

package games;

import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import javax.swing.Box;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;

class Factman_GUI_old extends JFrame {
    static JPanel panel;
    static JMenuBar menubar;
    static JCheckBoxMenuItem hideBoard;
    static JLabel p1ScoreLabel, p2ScoreLabel, turnIndicator, gameAreaLabel;
    static String userInput;
    static int userSelection = -1;
    static boolean newGameFlag = false;

    public Factman_GUI_old() {
        initGUI();
    }

    private void initGUI() {
        panel = new JPanel(new GridBagLayout());
        add(panel);

        // Generate the menu at the top of the window
        createMenu();

        //////////////////////////////////////////////////
        // First row, score labels
        // Score values will split all extra space evenly
        //
        GridBagConstraints constraints = new GridBagConstraints();
        JLabel p1Label = new JLabel("Player 1 Score:  ");
        constraints.anchor = GridBagConstraints.LINE_START;
        constraints.gridx = 0;
        constraints.gridy = 0;
        panel.add(p1Label, constraints);

        constraints = new GridBagConstraints();
        p1ScoreLabel = new JLabel("0");
        constraints.fill = GridBagConstraints.HORIZONTAL;
        constraints.anchor = GridBagConstraints.LINE_START;
        constraints.gridx = 1;
        constraints.gridy = 0;
        constraints.weightx = 0.5;
        panel.add(p1ScoreLabel, constraints);

        constraints = new GridBagConstraints();
        JLabel p2Label = new JLabel("Player 2 Score:  ");
        constraints.anchor = GridBagConstraints.LINE_START;
        constraints.gridx = 2;
        constraints.gridy = 0;
        panel.add(p2Label, constraints);

        constraints = new GridBagConstraints();
        p2ScoreLabel = new JLabel("0");
        constraints.fill = GridBagConstraints.HORIZONTAL;
        constraints.anchor = GridBagConstraints.LINE_START;
        constraints.gridx = 3;
        constraints.gridy = 0;
        constraints.weightx = 0.5;
        panel.add(p2ScoreLabel, constraints);

        //////////////////////////////////////////////////
        // Second row, main content area.
        // This spans all 4 columns and 2 rows
        //
        constraints = new GridBagConstraints();
        JPanel gameArea = new JPanel();
        gameArea.setLayout(new GridBagLayout());
        constraints.fill = GridBagConstraints.BOTH;
        constraints.gridx = 0;
        constraints.gridy = 1;
        constraints.gridwidth = 4;
        constraints.gridheight = 2;
        constraints.weighty = 1;
        panel.add(gameArea, constraints);

            constraints = new GridBagConstraints();
            gameAreaLabel = new JLabel("[]");
            constraints.anchor = GridBagConstraints.CENTER;
            constraints.fill = GridBagConstraints.BOTH;
            gameArea.add(gameAreaLabel, constraints);

        //////////////////////////////////////////////////
        // Third row, input area
        // This row contains another panel with its own layout
        // The first row indicates whose turn it is,
        // the second row takes user input. The text
        // field will take up all extra space
        //
        JPanel inputPanel = new JPanel();
        inputPanel.setLayout(new GridBagLayout());
        constraints = new GridBagConstraints();
        constraints.fill = GridBagConstraints.BOTH;
        constraints.gridx = 0;
        constraints.gridy = 3;
        constraints.gridwidth = 4;
        constraints.weightx = 1;
        panel.add(inputPanel, constraints);

            constraints = new GridBagConstraints();
            turnIndicator = new JLabel("It is Player 1's Turn");
            constraints.gridx = 0;
            constraints.gridy = 0;
            constraints.gridwidth = 4;
            inputPanel.add(turnIndicator, constraints);

            constraints = new GridBagConstraints();
            JLabel inputLabel = new JLabel("Enter your selection: ");
            constraints.fill = GridBagConstraints.BOTH;
            constraints.gridx = 0;
            constraints.gridy = 1;
            inputPanel.add(inputLabel, constraints);

            constraints = new GridBagConstraints();
            final JTextField inputField = new JTextField();
            constraints.fill = GridBagConstraints.HORIZONTAL;
            constraints.gridx = 1;
            constraints.gridy = 1;
            constraints.gridwidth = 3;
            constraints.weightx = 1;
            inputField.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent event) {
                    userInput = inputField.getText();
                    try {
                        userSelection = Integer.parseInt(userInput);
                    } catch (NumberFormatException e) {
                        System.out.println("No number entered...");
                    }
                    System.out.println(userInput);
                    inputField.setText("");
                }
            });
            inputPanel.add(inputField, constraints);


        // Set basic window properties
        setTitle("Factman Game");
        setSize(600,200);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
    }

    private void createMenu() {
        menubar = new JMenuBar();

        // Create the file menu
        JMenu filemenu = new JMenu("File");
        filemenu.setMnemonic(KeyEvent.VK_F);

        JMenuItem newGame = new JMenuItem("New Game");
        newGame.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N,
            ActionEvent.CTRL_MASK));
        newGame.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent event) {
                int response = JOptionPane.showConfirmDialog(
                    panel,
                    "You are about to start a new game.\n"+
                    "Your current game will be lost.",
                    "Confirm New Game",
                    JOptionPane.OK_CANCEL_OPTION,
                    JOptionPane.WARNING_MESSAGE);
                if (response == 0) newGameFlag = true;
            }
        });

        JMenuItem quit = new JMenuItem("Exit");
        quit.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q,
            ActionEvent.CTRL_MASK));
        quit.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent event) {
                if(JOptionPane.showConfirmDialog(
                        null,
                        "Are you sure you want to quit Factman?",
                        "Quit",
                        JOptionPane.YES_NO_OPTION,
                        JOptionPane.WARNING_MESSAGE) == 0) {
                    System.exit(0);
                }
            }
        });

        filemenu.add(newGame);
        filemenu.addSeparator();
        filemenu.add(quit);

        // create the view menu
        JMenu viewmenu = new JMenu("View");
        viewmenu.setMnemonic(KeyEvent.VK_V);

        hideBoard = new JCheckBoxMenuItem("Hide Game Board");
        hideBoard.setState(false);        
        viewmenu.add(hideBoard);

        // Create the help menu
        JMenu helpmenu = new JMenu("Help");
        helpmenu.setMnemonic(KeyEvent.VK_H);

        JMenuItem gameInstructions = new JMenuItem("How to Play");
        gameInstructions.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent event) {
                JOptionPane.showMessageDialog(
                    panel,
                    "<html>" +
                        "<p>Factman is a pretty simple game once you know the rules.<br>" +
                           "To play, each player will take turns selecting a number<br>" +
                           "from the list. The player will earn the number of points<br>" +
                           "equal to the number they selected. But be careful, if you<br>" +
                           "choose a number not in the list, you loose a turn!</p>" +
                        "<p></p>" +
                        "<p>When a player chooses a number, the other player will gain<br>" +
                           "the number of points for each of the factors in the list.<br>" +
                           "Any number that is used (selected or a factor) is removed<br>" +
                           "from the list.</p>" +
                        "<p></p>" +
                        "<p>The player with the highest score when the list is empty wins.</p>" +
                        "<p></p>" +
                        "<p>Good Luck!</p>" +
                    "</html>",
                    "How to Play",
                    JOptionPane.INFORMATION_MESSAGE);

            }
        });

        helpmenu.add(gameInstructions);        

        // Populate the menu bar
        menubar.add(filemenu);
        menubar.add(viewmenu);
        menubar.add(helpmenu);

        // Set the menu bar in the panel
        setJMenuBar(menubar);
    }
}

public class Factman_Swing extends Factman_GUI_old {
    static ArrayList<Integer> gameBoard;
    static int upperBound, factorIndex, p1Score = 0, p2Score = 0;
    static boolean player1 = true;

    public static void main(String args[]) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                Factman_GUI_old factman = new Factman_GUI_old();
                factman.setVisible(true);
            }
        });

        playGame();
    }

    public static void playGame() {
        // set the flag false to prevent a new game when someone wins
        newGameFlag = false;
        // make sure the label text is black
        //gameAreaLabel.setForeground(Color.black);

        // create a popup window to get the upper bound
        upperBound = Integer.parseInt(JOptionPane.showInputDialog(
            panel, "Enter the upper bound for this game", null));
        System.out.println("Upper bound = " + upperBound);

        // generate the arraylist with the given upper limit
        gameBoard = createList(upperBound);
        System.out.println(gameBoard);

        // as long as there are numbers left in the list, keep looping the game
        while(!gameBoard.isEmpty()) {
            // if the new game option was selected, go back to main
            if (newGameFlag) return;

            // show the list in the GUI
            gameAreaLabel.setVisible(!hideBoard.getState());
            gameAreaLabel.setText(gameBoard.toString());

            // indicate whose turn it is in the GUI
            if(player1) turnIndicator.setText("It's Player 1's Turn");
            else        turnIndicator.setText("It's Player 2's Turn");

            // userSelection becomes non-zero when a
            // number is entered in the text field
            if (userSelection >= 0) {
                // save the input and set it back to zero
                // so the loop doesnt fire again
                int selection = userSelection;
                userSelection = -1;
                System.out.println("User selected " + selection);

                // wrap the selection in an Integer object for comparison with the list
                Integer number = new Integer(selection);
                // the player will loose his/her turn if an invalid number is entered
                if (!gameBoard.contains(number)) {
                    JOptionPane.showMessageDialog(
                        panel,
                        "The number you selected is not in the list.\nYou loose a turn",
                        "OOPS",
                        JOptionPane.ERROR_MESSAGE);
                    player1 = !player1;
                    continue;
                }

                // add the selection to the current player's score
                if (player1) p1Score += selection;
                else         p2Score += selection;

                // search for and remove the selection from the list
                removeInt(gameBoard, selection);

                // as long as there are factors, add them to the other
                // players score and remove them from the list
                do {
                    factorIndex = findFactor(gameBoard, selection);
                    if (factorIndex >= 0) {
                        int value = gameBoard.get(factorIndex).intValue();
                        if (player1) p2Score += value;
                        else         p1Score += value;
                        // remove the factor
                        removeInt(gameBoard, value);
                    }
                } while (factorIndex >= 0);    // loop until no factor is found

                // show the scores in the GUI
                p1ScoreLabel.setText(String.valueOf(p1Score));
                p2ScoreLabel.setText(String.valueOf(p2Score));

                // switch players
                player1 = !player1;
            }
        }

        // Show who won
        gameAreaLabel.setForeground(Color.blue);
        if (p1Score > p2Score)       gameAreaLabel.setText("PLAYER 1 WINS!!!!");
        else if (p1Score < p2Score)  gameAreaLabel.setText("PLAYER 2 WINS!!!!");
        else gameAreaLabel.setText("Somehow, you managed to tie.  Nice going.");
    }

    /**
     * Create a list of Integer objects from 1 to limit, inclusive.
     * @param limit the upper bound of the list
     * @return an ArrayList of Integer type 
     */
    public static ArrayList<Integer> createList(int limit) {
        ArrayList<Integer> temp = new ArrayList<Integer>();
        for (int i = 1; i <= limit; i ++) {
            temp.add(new Integer(i));
        }
        return temp;
    }

    /**
     * Search for the specified value in the list and remove the object
     * from the list. The remove method of the ArrayList class removes
     * the object and shifts all of the objects following it to the
     * left one index.
     * @param list  an ArrayList of Integers to search
     * @param value the value to remove from the list
     * @see java.util.ArrayList#remove
     */
    private static void removeInt(ArrayList<Integer> list, int value) {
        // loop through the list until the value of the object matches
        // the specified value, then remove it
        for (Integer element : list) {
            if(element == value) {
                list.remove(element);
                break;
            }
        }
    }

    /**
     * Returns the index of the first factor of the specified number in
     * the specified ArrayList.  If no factor is found, -1 is returned.
     * @param list   an ArrayList of Integers to search
     * @param number the value to find factors of
     * @return the index of the first factor, or -1 if no factors exist
     */
    private static int findFactor(ArrayList<Integer> list, int number) {
        // loop through the list until the end or the specified number
        // this prevents index exceptions
        for (int i = 0; i < list.size() && i < number; i ++) {
            // check if the value divides evenly into the number
            if (number % list.get(i).intValue() == 0) {
                return i;
            }
        }
        // we only get here if no index was found
        return -1;
    }
}

GUI基本上是一样的,只是粘贴到一个单独的类中。

需要注意的是,MVC不是一种游戏设计模式,所以不要试图将你的游戏建立在它之上。@Jon我的印象是,MVC是一种通用设计,允许将逻辑与用户所看到的分开。我对swing的世界是全新的,对Java一般来说是相当陌生的。有更好的设计来满足我的需求吗。你能推荐一些关于这个主题的教程吗?好的,开始这项工作的方法是将所有GUI与其他任何东西分开。不要担心控制器和模型的问题。只要从一个哑GUI开始,它的所有功能都可以通过方法访问。在GUI中绝对没有智能。在这方面,您将要做的是从控制视图的内容中分离出如何查看内容的第一步。@tgm1024好的,这很好,但我遇到的问题是,我无法再使用菜单/文本字段上的事件侦听器。在一个单独的GUI类中,逻辑如何知道按下了什么以及何时按下?您可以将任何需要的内容输入到侦听器。侦听器是类,您可以像我现在假设的那样将它们设置为匿名的内部类,或者您可以将侦听器设置为自己的类文件,并且引用与导入和初始化一样简单。
package games.factman;

import java.util.ArrayList;

public class Factman {
    private ArrayList<Integer> list;
    private int playerTurn = 1;
    private int p1Score = 0, p2Score = 0;

    public Factman() {
        list = new ArrayList<Integer>();
    }

    public void startGame(int gameSize) {
        // fill the list with numbers
        for (int i = 1; i <= gameSize; i ++) {
            list.add(i);
        }
    }

    public boolean makeMove(int playerNumber, int selection) {
        int selectionIndex = list.indexOf(selection);
        if (selectionIndex < 0) {
            return false;
        }

        // Remove the selection now, so its not counted as a factor
        list.remove(selectionIndex);

        int factorIndex, factorSum = 0;
        do {
            factorIndex = findFirstFactor(selection);
            if (factorIndex >= 0) {
                int factorValue = list.get(factorIndex);
                factorSum += factorValue;
                list.remove(factorIndex);
            }
        } while (factorIndex > -1);

        if (playerNumber == 1) {
            p1Score += selection;
            p2Score += factorSum;
        }
        else if (playerNumber == 2) {
            p2Score += selection;
            p1Score += factorSum;   
        }
        // return true to indicate a successful move
        return true;
    }

    public int getPlayerScore(int playerNumber) {
        if (playerNumber == 1) {
            return p1Score;
        }
        else if (playerNumber == 2) {
            return p2Score;
        }
        else {
            return 0;
        }
    }

    public String getList() {
        return list.toString();
    }

    private int findFirstFactor(int number) {
        for (int i = 0; (i < list.size()) && (i < number); i ++) {
            if (number % list.get(i) == 0) {
                return i;
            }
        }
        return -1;
    }

    public static void main(String... args) {
        Factman game1 = new Factman();
        game1.startGame(15);
        System.out.println(game1.getList());
        game1.makeMove(1, 10);
        System.out.println(game1.getList());
        game1.makeMove(2, 8);
        System.out.println(game1.getList());

        System.out.println("P1: " + game1.getPlayerScore(1));
        System.out.println("P2: " + game1.getPlayerScore(2));
    }
}