0

我正在开发控制器以制作数独游戏。当您运行我的 SudokuMain.java 文件,然后单击页面顶部的“文件”,然后选择“新游戏”时,出现异常:

线程“AWT-EventQueue-0”中的异常 java.lang.NullPointerException

我有一个用于“新游戏”的 ActionListener 来创建一个名为“创建板”的 JDialog 对象,并提示用户输入“每个区域的行”和“每个区域的列”并按“创建板”,或者按“取消”并取消它。

我不确定我做错了什么,但我觉得问题出在内部类 MenuAtTop 上。任何帮助表示赞赏!

// Allow short name access to following classes
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;

public class SudokuMain extends JComponent {

  public static void main(String[] args) {
    new SudokuMain();
  }

  private SudokuBase board;
  private SudokuView view;

  private JFrame win;
  private JPanel center;
  private JPanel west;
  private JPanel east;
  private JPanel cells;

  private final Dialog1 setWin1;

  public SudokuMain() {

   // start game
   view = new SudokuView(makeBoard());
   board = makeBoard();

   win = new JFrame("Sudoku");
   center = new JPanel();
   west = new JPanel();
   east = new JPanel();

   // "player" cells for current Sudoku board
   cells = new SetSymbols(view);
   // the 1st set-up window
   setWin1 = new Dialog1(this, "New Game", true);

   // create menu bar
   MenuAtTop menuBar = new MenuAtTop(this);
   win.setJMenuBar(menuBar);

   win.setLayout(new BorderLayout());
   view.setSelected(1, 1);
   west.setLayout(new BorderLayout());
   east.setLayout(new BorderLayout());
   center.setLayout(new FlowLayout());

   west.add(cells);
   east.add(view, BorderLayout.CENTER);
   center.add(west);
    center.add(east);

   win.add(center);

   win.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
   win.pack();
   win.setVisible(true);

 }

class SudokuControlButton extends JPanel {

  private int row;
  private int col;

  // row of selected cell
  private int selRow;
  // column of selected cell
  private int selCol;

  // the value that corresponds with the desired symbol
  private int value;

  /**
   * Constructs SudokuControlButton object; the graphic "button"
   * to control the board.
   */
  public SudokuControlButton(final SudokuView view) {

    setPreferredSize(new Dimension(40, 40));
    setBackground(Color.LIGHT_GRAY);

    //value = 0;

    addMouseListener(new MouseListener() {

      public void mouseClicked(MouseEvent e) {
        selRow = view.getSelectedRow();
        selCol = view.getSelectedColumn();

        if(!board.isGiven(selRow, selCol)) {
          board.setValue(selRow, selCol, value);

        view.repaint();
        } else {  // have system beep sound
          getToolkit().beep();
        }

        repaint();
      }

      public void mouseEntered(MouseEvent e){
        // set to "highlighted" color
        setBackground(Color.WHITE);

        repaint();
      }

      public void mouseExited(MouseEvent e){
        // set to default color
        setBackground(Color.LIGHT_GRAY);

        repaint();
      }

      public void mousePressed(MouseEvent e){
        // set to "active" color
        setBackground(Color.YELLOW);

        repaint();
      }

      public void mouseReleased(MouseEvent e){
      }

    });
  }

