有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何将对象从另一个类传递到paintComponent方法?

我的任务是制作游戏“洪水”如果你需要理解的话,你可以在这里玩这个游戏,但我认为这不是真的必要:http://unixpapa.com/floodit/

我已经完成了它的实际游戏部分,但现在我需要为它制作一个图形界面。我有三门课:

董事会。java,它使棋盘具有随机的int值,并包含其他几种使游戏正常运行的方法:

import java.awt.Color;
import java.util.Random;


/**The board class for the Flood-It game.  This class implements a NxN board filled with numColors colors.
 * The class implements several methods to allow the playing of the game.
 */

class Board {

//you will probably need to create some field variables
private int size;
private int numColors;
private int[][] board;
private int numOfMoves;
/**Constructs a new sizeXsize board filled where each element on the board is a random number between 0
 * and numColors.  Also initializes the number of moves to zero.
 * @param size -- the size of the board
 * @param numColors -- the number of possible entries on the board
 */
public Board(int size,int numColors) {
    //TODO finish this constructor
    this.size = size;
    this.numColors = numColors;
    numOfMoves = 0;



    board = new int[size][size];
    Random rand = new Random();
    int randomNum = 0;
    for (int count = 0; count < size; count++) {
        for (int counter = 0; counter < size; counter++) {
            randomNum = rand.nextInt(this.numColors);
            board[count][counter] = randomNum;
        }
    }


}


/**Updates the board to fill (from the top left corner) with a specified color.  
 * Filling stops when any other color is hit besides the one in the top left corner.
 * Play the game at http://www.lemoda.net/javascript/flood-it/ or http://unixpapa.com/floodit/?sz=14&nc=4
 * to get a better understanding of what this method should do.
 * You will probably also want to take a look at the algorithm described
 * at http://en.wikipedia.org/wiki/Flood_fill which describes what this method should do.
 * I recommend the Stack-based recursive implementation.  It is a recursive algorithm for
 * flooding the board.  It is one of the easier ones to implement.
 * You are free to have this method call other methods.  I would recommend creating a private method that
 * this method calls and have that private method be the recursive method.
 * A recursive method is one that calls itself.
 * @param color -- the new color to flood the board with.
 */
public void move(int replacementColor) {
    int targetColor = board[0][0];
    recursiveMove(0,0,targetColor,replacementColor);
    numOfMoves++;
}

private void recursiveMove(int xCoord, int yCoord, int targetColor, int replacementColor) {
    if (targetColor == replacementColor) {
        return;
    }
    if (board[xCoord][yCoord] != targetColor) {
        return;
    }

    board[xCoord][yCoord] = replacementColor;
    if (yCoord != size-1) {
        recursiveMove(xCoord,yCoord+1,targetColor,replacementColor);
    }
    if (yCoord != 0) {
        recursiveMove(xCoord,yCoord-1,targetColor,replacementColor);
    }
    if (xCoord != 0) {
        recursiveMove(xCoord-1,yCoord,targetColor,replacementColor);
    }
    if (xCoord != size-1) {
        recursiveMove(xCoord+1,yCoord,targetColor,replacementColor);
    }
}


/**returns true if the board is not completely filled with a single color.
 * Otherwise it returns false.
 * @return true if board is all one color
 */
public boolean finished() {
    //TODO finish this method
    for (int count = 0; count < size; count++) {
        for (int counter = 0; counter < size; counter++) {
            if (board[count][counter] != board[0][0]) {
                return false;
            }
        }
    }
    return true;
}


/**returns how many times the move() method has been called.
 * @return the number of times the move() method has been called.
 */
public int numMoves() {
    //TODO finish this method
    return numOfMoves;
}


/**Returns a string representation of the board.  Use tabs between elements of the board.
 * And have every row of the board be separated by a newline character.
 * Example:
 * "1\t0\t3\t\n2\t0\t2\t\n1\t0\t1\t\n"
 * @return a String representation of the board
 */
public String toString() {
    //TODO finish this method
    String boardString = "";
    for (int count = 0; count < board.length; count++) {
        for (int counter = 0; counter < board.length; counter++) {
            boardString += board[count][counter];
            boardString += "\t";
        }
        boardString += "\n";
    }
    return boardString;
}
}

