Java按钮反转

标签 java swing

当我禁用用户按下或不按下的按钮时,会发生神秘的反转。该项目是设置一个战舰游戏,一侧用于计算机,另一侧用于用户。当我有这样的用户可以同时按下两个按钮时,船舶会在点击时正确显示在按钮上。但当计算机将按钮射向南时,神秘地反转了 90 度。这是代码的主要部分和 AI 类

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileNotFoundException;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;

/**
 * @author Alex Larson
 * Project #3
 * This is the main part of the BattleshipGUI.
 * This class has several inner classes that are listeners.
 * This class also has the main method in it.
 * This class sets up the entire GUI.
 */
public class BsGui extends JFrame {

    /**Array of FireButtons for the player */
    FireButton play[][] = null;

    /**Array of FireButtons for the player */
    FireButton opp[][] = null;

    /**A static constant for the player's BattleshipBoard */
    public static BattleshipBoard playerB;

    /**A static constant for the opponent's (or computer's) BattleshipBoard */
    public static BattleshipBoard opponentB;

    /**A static constant for a computer AI object */
    public static ComputerAI AI;

    /**A static constant that stores the computers designated AI */ 
    public static char computer;

    /**public int for passing around the shot the computer takes */ 
    public int[][] compShot;

    /**BorderLayout for the JFrame */
    public BorderLayout br;

    /**GridLayout for main JPanel */
    public GridLayout gr;

    /**GridLayout for both FireButton holding JPanels */
    public GridLayout gr2;

    /**GridLayout for bottom JPanel */
    public GridLayout gr3;

    /**FlowLayout: not used */
    public FlowLayout fl;

    /**JPanel that has the players FireButtons in it */
    public JPanel playB;

    /**JPanel that has the opponent's (or computer's) FireButtons in it */
    public JPanel oppB;

    /**JPanel that is not needed but hold the 2 FireButton holding JPanels */
    public JPanel main;

    /**JPanel that holds the title JLabel */
    public JPanel top;

    /**JPanel that hold shipsLeft button and ships JLabel */
    public JPanel bottom;

    /**Another not used, unneeded JPanel */
    public JPanel left;

    /**Another not used, unneeded JPanel */
    public JPanel right;

    /**JButton used to show user number of ships left */
    public JButton shipsLeft;

    /**JLabel used to show the title of the game */
    public JLabel title;

    /**JLabel used when game is over */
    public JLabel win;

    /**JLabel used to the user the number of ships left */
    public JLabel ships;

    /**Font used to change styles text */
    public Font font = null;

    /**
     * Constructor for BsGui. It creates a GUI with JLabel as a center
     * title and has 2 JPanels that hold arrays of FireButtons. It 
     * also sets up a button at the bottom that gives you the 
     * number of ships left for the players board, not the computers board.
     */
    public BsGui(){
        //Instantiating Section
        play = new FireButton[10][10];
        opp = new FireButton[10][10];
        br = new BorderLayout(10,10);
        gr = new GridLayout(1,2);
        gr2 = new GridLayout(10,10);
        gr3 = new GridLayout(2,2);
        fl = new FlowLayout();
        playB = new JPanel();
        oppB = new JPanel();
        main = new JPanel();
        top  = new JPanel();
        bottom = new JPanel();
        left = new JPanel();
        right = new JPanel();
        shipsLeft = new JButton();
        title = new JLabel();
        win = new JLabel();
        ships = new JLabel();
        font = new Font("Veranda", Font.BOLD, 20);
        compShot = new int[2][1];

        //Setting parameters for GUI 
        main.setBackground(Color.white);
        main.setLayout(gr);
        top.add(title);
        playB.setBackground(Color.cyan);
        playB.setName("Player Board");
        playB.setLayout(gr2);
        oppB.setBackground(Color.magenta);
        oppB.setName("Computer Board");
        oppB.setLayout(gr2);
        shipsLeft.setText("How Many Ships Left");
        shipsLeft.setVisible(true);
        title.setText("Battleship");
        title.setFont(font);
        this.setTitle("Battlseship");
        this.setSize(1100, 700);
        this.setLayout(br);     

        //Adding Listeners
        shipsLeft.addActionListener(new ShipsLeftListener());


        //Adding components to GUI section
        this.add(main, BorderLayout.CENTER);
        this.add(top, BorderLayout.NORTH);
        this.add(bottom, BorderLayout.SOUTH);
        this.add(left, BorderLayout.WEST);
        this.add(right, BorderLayout.EAST);
        this.addFireBottonsToArray();
        this.addFireButtonsPlay();
        this.addFireButtonsOpp();
        main.add(playB);
        main.add(oppB);
        bottom.add(shipsLeft);
        bottom.add(ships);
    }

