import java.awt.Graphics; import java.awt.Image; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.Random; import javax.swing.ImageIcon; import javax.swing.JLabel; import javax.swing.JPanel; public class Board extends JPanel { private final int NUM_IMAGES = 13; private final int CELL_SIZE = 15; private final int COVER_FOR_CELL = 10; private final int MARK_FOR_CELL = 10; private final int EMPTY_CELL = 0; private final int MINE_CELL = 9; private final int COVERED_MINE_CELL = MINE_CELL + COVER_FOR_CELL; private final int MARKED_MINE_CELL = COVERED_MINE_CELL + MARK_FOR_CELL; private final int DRAW_MINE = 9; private final int DRAW_COVER = 10; private final int DRAW_MARK = 11; private final int DRAW_WRONG_MARK = 12; private final int N_MINES = 40; private final int N_ROWS = 16; private final int N_COLS = 16; private int[] field; private boolean inGame; private int mines_left; private Image[] img; private int all_cells; private JLabel statusbar; public Board(JLabel statusbar) { this.statusbar = statusbar; img = new Image[NUM_IMAGES]; for (int i = 0; i < NUM_IMAGES; i++) { img[i] = (new ImageIcon(i + ".png")).getImage(); } setDoubleBuffered(true); addMouseListener(new MinesAdapter()); newGame(); } private void newGame() { Random random; int current_col; int i = 0; int position = 0; int cell = 0; random = new Random(); inGame = true; mines_left = N_MINES; all_cells = N_ROWS * N_COLS; field = new int[all_cells]; for (i = 0; i < all_cells; i++) field[i] = COVER_FOR_CELL; statusbar.setText(Integer.toString(mines_left)); i = 0; while (i < N_MINES) { position = (int) (all_cells * random.nextDouble()); if ((position < all_cells) && (field[position] != COVERED_MINE_CELL)) { current_col = position % N_COLS; field[position] = COVERED_MINE_CELL; i++; if (current_col > 0) { cell = position - 1 - N_COLS; if (cell >= 0) if (field[cell] != COVERED_MINE_CELL) field[cell] += 1; cell = position - 1; if (cell >= 0) if (field[cell] != COVERED_MINE_CELL) field[cell] += 1; cell = position + N_COLS - 1; if (cell < all_cells) if (field[cell] != COVERED_MINE_CELL) field[cell] += 1; } cell = position - N_COLS; if (cell >= 0) if (field[cell] != COVERED_MINE_CELL) field[cell] += 1; cell = position + N_COLS; if (cell < all_cells) if (field[cell] != COVERED_MINE_CELL) field[cell] += 1; if (current_col < (N_COLS - 1)) { cell = position - N_COLS + 1; if (cell >= 0) if (field[cell] != COVERED_MINE_CELL) field[cell] += 1; cell = position + N_COLS + 1; if (cell < all_cells) if (field[cell] != COVERED_MINE_CELL) field[cell] += 1; cell = position + 1; if (cell < all_cells) if (field[cell] != COVERED_MINE_CELL) field[cell] += 1; } } } } public void find_empty_cells(int j) { int current_col = j % N_COLS; int cell; if (current_col > 0) { cell = j - N_COLS - 1; if (cell >= 0) if (field[cell] > MINE_CELL) { field[cell] -= COVER_FOR_CELL; if (field[cell] == EMPTY_CELL) find_empty_cells(cell); } cell = j - 1; if (cell >= 0) if (field[cell] > MINE_CELL) { field[cell] -= COVER_FOR_CELL; if (field[cell] == EMPTY_CELL) find_empty_cells(cell); } cell = j + N_COLS - 1; if (cell < all_cells) if (field[cell] > MINE_CELL) { field[cell] -= COVER_FOR_CELL; if (field[cell] == EMPTY_CELL) find_empty_cells(cell); } } cell = j - N_COLS; if (cell >= 0) if (field[cell] > MINE_CELL) { field[cell] -= COVER_FOR_CELL; if (field[cell] == EMPTY_CELL) find_empty_cells(cell); } cell = j + N_COLS; if (cell < all_cells) if (field[cell] > MINE_CELL) { field[cell] -= COVER_FOR_CELL; if (field[cell] == EMPTY_CELL) find_empty_cells(cell); } if (current_col < (N_COLS - 1)) { cell = j - N_COLS + 1; if (cell >= 0) if (field[cell] > MINE_CELL) { field[cell] -= COVER_FOR_CELL; if (field[cell] == EMPTY_CELL) find_empty_cells(cell); } cell = j + N_COLS + 1; if (cell < all_cells) if (field[cell] > MINE_CELL) { field[cell] -= COVER_FOR_CELL; if (field[cell] == EMPTY_CELL) find_empty_cells(cell); } cell = j + 1; if (cell < all_cells) if (field[cell] > MINE_CELL) { field[cell] -= COVER_FOR_CELL; if (field[cell] == EMPTY_CELL) find_empty_cells(cell); } } } @Override public void paintComponent(Graphics g) { int cell = 0; int uncover = 0; for (int i = 0; i < N_ROWS; i++) { for (int j = 0; j < N_COLS; j++) { cell = field[(i * N_COLS) + j]; if (inGame && cell == MINE_CELL) inGame = false; if (!inGame) { if (cell == COVERED_MINE_CELL) { cell = DRAW_MINE; } else if (cell == MARKED_MINE_CELL) { cell = DRAW_MARK; } else if (cell > COVERED_MINE_CELL) { cell = DRAW_WRONG_MARK; } else if (cell > MINE_CELL) { cell = DRAW_COVER; } } else { if (cell > COVERED_MINE_CELL) cell = DRAW_MARK; else if (cell > MINE_CELL) { cell = DRAW_COVER; uncover++; } } g.drawImage(img[cell], (j * CELL_SIZE), (i * CELL_SIZE), this); } } if (uncover == 0 && inGame) { inGame = false; statusbar.setText("Game won"); } else if (!inGame) statusbar.setText("Game lost"); } class MinesAdapter extends MouseAdapter { @Override public void mousePressed(MouseEvent e) { int x = e.getX(); int y = e.getY(); int cCol = x / CELL_SIZE; int cRow = y / CELL_SIZE; boolean rep = false; if (!inGame) { newGame(); repaint(); } if ((x < N_COLS * CELL_SIZE) && (y < N_ROWS * CELL_SIZE)) { if (e.getButton() == MouseEvent.BUTTON3) { if (field[(cRow * N_COLS) + cCol] > MINE_CELL) { rep = true; if (field[(cRow * N_COLS) + cCol] <= COVERED_MINE_CELL) { if (mines_left > 0) { field[(cRow * N_COLS) + cCol] += MARK_FOR_CELL; mines_left--; statusbar.setText(Integer.toString(mines_left)); } else statusbar.setText("No marks left"); } else { field[(cRow * N_COLS) + cCol] -= MARK_FOR_CELL; mines_left++; statusbar.setText(Integer.toString(mines_left)); } } } else { if (field[(cRow * N_COLS) + cCol] > COVERED_MINE_CELL) { return; } if ((field[(cRow * N_COLS) + cCol] > MINE_CELL) && (field[(cRow * N_COLS) + cCol] < MARKED_MINE_CELL)) { field[(cRow * N_COLS) + cCol] -= COVER_FOR_CELL; rep = true; if (field[(cRow * N_COLS) + cCol] == MINE_CELL) inGame = false; if (field[(cRow * N_COLS) + cCol] == EMPTY_CELL) find_empty_cells((cRow * N_COLS) + cCol); } } if (rep) repaint(); } } } }