淹没它。java,其中包含用于加载图形界面的JFrame行,以及用于实际运行游戏的代码(由于我被卡住,它还没有完全完成):

import java.util.Scanner;
import javax.swing.JFrame;

/**This class is the main method for the Flood-It game as found on many web sites 
 * ( such as http://www.lemoda.net/javascript/flood-it/ or 
http://unixpapa.com/floodit/?sz=14&nc=4 ).
 * It prompts the user for the size of the board
 * and the number of colors.  The user is prompted for the next color until the board is flooded.
 * After the game is over it prints how many turns the user took and then asks if they want to play again.
 */
class FloodIt {

private static final int FRAMESIZE = 1000;

public static void main(String args[]) {
    JFrame frame = new JFrame();
    frame.setSize(FRAMESIZE,FRAMESIZE);
    frame.setTitle("Brennan's Game");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    GraphicalBoard component = new GraphicalBoard();
    frame.add(component);
    frame.setVisible(true);

    String again="";
    int size = 20;
    int numColors = 7;
    do {
        Board board=new Board(size,numColors);
        while(!board.finished()) {
            //I will change the print statements below into graphical input boxes later
            System.out.print("****************\n"+board+"\n****************\n");
            System.out.print("What color do you choose? ");
            int color=Integer.parseInt(scan.nextLine());
            board.move(color);
        }
        System.out.println("Nice job, you finished in "+board.numMoves());
        System.out.print("Would you like to play again (Y/N)? ");
        again=scan.nextLine();
    } while (again.equalsIgnoreCase("Y"));
    scan.close();
}
}

和图形板。java,它应该从板上获取2d数组的值。java,并在图形界面中显示电路板。2d数组中的每个数字都对应于颜色数组中的一种颜色:

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import javax.swing.JComponent;

public class GraphicalBoard extends JComponent {
private int xSize = 50;
private int ySize = 50;
public void paintComponent(Graphics g, int size, Board board) {
    String colors[] = {"BLUE","GREEN","YELLOW","RED","BLACK","ORANGE","PINK"};
    Graphics2D g2 = (Graphics2D) g;
    int xCoord = 0;
    int yCoord = 0;
    int colorNum = 0;
    String colorOfSquare = "";
    for (int count = 0; count < size; count++) {
        for (int counter = 0; counter < size; counter++) {
            colorNum = board[count][counter];
            colorOfSquare = colors[colorNum];
            g2.setColor(Color.colorOfSquare);
            Rectangle square = new Rectangle(xCoord,yCoord,xSize,ySize);
            xCoord += 50;
        }
        yCoord += 50;
    }
}

}

两个问题:

  1. 在图形板中。java,在“colorNum=board[count][counter];”行上,我得到了一个错误:“表达式的类型必须是数组类型,但它已解析为Board。”

我似乎遇到了一个问题,将已经初始化的电路板从电路板中取出。将java类转换为GraphicalBoard。java类

  1. 在图形板中。java,在“g2.setColor(Color.colorOfSquare);”行上,我得到一个错误:“colorOfSquare无法解析,或者它不是一个字段。”

我知道这个问题,应该是“g2.setColor(Color.BLACK);”,但是我要让用户输入颜色,所以它需要是一个变量,我希望有一些更干净的东西,而不仅仅是每个颜色的if语句

有什么建议吗?谢谢