    /**
     * This method adds new FireButtons to each part of the 
     * FireButton arrays. The first for loop adds buttons for the 
     * player. The second for loop adds buttons for the computer 
     * and makes them not click-able.
     */
    private void addFireBottonsToArray(){
        //Adds FireButtons to play array
        for(int i = 0; i < 10; i++){
            for(int j = 0; j < 10; j++){
                play[j][i] = new FireButton(j, i);
            }
        }
        //Adds FireButtons to opp array
        for(int i = 0; i < 10; i++){
            for(int j = 0; j < 10; j++){
                opp[j][i] = new FireButton(j, i);
                //opp[j][i].setEnabled(false);
            }
        }
    }

    /**
     * This method adds and listener to each FireButton
     * before adding it to the JPanel for the player.
     */
    private void addFireButtonsPlay(){
        for(int i = 0; i < 10; i++){
            for(int j = 0; j < 10; j++){
                play[j][i].addActionListener( new FireButtonListener());
                playB.add(play[j][i]);
            }
        }
    }

    /**
     * This method adds and listener to each FireButton
     * before adding it to the JPanel for the computer.
     */
    private void addFireButtonsOpp(){
        for(int i = 0; i < 10; i++){
            for(int j = 0; j < 10; j++){
                opp[j][i].addActionListener( new OpponentButtonListener());
                oppB.add(opp[j][i]);
            }
        }
    }   

    /**
     * This method hits buttons for the computer where ever 
     * the AI tells it to. Int x is the row of the button and
     * int y is the column.
     * 
     * @param int x 
     *          The row coordinate.
     * @param int y
     *          The column coordinate.
     */
    public void computerButtonHitter(int x, int y){
        if(opponentB.fireShot(x, y) ==  true){
            opp[x][y].setBackground(Color.RED); 
            opp[x][y].setFont(font);
            opp[x][y].setText("H");
        }
        else{
            opp[x][y].setBackground(Color.BLUE);
            opp[x][y].setFont(font);
            opp[x][y].setText("M");
        }
    }

    /**
     * This inner class is for the FireButton Listener. This particular 
     * class does probably too much but it was an easy way to do the 
     * problem at hand. 
     */
    public class FireButtonListener implements ActionListener{
        /**
         * This method is mandatory with implementing ActionListener. 
         * When a FireButton is pressed it finds the place it was fired at
         * and changes it to red if a ship exists at that spot and if 
         * not turns it blue. So red means hit and blue means miss. This 
         * method also adds an 'H' for hit and 'M' for miss to the button.
         * This method then also calls the method to make the computer 
         * do its move based on a switch case for which AI to use. 
         * 
         * @param ActionEvent
         *          The event that triggers this method.
         */
        public void actionPerformed(ActionEvent e){
            if(e.getSource() instanceof FireButton){
                FireButton fb = (FireButton)e.getSource();
                //System.out.println("FireButton at "+(fb.getCell().getColumn()+1)+", "+(fb.getCell().getRow()+1)+" was pressed");
                if(playerB.fireShot(fb.getCell().getColumn(), fb.getCell().getRow()) ==  true){
                    play[fb.getCell().getRow()][fb.getCell().getColumn()].setBackground(Color.RED); 
                    play[fb.getCell().getRow()][fb.getCell().getColumn()].setFont(font);
                    play[fb.getCell().getRow()][fb.getCell().getColumn()].setText("H");
                    play[fb.getCell().getRow()][fb.getCell().getColumn()].setEnabled(false);
                }
                else{
                    play[fb.getCell().getRow()][fb.getCell().getColumn()].setBackground(Color.BLUE);
                    play[fb.getCell().getRow()][fb.getCell().getColumn()].setFont(font);
                    play[fb.getCell().getRow()][fb.getCell().getColumn()].setText("M");
                    play[fb.getCell().getRow()][fb.getCell().getColumn()].setEnabled(false);
                }           
                switch(computer){
                case 'r':
                    compShot = AI.randomShot();
                    computerButtonHitter(compShot[0][0], compShot[1][0]);
                    break;
                case 's':
                    compShot = AI.systematicShot();
                    computerButtonHitter(compShot[0][0], compShot[1][0]);
                    break;
                }
                if(playerB.isGameOver() == true){
                    main.remove(playB);
                    main.remove(oppB);
                    font = new Font("Veranda", Font.BOLD, 50);
                    win.setFont(font);
                    win.setText("Congratulations u win!");
                    main.add(win);
                }
                if(opponentB.isGameOver() == true){
                    main.remove(playB);
                    main.remove(oppB);
                    font = new Font("Veranda", Font.BOLD, 50);
                    win.setFont(font);
                    win.setText("Awe too bad, the computer won");
                    main.add(win);
                }
            }
        }
    }