  public void paintComponent(Graphics g) {
    super.paintComponent(g);

    switch(value) {
      case 0:
      drawSymbol(g, 0);
      break;
    case 1:
      drawSymbol(g, 1);
      break;
    case 2:
      drawSymbol(g, 2);
      break;
    case 3:
      drawSymbol(g, 3);
      break;
    case 4:
      drawSymbol(g, 4);
      break;
    case 5:
      drawSymbol(g, 5);
      break;
    case 6:
      drawSymbol(g, 6);
      break;
    case 7:
      drawSymbol(g, 7);
      break;
    case 8:
      drawSymbol(g, 8);
      break;
    case 9:
      drawSymbol(g, 9);
      break;
    case 10:
      drawSymbol(g, 10);
      break;
    case 11:
      drawSymbol(g, 11);
      break;
    case 12:
      drawSymbol(g, 12);
      break;
  }

}

/**
 * This method draws the symbol that corresponds with 
 * the specified value (0-12).
 * 
 * @param g The drawing mechanism.
 * @param value The specified value.
 */
public void drawSymbol(Graphics g, int value) {

  if(value < 0 || value > 12) {
    String msg = "Value cannot be less than 1 or greater than 12.";
    throw new IllegalArgumentException(msg);
  }

  // enable drawing with "thick" lines
  Graphics2D g2 = (Graphics2D) g;
  g2.setStroke(new BasicStroke(3));

  switch(value) {
    case 0:
      // draw borders
      g.drawRect(0, 0, 50, 50);
      break;
    case 1:
      // draw borders
      g.drawRect(0, 0, 50, 50);
      // draw symbol
      g2.drawLine(5, 5, 5, 45);
      break;
    case 2:
      // draw borders
      g.drawRect(0, 0, 50, 50);
      // draw symbol
      g2.drawLine(5, 5, 5, 45);
      g2.drawLine(10, 5, 10, 45);
      break;
    case 3:
      // draw borders
      g.drawRect(0, 0, 50, 50);
      // draw symbol
      g2.drawLine(5, 5, 5, 45);
      g2.drawLine(10, 5, 10, 45);
      g2.drawLine(15, 5, 15, 45);
      break;
    case 4:
      // draw borders
      g.drawRect(0, 0, 50, 50);
      // draw symbol
      g2.drawLine(5, 5, 5, 45);
      g2.drawLine(10, 5, 10, 45);
      g2.drawLine(15, 5, 15, 45);
      g2.drawLine(20, 5, 20, 45);
      break;
    case 5:
      // draw borders
      g.drawRect(0, 0, 50, 50);
      // draw symbol
      g2.drawLine(5, 5, 5, 45);
      g2.drawLine(10, 5, 10, 45);
      g2.drawLine(15, 5, 15, 45);
      g2.drawLine(20, 5, 20, 45);
      g2.drawLine(25, 5, 25, 45);
      break;
    case 6:
      // draw borders
      g.drawRect(0, 0, 50, 50);
      // draw symbol
      g2.drawLine(5, 5, 5, 45);
      g2.drawLine(10, 5, 10, 45);
      g2.drawLine(15, 5, 15, 45);
      g2.drawLine(20, 5, 20, 45);
      g2.drawLine(25, 5, 25, 45);
      g2.drawLine(30, 5, 30, 45);
      break;
    case 7:
      // draw borders
      g.drawRect(0, 0, 50, 50);
      // draw symbol
      g2.drawLine(5, 5, 5, 20);
      g2.drawLine(10, 5, 10, 20);
      g2.drawLine(15, 5, 15, 20);
      g2.drawLine(20, 5, 20, 20);
      g2.drawLine(25, 5, 25, 20);
      g2.drawLine(30, 5, 30, 20);
      g2.drawLine(5, 30, 5, 45);
      break;
    case 8:
      // draw borders
      g.drawRect(0, 0, 50, 50);
      // draw symbol
      g2.drawLine(5, 5, 5, 20);
      g2.drawLine(10, 5, 10, 20);
      g2.drawLine(15, 5, 15, 20);
      g2.drawLine(20, 5, 20, 20);
      g2.drawLine(25, 5, 25, 20);
      g2.drawLine(30, 5, 30, 20);
      g2.drawLine(5, 30, 5, 45);
      g2.drawLine(10, 30, 10, 45);
      break;
    case 9:
      // draw borders
      g.drawRect(0, 0, 50, 50);
      // draw symbol
      g2.drawLine(5, 5, 5, 20);
      g2.drawLine(10, 5, 10, 20);
      g2.drawLine(15, 5, 15, 20);
      g2.drawLine(20, 5, 20, 20);
      g2.drawLine(25, 5, 25, 20);
      g2.drawLine(30, 5, 30, 20);
      g2.drawLine(5, 30, 5, 45);
      g2.drawLine(10, 30, 10, 45);
      g2.drawLine(15, 30, 15, 45);
      break;
    case 10:
      // draw borders
      g.drawRect(0, 0, 50, 50);
      // draw symbol
      g.drawLine(5, 5, 5, 20);
      g.drawLine(10, 5, 10, 20);
      g.drawLine(15, 5, 15, 20);
      g.drawLine(20, 5, 20, 20);
      g.drawLine(25, 5, 25, 20);
      g.drawLine(30, 5, 30, 20);
      g.drawLine(5, 30, 5, 45);
      g.drawLine(10, 30, 10, 45);
      g.drawLine(15, 30, 15, 45);
      g.drawLine(20, 30, 20, 45);
      break;
    case 11:
      // draw borders
      g.drawRect(0, 0, 50, 50);
      // draw symbol
      g.drawLine(5, 5, 5, 20);
      g.drawLine(10, 5, 10, 20);
      g.drawLine(15, 5, 15, 20);
      g.drawLine(20, 5, 20, 20);
      g.drawLine(25, 5, 25, 20);
      g.drawLine(30, 5, 30, 20);
      g.drawLine(5, 30, 5, 45);
      g.drawLine(10, 30, 10, 45);
      g.drawLine(15, 30, 15, 45);
      g.drawLine(20, 30, 20, 45);
      g.drawLine(25, 30, 25, 45);
      break;
    case 12:
      // draw borders
      g.drawRect(0, 0, 50, 50);
      // draw symbol
      g.drawLine(5, 5, 5, 20);
      g.drawLine(10, 5, 10, 20);
      g.drawLine(15, 5, 15, 20);
      g.drawLine(20, 5, 20, 20);
      g.drawLine(25, 5, 25, 20);
      g.drawLine(30, 5, 30, 20);
      g.drawLine(5, 30, 5, 45);
      g.drawLine(10, 30, 10, 45);
      g.drawLine(15, 30, 15, 45);
      g.drawLine(20, 30, 20, 45);
      g.drawLine(25, 30, 25, 45);
      g.drawLine(30, 30, 30, 45);
      break;
    }

  }

 }

class MenuAtTop extends JMenuBar implements ActionListener{

