问题遇到的现象和发生背景
在任意操作后 整个窗口就卡住了
问题相关代码,请勿粘贴截图
package minesweeper;
import java.awt.*; // Use AWT's Layout Manager
import java.awt.event.*; // Use AWT's Event handlers
import javax.swing.*; // Use Swing's Containers and Components
/**
* The Mine Sweeper Game.
* Left-click to reveal a cell.
* Right-click to plant/remove a flag for marking a suspected mine.
* You win if all the cells not containing mines are revealed.
* You lose if you reveal a cell containing a mine.
*/
@SuppressWarnings("serial")
public class MineSweeper2 extends JFrame {
// private variables
GameBoard board = new GameBoard();
JButton btnNewGame = new JButton("New Game");
// Constructor to set up all the UI and game components
public MineSweeper2() {
Container cp = this.getContentPane(); // JFrame's content-pane
cp.setLayout(new BorderLayout()); // in 10x10 GridLayout
cp.add(board, BorderLayout.CENTER);
// Add a button to the south to re-start the game
// ......
JButton restartBtn= new JButton("Restart");
add(restartBtn,BorderLayout.SOUTH);
restartBtn.addActionListener(evt-> board.init());
board.init();
pack(); // Pack the UI components, instead of setSize()
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // handle window-close button
setTitle("Mineswepper");
setVisible(true); // show it
}
// The entry main() method
public static void main(String[] args) {
// Run GUI codes in Event-Dispatching thread for thread-safety
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new MineSweeperMain(); // Let the constructor do the job
}
});
}
}
package minesweeper;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
@SuppressWarnings("serial")//加
public class GameBoard2 extends JPanel {
// Name-constants for the game properties
public static final int ROWS = 10; // number of cells
public static final int COLS = 10;
// Name-constants for UI sizes
public static final int CELL_SIZE = 60; // Cell width and height, in pixels
public static final int CANVAS_WIDTH = CELL_SIZE * COLS; // Game board width/height
public static final int CANVAS_HEIGHT = CELL_SIZE * ROWS;
public boolean isRevealed;
public boolean isMined;
public boolean isFlagged;
Cell cells[][] = new Cell[ROWS][COLS];
MineMap mines = new MineMap();
int numMines = 10;
// Constructor
public GameBoard2() {
super.setLayout(new GridLayout(ROWS, COLS, 2, 2)); // JPanel
// Allocate the 2D array of Cell, and added into content-pane.
for (int row = 0; row < ROWS; ++row) {
for (int col = 0; col < COLS; ++col) {
cells[row][col] = new Cell(row, col);
super.add(cells[row][col]);
}
}
// [TODO 3] Allocate a common listener as the MouseEvent listener for all the
// Cells (JButtons)
CellMouseListener listener=new CellMouseListener();
// [TODO 4] Every cell adds this common listener
for (int row = 0; row < ROWS; ++row) {
for (int col = 0; col < COLS; ++col) {
cells[row][col].addMouseListener(listener);
}
}
// Initialize for a new game
init();
// Set the size of the content-pane and pack all the components
// under this container.
super.setPreferredSize(new Dimension(CANVAS_WIDTH, CANVAS_HEIGHT));
}
// Initialize and re-initialize a new game
public void init() {
// Get a new mine map
mines.newMineMap(numMines);
// Reset cells, mines, and flags
for (int row = 0; row < ROWS; row++) {
for (int col = 0; col < COLS; col++) {
// Initialize each cell with/without mine
cells[row][col].init(mines.isMined[row][col]);
}
}
}
// Return the number of mines (0 - 8) in the 8 surrounding cells of the given cell.
private int getSurroundingMines(Cell cell) {
int numMines = 0;
for (int row = cell.row - 1; row <= cell.row + 1; row++) {
for (int col = cell.col - 1; col <= cell.col + 1; col++) {
// Need to ensure valid row and column numbers too
if (row >= 0 && row < ROWS && col >= 0 && col < COLS && mines.isMined[row][col]) {
numMines++;
}
}
}
return numMines;
}
// This cell has 0 surrounding mine. Reveal the 8 surrounding cells recursively
public void revealSurrounding(Cell cell) {
if (getSurroundingMines(cell)==0) {
for (int row=cell.row-1; row<=cell.row+1; row++) {
for (int col=cell.col-1;col<=cell.col+1;col++) {
isRevealed=true;
int surroundingMine=getSurroundingMines(cell);
cell.setText(""+surroundingMine);
cell.paint();
}
}
}else {
for (int row=cell.row-1; row<=cell.row+1; row++) {
for (int col=cell.col-1;col<=cell.col+1;col++) {
if (mines.isMined[row][col]==false) {
isRevealed=true;
int surroundingMine=getSurroundingMines(cell);
cell.setText(""+surroundingMine);
cell.paint();
}
}
}
}
}
// Return true if the player has won (all cells have been revealed or were mined)
public boolean hasWon() {
int countRevealed=0;
for (int row = 0; row < ROWS ;row++) {
for (int col = 0; col < COLS ; col++) {
if (isRevealed==true&&isMined==false) {
countRevealed++;
}
}
}
if (countRevealed==(ROWS*COLS-numMines)) {
return true;
}else {return false;}
}
// [TODO 2] Define a Listener Inner Class
private class CellMouseListener extends MouseAdapter{
@Override
public void mouseClicked(MouseEvent evt){
Cell sourceCell=(Cell)evt.getSource();
//For debugging
System.out.println("You clicked on (" + sourceCell.row + "," + sourceCell.col + ")");
//Left-click to reveal a cell;Right-click to plant/remove the flag
if (evt.getButton()== MouseEvent.BUTTON1) {
if (mines.isMined[sourceCell.row][sourceCell.col]==true) {
init();
}else if(mines.isMined[sourceCell.row][sourceCell.col]==false){
isRevealed=true;
revealSurrounding(sourceCell);
sourceCell.paint();
}
}else if(evt.getButton() == MouseEvent.BUTTON3) {
if (sourceCell.row >= 0 && sourceCell.row < ROWS && sourceCell.col >= 0 && sourceCell.col < COLS) {
if(isFlagged==false) {
isFlagged=true;
sourceCell.paint();
}else{
isFlagged=false;
sourceCell.paint();
}
}
}
if(hasWon()==true) {
init();
}
}
}
}
package minesweeper;
import java.awt.Color;
import java.awt.Font;
import javax.swing.JButton;
/**
* Customize (subclass) the JButton to include
* row/column numbers and status of each cell.
*/
@SuppressWarnings("serial")
public class Cell2 extends JButton {
// Name-constants for JButton's colors and fonts
public static final Color BG_NOT_REVEALED = Color.GREEN;
public static final Color FG_NOT_REVEALED = Color.RED; // flag, mines
public static final Color BG_REVEALED = Color.DARK_GRAY;
public static final Color FG_REVEALED = Color.YELLOW; // number of mines
public static final Font FONT_NUMBERS = new Font("Monospaced", Font.BOLD, 20);
public static final int ROWS = 10; // number of cells
public static final int COLS = 10;
// All variables have package access
public int row, col; // The row and column number of the cell
public boolean isRevealed;
public boolean isMined;
public boolean isFlagged;
// Constructor
public Cell2(int row, int col) {
super(); // JTextField
this.row = row;
this.col = col;
// Set JButton's default display properties
super.setFont(FONT_NUMBERS);
}
public void init(boolean isMined) {
isRevealed = false;
isFlagged = false;
this.isMined = isMined;
super.setEnabled(true); // enable button
super.setForeground(FG_NOT_REVEALED);
super.setBackground(BG_NOT_REVEALED);
super.setOpaque(true);
super.setBorderPainted(false);
super.setText(""); // display blank
}
// Paint itself based on its status
public void paint() {
Cell cells[][] = new Cell[ROWS][COLS];
for (int row = 0;row < ROWS; ++row) {
for (int col = 0; col < COLS; ++col) {
if(isFlagged==true) {
cells[row][col].setBackground(FG_NOT_REVEALED);
}else if(isRevealed==true) {
cells[row][col].setBackground(BG_REVEALED);
}else if(isMined==true&&isRevealed==true) {
cells[row][col].setBackground(FG_REVEALED);
}
}
}
}
}
运行结果及报错内容
运行结果是可以打开窗口 基本框架也都有 但是运行方面应该是算法出了runtime error
我的解答思路和尝试过的方法
试着改了几次loop都不太对
我想要达到的结果
程序正常运行