    /**
     * This Class is simple and offers the user a way finding how 
     * many ships he or she still needs to destroy.
     */
    public class ShipsLeftListener implements ActionListener{
        /**
         * This method is mandatory when implementing ActionListener.
         * It sets the JLabel ships to the number of ships left
         * when the button is pressed.
         * 
         * @param ActionEvent
         *          The event that triggers this method.
         */
        public void actionPerformed(ActionEvent e){
            ships.setText("" + playerB.getNumBattleshipsLeft());            
        }
    }

    /**
     * This class works exactly as the first part of FireButtonListener. 
     * The only difference is it doesn't work now since all the 
     * opponent's (computer) buttons are disabled. This method is here 
     * for later use for 2 player mode. (Did not have time to get that far).
     */
    public class OpponentButtonListener implements ActionListener{

        /**
         * This method is mandatory with implementing ActionListener. 
         * When a FireButton is pressed it finds the place it was fired at
         * and changes it to red if a ship exists at that spot and if 
         * not turns it blue. So red means hit and blue means miss. This 
         * method also adds an 'H' for hit and 'M' for miss to the button.
         * 
         * @param ActionEvent
         *          The event that triggers this method.
         */
        public void actionPerformed(ActionEvent e){
            if(e.getSource() instanceof FireButton){
                FireButton fb = (FireButton)e.getSource();
                //System.out.println("Opponent Button Pressed at "+(fb.getCell().getColumn()+1)+", "+(fb.getCell().getRow()+1)+" was pressed");
                if(opponentB.fireShot(fb.getCell().getColumn(), fb.getCell().getRow()) ==  true){
                    opp[fb.getCell().getRow()][fb.getCell().getColumn()].setBackground(Color.RED);  
                    opp[fb.getCell().getRow()][fb.getCell().getColumn()].setFont(font);
                    opp[fb.getCell().getRow()][fb.getCell().getColumn()].setText("H");
                    opp[fb.getCell().getRow()][fb.getCell().getColumn()].setEnabled(false);
                }
                else{
                    opp[fb.getCell().getRow()][fb.getCell().getColumn()].setBackground(Color.BLUE);
                    opp[fb.getCell().getRow()][fb.getCell().getColumn()].setFont(font);
                    opp[fb.getCell().getRow()][fb.getCell().getColumn()].setText("M");
                    opp[fb.getCell().getRow()][fb.getCell().getColumn()].setEnabled(false);
                }
            }
        }       
    }