  private SudokuMain main;

  private JMenu fileMenu;
  private JMenuItem newGame;

  private JDialog createNewWin; 

  public MenuAtTop(final SudokuMain m) {

    fileMenu = new JMenu("File");
    add(fileMenu);

    newGame = new JMenuItem("New Game");
    newGame.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N,
                                                  ActionEvent.CTRL_MASK));
    fileMenu.add(newGame);
    newGame.addActionListener(this);

  }

  public void actionPerformed(ActionEvent e) {
    setEnabled(false);
    createNewWin = new Dialog1(main, "Create New Board", true);
  }

}

class Dialog1 extends JDialog {

  private JTextField rows;
  private JTextField cols;
  private JButton createBoard; 
  private JButton cancel;
  private JLabel rowLabel;
  private JLabel colLabel;
  private JLabel errorMes;


  private JPanel center;
  private JPanel north;
  private JDialog setUpWin2;

  /**
   * Constructs Dialog1 object.
   * 
   * @param win The window containing the dialog box.
   * @param header The title of dialog box.
   * @param modal Whether dialog box is modal or not.
   */
  public Dialog1(final SudokuMain win, String header, boolean modal) {
    // call superclass constructor
    super();

    // instantiate and bind to references
    rows = new JTextField(2);
    cols = new JTextField(2);
    createBoard = new JButton("Create Board");
    cancel = new JButton("Cancel");
    rowLabel = new JLabel("Rows per region: ");
    colLabel = new JLabel("Columns per region: ");
    errorMes = new JLabel();

    north = new JPanel(new FlowLayout());
    center = new JPanel(new FlowLayout());

    // set characteristics
    setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
    setTitle(header);
    setModal(modal);
    setLayout(new BorderLayout());

    // set characteristics of error message
    errorMes.setForeground(Color.RED);
    errorMes.setFont(new Font("Arial", Font.ITALIC, 12));
    errorMes.setVisible(false);

    cancel.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        setVisible(false);
      }
    });

    createBoard.addActionListener(new ActionListener() {

      public void actionPerformed(ActionEvent e) {
        int newRows;
        int newCols;
        int newSize;

        try{
          newRows = Integer.parseInt(rows.getText());
          newCols = Integer.parseInt(cols.getText());
        } catch (NumberFormatException exc) {
          newRows = 0;
          newCols = 0;
        }

        newSize = newRows * newCols;
        // input validation
        if(newSize <= 0 && newSize > 12) {
          errorMes.setText("Rows times columns cannot be greater than 12!");
          errorMes.setVisible(true);
          pack();

        } else{ // valid input
          errorMes.setVisible(false);
          setVisible(false);
          setUpWin2 = new Dialog2(win, "New Sudoku", newRows, newCols, true);
        }
      }});


    // place error message in the center
    center.add(errorMes);

    // place labels for rows and columns at the top 
    north.add(rowLabel);
    north.add(rows);
    north.add(colLabel);
    north.add(cols);

    add(center, BorderLayout.CENTER);
    add(north, BorderLayout.NORTH);

    pack();

    if(!win.win.isVisible()) {
      dispose();
    }

  }
}

class Dialog2 extends JDialog {

  private SudokuView view;

  private JPanel panel;
  private JPanel northPanel;
  private JPanel cells;

  private JButton setGivens; 
  private JButton cancel;

