代码之家  ›  专栏  ›  技术社区  ›  Teodor Kostovski

如何让程序重新生成一个“新游戏”,在这个游戏中,以前的网格字母被替换为新的网格字母

  •  0
  • Teodor Kostovski  · 技术社区  · 4 年前

    在这个程序中,我试图输入一个启动游戏的功能,如果我点击开始游戏(Main菜单),就会打开一个新的jpanel(MainGame),创建另一个jpanel,在网格中创建jbuttons。如果我返回并再次单击“开始游戏”,将生成一个新网格,而不是上一个网格,从而有效地开始一个“新游戏”。问题是,如果我返回并再次点击新游戏,程序会创建两个网格。

    我尝试过用=null删除网格面板的实例,但没有成功

    主要功能:

    import javax.swing.*;
    import java.awt.*;
    import java.awt.CardLayout;
    
    public class Game extends JFrame {
        MainMenu mainMenu;
        Settings settings;
        MainGame mainGame;
        CardLayout cl;
        JPanel container;
    
        public Game(){
            setSize(900,900); //have all as seperate classes
            setDefaultCloseOperation(3); //cl call container
            container  = new JPanel(); //container call menu1 and menu2
            cl = new CardLayout();
            mainMenu = new MainMenu();
            settings = new Settings();
            mainGame = new MainGame();
            mainMenu.setSettings(settings);
            settings.setMainMenu(mainMenu);
            settings.setMainGame(mainGame);
            mainMenu.setMainGame(mainGame);
            mainGame.setMainMenu(mainMenu);
            mainGame.setSettings(settings);
            container.setLayout(cl); //this stays here i think
    
    
    
            //add setter for main game here
            container.add(mainMenu,"1");
            container.add(settings,"2");
            container.add(mainGame,"3");
            mainMenu.setContainer(container);
            mainMenu.setCl(cl);
            settings.setContainer(container);
            settings.setCl(cl);
            mainGame.setContainer(container);
            mainGame.setCl(cl);
            cl.show(container, "1");
            add(container,BorderLayout.CENTER);
    
        }
    
        public static void main(String[] args) {
            Game game = new Game();
            game.setVisible(true);
        }
    }
    

    主要游戏类别:

    import javax.swing.*;
    import java.awt.*;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    
    
    public class MainGame extends JPanel {
        MainMenu mainMenu;
        Settings settings;
        CardLayout cl;
        JPanel container;
        String rows;
        String columns;
    
        public void setMainMenu(MainMenu mainMenu) {
            this.mainMenu = mainMenu;
        }
    
        public void setSettings(Settings settings) {
            this.settings = settings;
        }
    
        public void setCl(CardLayout cl) {
            this.cl = cl;
        }
    
        public void setContainer(JPanel container) {
            this.container = container;
        }
    
        public void setRows(String rows) {
            this.rows = rows;
        }
    
        public void setColumns(String columns) {
            this.columns = columns;
        }
        public MainGame(){
            JPanel north = new JPanel();
            north.setLayout(new FlowLayout());
            ReturnAction returnAl = new ReturnAction();
            JButton Return2 = new JButton("Return");
            Return2.addActionListener(returnAl);
            north.add(Return2);
            add(north);
        }
        class ReturnAction implements ActionListener {
            @Override
    
            public void actionPerformed(ActionEvent e) {
                cl.show(container,"1");
            }
        }
    }
    

    主菜单类(这个包含游戏生成部分):

    import javax.swing.*;
    import java.awt.*;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.util.Random;
    
    public class MainMenu extends JPanel {
    JPanel grid = new JPanel();
    MainGame mainGame;
    Settings settings;
    CardLayout cl;
    JPanel container;
    String rows;
    String columns;
    boolean checkexists = false;
    int rownumber;
    int columnnumber;
    
    
    public void setMainGame(MainGame mainGame) {
        this.mainGame = mainGame;
    }
    
    public void setCl(CardLayout cl) {
        this.cl = cl;
    }
    
    public void setContainer(JPanel container) {
        this.container = container;
    }
    
    public void setSettings(Settings settings) {
        this.settings = settings;
    }
    
    public void setRows(String rows) {
        this.rows = rows;
    }
    
    public void setColumns(String columns) {
        this.columns = columns;
    }
    
    public MainMenu() {
        setLayout(new GridLayout(3, 1));
        JButton Newgame = new JButton("New Game");
        JButton Cont = new JButton("Continue");
        JButton Sett = new JButton("Settings");
        add(Newgame);
        add(Cont);
        SwitchMenu1 switchMenu1 = new SwitchMenu1();
        SwitchMenu2 switchMenu2 = new SwitchMenu2();
        GenerateGame generateGame = new GenerateGame();
        Newgame.addActionListener(switchMenu2);
        Newgame.addActionListener(generateGame);
        Sett.addActionListener(switchMenu1);
        add(Sett);
    
    }
    
    class SwitchMenu1 implements ActionListener {
        @Override
    
        public void actionPerformed(ActionEvent e) {
            cl.show(container, "2");
    
        }
    }
    
    class SwitchMenu2 implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            cl.show(container, "3");
        }
    }
    
    class GenerateGame implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            if (checkexists == true){
                grid = null;
                grid = new JPanel();
            }
            try {
                rownumber = Integer.parseInt(rows);
            } catch (NumberFormatException be) {
                rownumber = 10;
            }
            try {
                columnnumber = Integer.parseInt(columns);
            } catch (NumberFormatException be) {
                columnnumber = 10;
            }
            Random rand = new Random();
            int randomnumber;
            String Letters = "AAIIOOUUEEABCDEFGHIJKLMNOPQRSTUVWXYZ";
            grid.setLayout(new GridLayout(rownumber, columnnumber));
            JButton[][] gridbutton = new JButton[rownumber][columnnumber];
            MainbuttonAL mainbuttonAL = new MainbuttonAL();
            for (int i = 0; i < rownumber; i++) {
                for (int j = 0; j < columnnumber; j++) {
                    if (checkexists == true){
                        gridbutton[i][j] = null;
                    }
                    randomnumber = rand.nextInt(Letters.length());
                    gridbutton[i][j] = new JButton("" + Letters.charAt(randomnumber));
                    gridbutton[i][j].addActionListener(mainbuttonAL);
                    grid.add(gridbutton[i][j]);
                }
            }
            mainGame.add(grid);
            checkexists = true;
        }
    }
    
    class MainbuttonAL implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
    
        }
    }
    }
    

    设置类:

    import javax.swing.*;
    import java.awt.*;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.util.Random;
    
    public class MainMenu extends JPanel {
        JPanel grid = new JPanel();
        MainGame mainGame;
        Settings settings;
        CardLayout cl;
        JPanel container;
        String rows;
        String columns;
        boolean checkexists = false;
        int rownumber;
        int columnnumber;
    
    
        public void setMainGame(MainGame mainGame) {
            this.mainGame = mainGame;
        }
    
        public void setCl(CardLayout cl) {
            this.cl = cl;
        }
    
        public void setContainer(JPanel container) {
            this.container = container;
        }
    
        public void setSettings(Settings settings) {
            this.settings = settings;
        }
    
        public void setRows(String rows) {
            this.rows = rows;
        }
    
        public void setColumns(String columns) {
            this.columns = columns;
        }
    
        public MainMenu() {
            setLayout(new GridLayout(3, 1));
            JButton Newgame = new JButton("New Game");
            JButton Cont = new JButton("Continue");
            JButton Sett = new JButton("Settings");
            add(Newgame);
            add(Cont);
            SwitchMenu1 switchMenu1 = new SwitchMenu1();
            SwitchMenu2 switchMenu2 = new SwitchMenu2();
            GenerateGame generateGame = new GenerateGame();
            Newgame.addActionListener(switchMenu2);
            Newgame.addActionListener(generateGame);
            Sett.addActionListener(switchMenu1);
            add(Sett);
    
        }
    
        class SwitchMenu1 implements ActionListener {
            @Override
    
            public void actionPerformed(ActionEvent e) {
                cl.show(container, "2");
    
            }
        }
    
        class SwitchMenu2 implements ActionListener {
            @Override
            public void actionPerformed(ActionEvent e) {
                cl.show(container, "3");
            }
        }
    
        class GenerateGame implements ActionListener {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (checkexists == true){
                    grid = null;
                    grid = new JPanel();
                }
                try {
                    rownumber = Integer.parseInt(rows);
                } catch (NumberFormatException be) {
                    rownumber = 10;
                }
                try {
                    columnnumber = Integer.parseInt(columns);
                } catch (NumberFormatException be) {
                    columnnumber = 10;
                }
                Random rand = new Random();
                int randomnumber;
                String Letters = "AAIIOOUUEEABCDEFGHIJKLMNOPQRSTUVWXYZ";
                grid.setLayout(new GridLayout(rownumber, columnnumber));
                JButton[][] gridbutton = new JButton[rownumber][columnnumber];
                MainbuttonAL mainbuttonAL = new MainbuttonAL();
                for (int i = 0; i < rownumber; i++) {
                    for (int j = 0; j < columnnumber; j++) {
                        if (checkexists == true){
                            gridbutton[i][j] = null;
                        }
                        randomnumber = rand.nextInt(Letters.length());
                        gridbutton[i][j] = new JButton("" + Letters.charAt(randomnumber));
                        gridbutton[i][j].addActionListener(mainbuttonAL);
                        grid.add(gridbutton[i][j]);
                    }
                }
                mainGame.add(grid);
                checkexists = true;
            }
        }
    
        class MainbuttonAL implements ActionListener {
            @Override
            public void actionPerformed(ActionEvent e) {
    
            }
        }
    }
    

    我可以使用什么方法重新生成网格?

    0 回复  |  直到 4 年前
        1
  •  1
  •   MadProgrammer    4 年前

    一般来说,您应该研究将视图和数据分离的概念,这意味着您可以有一个“游戏模型”,可以应用于视图,然后视图将根据模型属性修改自己,这通常被称为“模型-视图-控制器”。

    然而,问题是,你永远不会移除 grid 当你创建一个新游戏时,从它的父容器

    if (checkexists == true){
        grid = null;
        grid = new JPanel();
    }
    

    网格 ,则应将其从父容器中移除

    if (grid != null) {
        mainGame.remove(grid);
        grid = null;
        grid = new JPanel();
    }
    

    或者你也可以把组件从机器上取下来 网格 面板本身

    grid.removeAll();
    

    另一种方法。。。

    在所有阶段,您都应该尝试将对象和工作流彼此分离,以便更容易更改任何一个部分,而不会对系统或工作流的其他部分产生不利影响。

    例如,看看您的代码,导航决策与每个面板/视图紧密耦合,但实际上,他们不应该知道或关心导航是如何工作的(或存在其他视图的事实),他们应该只做这些工作。

    你应该花点时间通读。。。

    但这对你有什么帮助?好吧,它会一直帮助你!

    让我们从“游戏”本身开始。我们需要的第一件事是某种容器来保存游戏的数据库逻辑,因此根据您当前的代码,它可能看起来像。。。

    public interface GameModel {
        public int getRows();
        public int getColumns();
    }
    

    我知道,太棒了,不是吗,但这 interface 将逐渐掌握运行游戏所需的逻辑。

    现在,我们可以把这个应用到 GamePanel

    public class GamePane extends JPanel {
        
        public interface Obsever {
            public void back(GamePane source);
        }
    
        private GameModel model;
        private Obsever obsever;
        
        private JPanel contentPane;
        
        private ActionListener buttonActionListener = new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                didTap(e.getActionCommand());
            }
        };
        
        public GamePane(Obsever obsever) {
            this.obsever = obsever;
            
            setLayout(new BorderLayout());
            
            contentPane = new JPanel();
            add(new JScrollPane(contentPane));
            
            JButton backButton = new JButton("<< Back");
            backButton.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    obsever.back(GamePane.this);
                }
            });
            
            JPanel bannerPane = new JPanel(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.weightx = 1;
            gbc.anchor = GridBagConstraints.LINE_END;
            
            bannerPane.add(backButton, gbc);
            
            add(bannerPane, BorderLayout.NORTH);
        }
    
        @Override
        public Dimension getPreferredSize() {
            // Bunch of things we could do here, but this basically
            // acts as a stand in for CardLayout, otherwise the primary
            // view will be to small
            return new Dimension(800, 800);
        }
    
        public void setModel(GameModel model) {
            if (this.model == model) {
                // Do nothing, nothings changed
                return;
            }
            this.model = model;
            buildUI();
        }
    
        protected void buildUI() {
            contentPane.removeAll();
            if (model == null) {
                return;
            }
            String Letters = "AAIIOOUUEEABCDEFGHIJKLMNOPQRSTUVWXYZ";
            Random rnd = new Random();
            JButton[][] gridbutton = new JButton[model.getRows()][model.getColumns()];
            contentPane.setLayout(new GridLayout(model.getRows(), model.getColumns()));
            //Game.MainMenu.MainbuttonAL mainbuttonAL = new Game.MainMenu.MainbuttonAL();
            for (int i = 0; i < model.getRows(); i++) {
                for (int j = 0; j < model.getColumns(); j++) {
                    int randomnumber = rnd.nextInt(Letters.length());
                    gridbutton[i][j] = new JButton("" + Letters.charAt(randomnumber));
                    //gridbutton[i][j].addActionListener(mainbuttonAL);
                    contentPane.add(gridbutton[i][j]);
                }
            }
        }
        
        protected void didTap(String action) {
            
        }
    
    }
    

    现在,有趣的“多汁”部分在 buildUI 它被称为 setModel 当模型改变时。这只是基于 GameModel 财产。

    GamePane 通过它 Observer 界面 .我首先创建了一个单独的类来处理导航工作流。

    这意味着“如何”或“实现细节”与系统的其他部分分离或隐藏。相反,它使用了简单的观察者/委派工作流。

    每个视图都提供了一个 观察者 (对于更好的名称)它描述了需要执行的导航操作。例如,两个 SettingsPane 游戏窗格 只是拥有 back .他们不在乎之前发生了什么,这取决于导航控制器。

    public class NavigationPane extends JPanel {
    
        enum View {
            MAIN_MENU, GAME, SETTINGS
        }
    
        private CardLayout cardLayout;
        private GameModel model;
        private GamePane gamePane;
        
        // Just for testing...
        private Random rnd = new Random();
    
        public NavigationPane() {
            cardLayout = new CardLayout();
            setLayout(cardLayout);
    
            add(new MainMenu(new MainMenu.Observer() {
                @Override
                public void newGame(MainMenu source) {
                    gamePane.setModel(createModel());
                    navigateTo(View.GAME);
                }
    
                @Override
                public void continueGame(MainMenu source) {
                    // Because it's possible to push continue
                    // without starting a game
                    // It might be possible have a "menu" model
                    // which can be used to change the enabled state of
                    // the continue button based on the state of the
                    // game
                    gamePane.setModel(getOrCreateGameModel());
                    navigateTo(View.GAME);
                }
    
                @Override
                public void settingsGame(MainMenu source) {
                    navigateTo(View.SETTINGS);
                }
            }), View.MAIN_MENU);
            
            gamePane = new GamePane(new GamePane.Obsever() {
                @Override
                public void back(GamePane source) {
                    navigateTo(View.MAIN_MENU);
                }
            });
            add(gamePane, View.GAME);
            
            add(new SettingsPane(new SettingsPane.Obsever() {
                @Override
                public void back(SettingsPane source) {
                    navigateTo(View.MAIN_MENU);
                }
            }), View.SETTINGS);
    
            navigateTo(View.MAIN_MENU);
        }
        
        protected GameModel createModel() {
            model = new DefaultGameModel(rnd.nextInt(9) + 2, rnd.nextInt(9) + 2);
            return model;
        }
        
        protected GameModel getOrCreateGameModel() {
            if (model == null) {
                model = createModel();
            }
            return model;
        }
    
        protected void add(Component component, View view) {
            add(component, view.name());
        }
    
        protected void navigateTo(View view) {
            cardLayout.show(this, view.name());
        }
    
    }
    

    可运行的示例。。。

    所以,这是大量的断章取义的代码。下面的示例基本上是一种可能的方法,您可以采取这种方法来进一步减少目前代码库中不断增长的一些混乱和耦合。

    import java.awt.BorderLayout;
    import java.awt.CardLayout;
    import java.awt.Component;
    import java.awt.Dimension;
    import java.awt.EventQueue;
    import java.awt.GridBagConstraints;
    import java.awt.GridBagLayout;
    import java.awt.GridLayout;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.util.Random;
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JPanel;
    import javax.swing.JScrollPane;
    
    public class Test {
    
        public static void main(String[] args) {
            new Test();
        }
    
        public Test() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    JFrame frame = new JFrame();
                    frame.add(new NavigationPane());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }
            });
        }
    
        public class NavigationPane extends JPanel {
    
            enum View {
                MAIN_MENU, GAME, SETTINGS
            }
    
            private CardLayout cardLayout;
            private GameModel model;
            private GamePane gamePane;
    
            // Just for testing...
            private Random rnd = new Random();
    
            public NavigationPane() {
                cardLayout = new CardLayout();
                setLayout(cardLayout);
    
                add(new MainMenu(new MainMenu.Observer() {
                    @Override
                    public void newGame(MainMenu source) {
                        gamePane.setModel(createModel());
                        navigateTo(View.GAME);
                    }
    
                    @Override
                    public void continueGame(MainMenu source) {
                        // Because it's possible to push continue
                        // without starting a game
                        // It might be possible have a "menu" model
                        // which can be used to change the enabled state of
                        // the continue button based on the state of the
                        // game
                        gamePane.setModel(getOrCreateGameModel());
                        navigateTo(View.GAME);
                    }
    
                    @Override
                    public void settingsGame(MainMenu source) {
                        navigateTo(View.SETTINGS);
                    }
                }), View.MAIN_MENU);
    
                gamePane = new GamePane(new GamePane.Obsever() {
                    @Override
                    public void back(GamePane source) {
                        navigateTo(View.MAIN_MENU);
                    }
                });
                add(gamePane, View.GAME);
    
                add(new SettingsPane(new SettingsPane.Obsever() {
                    @Override
                    public void back(SettingsPane source) {
                        navigateTo(View.MAIN_MENU);
                    }
                }), View.SETTINGS);
    
                navigateTo(View.MAIN_MENU);
            }
    
            protected GameModel createModel() {
                model = new DefaultGameModel(rnd.nextInt(9) + 2, rnd.nextInt(9) + 2);
                return model;
            }
    
            protected GameModel getOrCreateGameModel() {
                if (model == null) {
                    model = createModel();
                }
                return model;
            }
    
            protected void add(Component component, View view) {
                add(component, view.name());
            }
    
            protected void navigateTo(View view) {
                cardLayout.show(this, view.name());
            }
    
        }
    
        public class MainMenu extends JPanel {
    
            public interface Observer {
                public void newGame(MainMenu source);
                public void continueGame(MainMenu source);
                public void settingsGame(MainMenu source);
            }
    
            private Observer observer;
    
            public MainMenu(Observer observer) {
                this.observer = observer;
                setLayout(new GridBagLayout());
    
                JButton newGameButton = new JButton("New Game");
                JButton continueButton = new JButton("Continue");
                JButton settingsButton = new JButton("Settings");
    
                GridBagConstraints gbc = new GridBagConstraints();
                gbc.fill = GridBagConstraints.HORIZONTAL;
                gbc.gridwidth = GridBagConstraints.REMAINDER;
    
                add(newGameButton, gbc);
                add(continueButton, gbc);
                add(settingsButton, gbc);
    
                newGameButton.addActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        observer.newGame(MainMenu.this);
                    }
                });
    
                continueButton.addActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        observer.continueGame(MainMenu.this);
                    }
                });
    
                settingsButton.addActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        observer.settingsGame(MainMenu.this);
                    }
                });
            }
    
        }
    
        public class SettingsPane extends JPanel {
    
            public interface Obsever {
                public void back(SettingsPane source);
            }
    
            public SettingsPane(Obsever obsever) {
                setLayout(new GridBagLayout());
                GridBagConstraints gbc = new GridBagConstraints();
                gbc.gridwidth = GridBagConstraints.REMAINDER;
                add(new JLabel("All your setting belong to us"), gbc);
    
                JButton backButton = new JButton("<< Back");
                backButton.addActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        obsever.back(SettingsPane.this);
                    }
                });
    
                add(backButton, gbc);
            }
    
        }
    
        public interface GameModel {
            public int getRows();
            public int getColumns();
        }
    
        public class DefaultGameModel implements GameModel {
    
            private int rows;
            private int columns;
    
            public DefaultGameModel(int rows, int columns) {
                this.rows = rows;
                this.columns = columns;
            }
    
            @Override
            public int getRows() {
                return rows;
            }
    
            @Override
            public int getColumns() {
                return columns;
            }
    
        }
    
        public class GamePane extends JPanel {
    
            public interface Obsever {
                public void back(GamePane source);
            }
    
            private GameModel model;
            private Obsever obsever;
    
            private JPanel contentPane;
    
            private ActionListener buttonActionListener = new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    didTap(e.getActionCommand());
                }
            };
    
            public GamePane(Obsever obsever) {
                this.obsever = obsever;
    
                setLayout(new BorderLayout());
    
                contentPane = new JPanel();
                add(new JScrollPane(contentPane));
    
                JButton backButton = new JButton("<< Back");
                backButton.addActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        obsever.back(GamePane.this);
                    }
                });
    
                JPanel bannerPane = new JPanel(new GridBagLayout());
                GridBagConstraints gbc = new GridBagConstraints();
                gbc.weightx = 1;
                gbc.anchor = GridBagConstraints.LINE_END;
    
                bannerPane.add(backButton, gbc);
    
                add(bannerPane, BorderLayout.NORTH);
            }
    
            @Override
            public Dimension getPreferredSize() {
                // Bunch of things we could do here, but this basically
                // acts as a stand in for CardLayout, otherwise the primary
                // view will be to small
                return new Dimension(800, 800);
            }
    
            public void setModel(GameModel model) {
                if (this.model == model) {
                    // Do nothing, nothings changed
                    return;
                }
                this.model = model;
                buildUI();
            }
    
            protected void buildUI() {
                contentPane.removeAll();
                if (model == null) {
                    return;
                }
                String Letters = "AAIIOOUUEEABCDEFGHIJKLMNOPQRSTUVWXYZ";
                Random rnd = new Random();
                JButton[][] gridbutton = new JButton[model.getRows()][model.getColumns()];
                contentPane.setLayout(new GridLayout(model.getRows(), model.getColumns()));
                //Game.MainMenu.MainbuttonAL mainbuttonAL = new Game.MainMenu.MainbuttonAL();
                for (int i = 0; i < model.getRows(); i++) {
                    for (int j = 0; j < model.getColumns(); j++) {
                        int randomnumber = rnd.nextInt(Letters.length());
                        gridbutton[i][j] = new JButton("" + Letters.charAt(randomnumber));
                        //gridbutton[i][j].addActionListener(mainbuttonAL);
                        contentPane.add(gridbutton[i][j]);
                    }
                }
            }
    
            protected void didTap(String action) {
    
            }
    
        }
    }