    /**
     * Main Function
     * 
     * The main runs everything as normal. :P
     * It creates a GUI, an AI, and 2 BattleshipBoards. 
     * 
     * @param args
     *            Command line arguments
     *            For program to work correctly it 
     *            requires the first arg to be a path to 
     *            the player's ship placements. The second 
     *            arg requires the same as the first but for the 
     *            opponent. The 3rd arg requires a single letter 
     *            that represents the chosen AI for the computer. 
     *            The only supported letters at the moment are 'r' and 's'. 
     *            'r' is random and 's' is systematic. Other computer AIs and 
     *            difficulties will be added later.
     */
    public static void main(String[] args) {
        String player;
        String opponent;
        String inputAI;
        File fPlay;
        File fOpp;
        player = args[0];
        opponent = args[1];
        inputAI = args[2];
        computer = inputAI.charAt(0);
        AI = new ComputerAI(computer);
        try{            
            fPlay = new File(player);
            fOpp = new File(opponent);
            playerB = new BattleshipBoard(fPlay);
            opponentB = new BattleshipBoard(fOpp);
        }
        catch(FileNotFoundException fne){
            System.out.println("File path given must be wrong or file doesnt exist");
            System.exit(0);
        }
        catch(Exception e){
            System.exit(0);
        }
        JFrame gui = new BsGui();   
        gui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        gui.setVisible(true);
    }
}








import java.util.Random;

/**
 * 
 * @author Alex Larson XPS
 *
 *This class is how the computer gets its brains.
 *Has a constructor to set up the computer and 2 brain methods.
 *One method gives random shots and the other gives systematic shots.
 *More brain options to be added later.
 */
public class ComputerAI {

    /**This hold the last shot X coordinate */
    public int lastShotX;

    /**This hold the last shot Y coordinate */
    public int lastShotY;

    /**Not used, but will be for smarter AI
     * will be for determining if last shot was a hit or not */
    public boolean wasLastShotHit;

    /**Not used, but will be for smarter AI,
     * will be for holding last X hit */
    public int lastHitX;

    /**Not used, but will be for smarter AI,
     * will be for holding last Y hit */
    public int lastHitY;

    /**Not used, but would be for keeping track of shots fired */
    public int shotCounter;

    /**Used for passing on the coordinates of the shot fired */
    public int shotFired[][];

    /**Used to keep track of all shots fired coordinates */
    public int shotsFired[][];

    /**The random number generator */
    public Random gen;

    /**Keeps track of the computer AI */
    public char typeOfAI;

    /**
     * This is the computerAI constructor.
     * It initializes all variables and
     * gets the random generator ready to use.
     * 
     * @param c
     *      This is the char that determines the type of AI to be used.
     */
    public ComputerAI(char c){
        lastShotX = -1;
        lastShotY = -1;
        wasLastShotHit = false;
        lastHitX = -1;
        lastHitY = -1;
        shotCounter = 0;
        //At 0,0 shotX will be stored and at 1,0 shotY will be stored
        shotFired = new int[2][1];
        //There are 100 total shots on a 10x10 board
        //So this will hold 100 coordinates of shots
        shotsFired = new int[100][2];
        for(int i = 0; i < 100; i++){
            int j = 0;
            shotsFired[i][j] = -1;
            shotsFired[i][j+1] = -1;            
        }
        //Initializes the random number generator
        gen = new Random(9);
        typeOfAI = c;
    }   

    /**
     * Grabs the char representing the AI and returns it
     * 
     * @return the type of AI being used
     */
    public char getTypeOfAI(){
        return typeOfAI;
    }


    /**
     * This is the random shot brain.
     * It uses a random number generator to makes random shots.
     * It also keeps track of previous shots taken in shotsFired.
     * After making sure the shot has been taken before it returns
     * those coordinates.s
     * 
     * @return the int[][] that represents the coordinates of the shot fired
     */
    public int[][] randomShot(){
        int hitX = gen.nextInt(9);
        int hitY = gen.nextInt(9);
        shotFired[0][0] = hitX;
        shotFired[1][0] = hitY;
        int i;
        for(i = 0; i < 100; i++){
            //This if statement is for setting that this shot has been taken 
            if(shotsFired[i][0] == -1){
                shotsFired[i][0] = hitX;
                shotsFired[i][1] = hitY;
                break;
            }
            //This if statement is to make sure the shot being generated
            //has not been taken yet.
            if(shotsFired[i][0] == hitX && shotsFired[i][1] == hitY){
                hitX = gen.nextInt(9);
                hitY = gen.nextInt(9);
                shotFired[0][0] = hitX;
                shotFired[1][0] = hitY;
            }           
        }
        System.out.println(hitX +" "+ hitY);
        return shotFired;
    }