  /**
   * Constructs Dialog2 object.
   * 
   * @param win The window containing the dialog box.
   * @param header The title of the dialog box.
   * @param rows the rows to the new SudokuBoard to be constructed in the dialog box
   * @param cols the columns to the new SudokuBoard to be constructed in the dialog box
   * @param modal boolean value for whether the box is modal or not
   */
  public Dialog2(final SudokuMain mainWin, String header, int rows, int cols,
                 boolean modal) {
    // call superclass constructor
    super();

    // instantiate and bind to references
    view = new SudokuView(new SudokuBoard(rows, cols));
    panel = new JPanel();
    northPanel = new JPanel();
    setGivens = new JButton("Set Givens");
    cancel = new JButton("Cancel");
    cells = new SetSymbols(view);

    // set up characteristics 
    setTitle(header);
    setModal(modal);
    setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
    setLayout(new FlowLayout());
    panel.setLayout(new BorderLayout());
    northPanel.setLayout(new FlowLayout());


    setGivens.addActionListener(new ActionListener() {

      public void actionPerformed(ActionEvent e) {
        // set "given" cells
        makeBoard().fixGivens();

        // have window refer to new board
        west.remove(mainWin.view);
        mainWin.east.remove(mainWin.cells);

        mainWin.view = view;
        mainWin.cells = cells;

        mainWin.west.add(mainWin.view);
        mainWin.east.add(mainWin.cells);

        setVisible(false);

      }});

    cancel.addActionListener(new ActionListener() {
     public void actionPerformed(ActionEvent e) {
        setVisible(false);
    }});

    // place buttons at the top
    northPanel.add(setGivens);
    northPanel.add(cancel);

    panel.add(view, BorderLayout.CENTER);
    panel.add(northPanel, BorderLayout.NORTH);

    add(panel);
    add(cells);

    setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
    pack();
    setVisible(true);

  }

}

class SetSymbols extends JPanel {

// temporary board to help create graphic "buttons"
private SudokuBoard tempBd;

/**
 * Constructs SetSymbols object.
 * @param view The SudokuView object for SetSymbols.
 */
public SetSymbols(final SudokuView view) {
  // instantiate and bind to reference
  tempBd = new SudokuBoard(1, board.getBoardSize() + 1);

  setLayout(new GridLayout((tempBd.getBoardSize())/2 + 1, 2));

  for(int colCell = 0; colCell < tempBd.getBoardSize(); colCell++) {

    // cannot be changed after set/instantiated
    final int value = colCell;
    final JPanel cell = new JPanel();
    final Color defaultColor = cell.getBackground();

    // set characteristics
    cell.setBorder(BorderFactory.createLineBorder(Color.BLACK));
    // set value for each graphic "button"
    tempBd.setValue(0, colCell, colCell);
    // add the appropriate symbol to each graphic "button"
    cell.add(view.new SudokuCell(0, colCell, tempBd));

    cell.addMouseListener(new MouseListener() {
      // whether inside graphic "button" or not
      boolean insideCell;

      public void mouseClicked(MouseEvent e) {
        int selRow = view.getSelectedRow();
        int selCol = view.getSelectedColumn();

        if(!board.isGiven(selRow, selCol)) {
          board.setValue(selRow, selCol, value);

          view.repaint();
        }
        else {  // have system beep sound
          cell.getToolkit().beep();
        }

      }

      public void mouseEntered(MouseEvent e) {
        insideCell = true;
        // set to "highlighted" color
        cell.setBackground(Color.WHITE);

        view.repaint();
      }

      public void mouseExited(MouseEvent e) {
        insideCell = false;
        // set to default color
        cell.setBackground(defaultColor);

        view.repaint();
      }

      public void mousePressed(MouseEvent e) {
        // set to "active" color
        cell.setBackground(Color.YELLOW);

        view.repaint();
      }

      public void mouseReleased(MouseEvent e) {
        if(insideCell) {
          cell.setBackground(Color.YELLOW);
        }
        else {  // outside of symbol's cell
          cell.setBackground(defaultColor);
        }

        view.repaint();
      }
    });

    // add graphic "button"
    add(cell);

  }

  // handle possible "empty" graphic "button"
  if(tempBd.getBoardSize() % 2 != 0) {
    JPanel empty = new JPanel();
    empty.setBackground(Color.LIGHT_GRAY);
    empty.setBorder(BorderFactory.createLineBorder(Color.BLACK));
    add(empty);
   }

   }

  }

  public static SudokuBase makeBoard() {
    SudokuBase board = new SudokuBoard(2, 3);
    board.setValue(0, 3, 6);
    board.setValue(0, 5, 1);
    board.setValue(1, 2, 4);
    board.setValue(1, 4, 5);
    board.setValue(1, 5, 3);
    board.setValue(2, 3, 3);
    board.setValue(3, 2, 6);
    board.setValue(4, 0, 2);
    board.setValue(4, 1, 3);
    board.setValue(4, 3, 1);
    board.setValue(5, 0, 6);
    board.setValue(5, 2, 1);
    board.fixGivens();
    return board;
  }

}
4

1 回答 1

2

您在给变量赋值main之前传递变量。也许您打算将其初始化为 MenuAtTop 构造函数中的参数,例如main = m;

于 2013-07-14T22:57:15.380 回答