共 (3) 个答案

  1. # 1 楼答案

    两个答案:

    1. paintComponent接收图形对象。请参阅此link获取简短教程。如果需要访问此方法中的其他对象,请将其设置为变量GraphicalBoard,并在构造期间将其传递给om

    1.5您需要访问董事会的董事会,因为这是您正在使用的。所以在类Board中添加一个getBoard(int i, int j)。类似于以下内容(我还添加了一个getSize()方法):

    public int getBoard(int i, int j) {
      return board[i][j] ;
    } 
    
    public int getSize() {
       return size;
    } 
    
    1. 您的颜色colorOfSquare已定义为颜色。出现错误的原因是Color类没有这样的常量。你应该直接传递颜色

    试试这个:

      public class GraphicalBoard extends JComponent { 
    
         private int xSize = 50; 
         private int ySize = 50; 
         private Board board;
         private int size;
    
          public GraphicalBoard() {
           } 
    
          public void setBoard(Board board){
             this.board = board;
         } 
    
          public void paintComponent(Graphics g) { 
            super.paintComponent(); 
    
            if(board == null) {
              throw new RuntimeException("Board not set") ;
           } 
    
             String colors[] = {"BLUE","GREEN","YELLOW","RED","BLACK","ORANGE","PINK"}; 
             Graphics2D g2 = (Graphics2D) g; 
             int xCoord = 0; 
             int yCoord = 0; 
             int colorNum = 0; 
             int size = board.getSize() ;
            String colorOfSquare = ""; 
    
            for (int count = 0; count < size; count++) { 
    
                for (int counter = 0; counter < size; counter++) { 
                   colorNum = board.getBoard(count, counter) ; 
                   colorOfSquare = colors[colorNum]; 
                   g2.setColor(colorOfSquare); 
                   Rectangle square = new Rectangle(xCoord,yCoord,xSize,ySize); 
                   xCoord += 50; 
                 } 
               yCoord += 50;
             } 
    }
    
  2. # 2 楼答案

    1. 您的Board类包含一个成员变量int[][] board,但其作用域是私有的。当您调用以下命令时:

      colorNum=电路板[计数][计数器]

    这是错误的,因为这里的board变量是Board类的对象。它本身不是两天数组,但它将int[][] board封装在其中。因此,您需要在Board中提供一个getter方法来公开其board成员变量,如下所示:

    public int[][] getBoard() {
      return board;
    } 
    

    然后在paintComponent方法中,您可以通过以下方式访问它:board.getBoard()[count][counter]

    1. colorOfSquare变量中似乎已经有用户输入的颜色。但是Graphics2DsetColor方法只接受java类型的变量。awt。颜色因为有颜色的字符串表示,所以可以得到相应的java。awt。使用上述反射的颜色值here。以下几点应该对你有用:

      Color color;
      try {
          Field field = Color.class.getField(colorOfSquare);
          color = (Color) field.get(null);
      } catch (Exception e) {
          color = null; // Not defined
      }
      
  3. # 3 楼答案

    一般来说

    1. 您的视图(这里是图形JPanel)应该包含通过has-a或“合成”结构对模型对象的引用
    2. 应该通过事件侦听器(如PropertyChangeListener)通知视图模型中的更改
    3. 视图然后提取关键信息,并使用这些信息来帮助决定要绘制什么。因此,如果它有一个对当前Board对象的引用,它可以从paintComponent方法中调用getter方法

    代码中的其他问题:

    • 确保在覆盖中调用super的paintComponent,否则将无法清除“脏”像素
    • 不要在基于系统的扫描仪上混用线性代码。使用GUI代码。要么一个一个

    例如,在下面的代码中,我使用了一个模型类,这个类包含int[][]board变量,这里称为BoardModel,我给它一个SwingPropertyChangeSupport对象

    class BoardModel {
        // .....
        private SwingPropertyChangeSupport support = new SwingPropertyChangeSupport(this);
    

    此对象将接受侦听器,并允许我通知侦听器模型的更改

    public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) {
        support.addPropertyChangeListener(propertyName, listener);
    }
    

    然后,当模型更改时,我通过调用支持对象的firePropertyChange(...)方法通知所有侦听器:

    public void selectSquare(int x, int y) {
        int replacementValue = board[y][x];
        int targetValue = board[0][0];
        if (targetValue == replacementValue) {
            return;
        } else {
            recursiveMove(0, 0, targetValue, replacementValue);
            numOfMoves++;
            support.firePropertyChange(BOARD, null, board);  // ***** here
            setWin(checkForWin());
        }
    }    
    

    然后在控件中,我可以添加通知视图更改的侦听器:

           model.addPropertyChangeListener(BoardModel.BOARD, new PropertyChangeListener() {
    
                @Override
                public void propertyChange(PropertyChangeEvent e) {
                    view.repaint();
                    String moveCount = "" + model.getNumOfMoves();
                    controlPanel.setMoveCountFieldText(moveCount);
                }
            });
            model.addPropertyChangeListener(BoardModel.WIN, new PropertyChangeListener() {
    
                @Override
                public void propertyChange(PropertyChangeEvent evt) {
                    if ((boolean) evt.getNewValue()) {
                        String message = "Move count: " + model.getNumOfMoves();
                        String title = "Game Over";
                        int messageType = JOptionPane.PLAIN_MESSAGE;
                        JOptionPane.showMessageDialog(view, message, title, messageType);
                    }
                }
            });
    

    一个可行的例子可以如下所示:

    import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.Point;
    import java.awt.event.*;
    import java.beans.PropertyChangeEvent;
    import java.beans.PropertyChangeListener;
    import java.util.Random;
    
    import javax.swing.AbstractAction;
    import javax.swing.Action;
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JOptionPane;
    import javax.swing.JPanel;
    import javax.swing.JTextField;
    import javax.swing.SwingUtilities;
    import javax.swing.event.SwingPropertyChangeSupport;
    
    public class BoardFun {
        private static final int NUM_COLORS = 6;
        private static final int SIZE = 20;
    
        @SuppressWarnings("serial")
        public static void main(String[] args) {
            SwingUtilities.invokeLater(() -> {
                int size = SIZE;
                int numColors = NUM_COLORS;
                final BoardModel model = new BoardModel(size , numColors );
                final BoardPanel view = new BoardPanel();
                final ControlPanel controlPanel = new ControlPanel();
    
                view.setModel(model);
                view.addMouseListener(new MouseAdapter() {
                    @Override
                    public void mousePressed(MouseEvent mEvt) {
                        Point p = mEvt.getPoint();
                        int row = view.getRow(p);
                        int col = view.getColumn(p);
                        model.selectSquare(col, row);
                    }
                });
                model.addPropertyChangeListener(BoardModel.BOARD, new PropertyChangeListener() {
    
                    @Override
                    public void propertyChange(PropertyChangeEvent e) {
                        view.repaint();
                        String moveCount = "" + model.getNumOfMoves();
                        controlPanel.setMoveCountFieldText(moveCount);
                    }
                });
                model.addPropertyChangeListener(BoardModel.WIN, new PropertyChangeListener() {
    
                    @Override
                    public void propertyChange(PropertyChangeEvent evt) {
                        if ((boolean) evt.getNewValue()) {
                            String message = "Move count: " + model.getNumOfMoves();
                            String title = "Game Over";
                            int messageType = JOptionPane.PLAIN_MESSAGE;
                            JOptionPane.showMessageDialog(view, message, title, messageType);
                        }
                    }
                });
                controlPanel.setResetAction(new AbstractAction("Reset") {
    
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        model.reset();
                    }
                });
    
                JFrame frame = new JFrame("Game");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(view);
                frame.add(controlPanel, BorderLayout.PAGE_START);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            });
        }
    }
    

    @SuppressWarnings("serial")
    class ControlPanel extends JPanel {
        private JTextField moveCountField = new JTextField("0", 10);
        private JButton resetButton = new JButton();
    
        public ControlPanel() {
            add(new JLabel("Move Count:"));
            add(moveCountField);
            add(resetButton);
        }
    
        public void setResetAction(Action action) {
            resetButton.setAction(action);
        }
    
        public void setMoveCountFieldText(String text) {
            moveCountField.setText(text);
        }
    }
    

    @SuppressWarnings("serial")
    class BoardPanel extends JPanel {
        private static final int PREF_W = 640;
        private static final int PREF_H = PREF_W;
        private BoardModel model;
        private Color[] colors;
    
        @Override
        public Dimension getPreferredSize() {
            if (isPreferredSizeSet()) {
                return super.getPreferredSize();
            } else {
                return new Dimension(PREF_W, PREF_H);
            }
        }
    
        public void setModel(BoardModel model) {
            this.model = model;
            colors = new Color[model.getNumColors()];
    
            // create colors.length Colors, all of different hue
            for (int i = 0; i < colors.length; i++) {
                float hue = (float) i / colors.length;
                colors[i] = Color.getHSBColor(hue, 1f, 1f);
            }
        }
    
        // translate point to logical square position
        int getRow(Point p) {
            return (p.y * model.getBoard().length) / getHeight();
        }
    
        int getColumn(Point p) {
            return (p.x * model.getBoard()[0].length) / getWidth();
        }
    
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);  // always call the super's method
            if (model == null) {
                return;
            }
            int board[][] = model.getBoard();
            int height = getHeight() / board.length;
            int width = getWidth() / board[0].length;
            for (int i = 0; i < board.length; i++) {
                for (int j = 0; j < board[i].length; j++) {
                    Color color = colors[board[i][j]];
                    g.setColor(color);
                    int x = (j * getWidth()) / board[0].length;
                    int y = (i * getHeight()) / board.length;
                    g.fillRect(x, y, width, height);
                }
            }
        }
    }
    

    class BoardModel {
        public static final String BOARD = "board";
        public static final String WIN = "win";
        private int[][] board;
        private int numColors;
        private Random random = new Random();
        private SwingPropertyChangeSupport support = new SwingPropertyChangeSupport(this);
        private int numOfMoves = 0;
        private boolean win = false;
    
        public BoardModel(int size, int numColors) {
            board = new int[size][size];
            this.numColors = numColors;
            reset();
        }
    
        public void reset() {
            for (int i = 0; i < board.length; i++) {
                for (int j = 0; j < board[i].length; j++) {
                    board[i][j] = random.nextInt(numColors);
                }
            }
            numOfMoves = 0;
            support.firePropertyChange(BOARD, null, board);
            setWin(false);
        }
    
        public int[][] getBoard() {
            return board;
        }
    
        public int getNumOfMoves() {
            return numOfMoves;
        }
    
        public int getNumColors() {
            return numColors;
        }
    
        public void setWin(boolean win) {
            boolean oldValue = this.win;
            boolean newValue = win;
            this.win = win;
            support.firePropertyChange(WIN, oldValue, newValue);
        }
    
        public boolean isWin() {
            return win;
        }
    
        public void selectSquare(int x, int y) {
            int replacementValue = board[y][x];
            int targetValue = board[0][0];
            if (targetValue == replacementValue) {
                return;
            } else {
                recursiveMove(0, 0, targetValue, replacementValue);
                numOfMoves++;
                support.firePropertyChange(BOARD, null, board);
                setWin(checkForWin());
            }
        }
    
    
    
        public boolean checkForWin() {
            int value = board[0][0];
            for (int[] row : board) {
                for (int cell : row) {
                    if (cell != value) {
                        return false;
                    }
                }
            }
            return true;
        }
    
        private void recursiveMove(int i, int j, int targetValue, int replacementValue) {
            int currentValue = board[i][j];
            if (currentValue != targetValue || currentValue == replacementValue) {
                return;
            }
            board[i][j] = replacementValue;
            int rowMin = Math.max(0, i - 1);
            int rowMax = Math.min(board.length - 1, i + 1);
            int colMin = Math.max(0, j - 1);
            int colMax = Math.min(board[i].length - 1, j + 1);
            for (int i2 = rowMin; i2 <= rowMax; i2++) {
                if (i2 != i) {
                    recursiveMove(i2, j, targetValue, replacementValue);
                }
            }
            for (int j2 = colMin; j2 <= colMax; j2++) {
                if (j2 != j) {
                    recursiveMove(i, j2, targetValue, replacementValue);
                }
            }
        }
    
        public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) {
            support.addPropertyChangeListener(propertyName, listener);
        }   
    }