    /**
     * This is the systematic brain. 
     * It marches along row by row to fire shots.
     * It keeps track of the last shot taken by using 
     * lastShotX and lastShotY. It then return the 
     * shot fired.
     * 
     * @return the int[][] that represents the coordinates of the shot fired
     */
    public int[][] systematicShot(){
        if(lastShotX == -1 && lastShotY == -1){
            lastShotX = 0;
            lastShotY = 0; 
            shotFired[0][0] = lastShotX;
            shotFired[1][0] = lastShotY;
            return shotFired;
        }
        for(int i = 0; i < 10; i++){
            if(lastShotX == -1){
                lastShotX = 0;
                shotFired[0][0] = lastShotX;
                shotFired[1][0] = lastShotY;
                return shotFired;
            }
            for(int j = 0; j < 10; j++){
                if(lastShotX == j && lastShotY == i){
                    if(lastShotX == 9){
                        lastShotX = -1;
                        lastShotY++;
                    }
                    else{
                        lastShotX = j+1;                        
                        shotFired[0][0] = lastShotX;
                        shotFired[1][0] = lastShotY;
                        return shotFired;
                    }
                }               
            }
        }
        return shotFired;
    }
}

最佳答案

如果你比较你的方法computerButtonHitter

    if(opponentB.fireShot(x, y) ==  true){
        opp[x][y].setBackground(Color.RED); 
        opp[x][y].setFont(font);
        opp[x][y].setText("H");
    }
    else{
        opp[x][y].setBackground(Color.BLUE);
        opp[x][y].setFont(font);
        opp[x][y].setText("M");
    }

使用FireButtonListener

            if(playerB.fireShot(fb.getCell().getColumn(), fb.getCell().getRow()) ==  true){
                play[fb.getCell().getRow()][fb.getCell().getColumn()].setBackground(Color.RED); 
                play[fb.getCell().getRow()][fb.getCell().getColumn()].setFont(font);
                play[fb.getCell().getRow()][fb.getCell().getColumn()].setText("H");
                play[fb.getCell().getRow()][fb.getCell().getColumn()].setEnabled(false);
            }
            else{
                play[fb.getCell().getRow()][fb.getCell().getColumn()].setBackground(Color.BLUE);
                play[fb.getCell().getRow()][fb.getCell().getColumn()].setFont(font);
                play[fb.getCell().getRow()][fb.getCell().getColumn()].setText("M");
                play[fb.getCell().getRow()][fb.getCell().getColumn()].setEnabled(false);
            }           

你会发现不同之处。简而言之,第一个有 opponentB.fireShot(x,y)opp[x][y]....,而第二个有 playerB。 fireShot(c,r)play[r][c].... 因此,虽然第一个在方法和数组中具有相同的顺序,但第二个却没有。我想你应该更换其中之一以保持彼此的一致性。所以要么 opp[y][x] 要么 play[c][r] 但我无法判断哪一个是正确的(因为我没有完整的代码)。

关于Java按钮反转,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4989485/

相关文章:

java - 排序列表 <> 未按预期工作

java - 如何使用icu4j在java中将单词转换为数字

java - 我的 JRadioButton 无法与我的 Action 监听器一起使用

Java 按钮暂停图形更新

java - Cursor,CursorAdapter,LoaderManager,Loader之间的关系

java - Spark streaming 2.11 - java.util.NoSuchElementException : None. 在执行 SQL 函数时出错

java - Java中获取当前显示尺寸

java - 如何在不卡住 GUI 的情况下调用 SwingWorker .get()?

java - 父类(super class)不能分配给运行时由 asm 实现的类

java - 如何在编辑时更改 JTable 单元格文本?