Added board init and reset methods, added BoardConfig object

This commit is contained in:
Kai S. K. Engelbart 2019-04-01 14:57:29 +02:00
parent 0d7d498af7
commit 4e63dea497
3 changed files with 99 additions and 31 deletions

View File

@ -1,12 +1,14 @@
package dev.kske.minesweeper;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
@ -26,13 +28,14 @@ public class Board extends JPanel {
private static Map<String, Image> icons;
private int width, height;
private Rectangle screen;
private int boardWidth, boardHeight;
private GameState gameState;
private int mines, activeTiles, flaggedTiles;
private Tile[][] board;
private BoardConfig initialConfig;
static {
icons = new HashMap<>();
final String[] names = { "mine2", "mine4", "tile", "tile3", "flag" };
@ -41,31 +44,66 @@ public class Board extends JPanel {
}
}
public Board(int x, int y, int width, int height, int mines) {
public Board() {
// Not using a layout manager
super(null);
this.width = width;
this.height = height;
screen = new Rectangle(x, y, x + width * tileSize, y + height * tileSize);
addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent evt) {
Point tilePos = getTilePos(evt.getX(), evt.getY());
int n = tilePos.x, m = tilePos.y;
Tile tile = board[n][m];
if (tile.isTouched() || gameState != GameState.ACTIVE) return;
switch (evt.getButton()) {
case MouseEvent.BUTTON1:
// Touch tile
touchTile(n, m);
break;
case MouseEvent.BUTTON3:
// Flag tile
flagTile(n, m);
}
}
});
}
public void init(BoardConfig config) {
initialConfig = config;
boardWidth = config.width;
boardHeight = config.height;
setPreferredSize(new Dimension(config.width * tileSize, config.height * tileSize));
gameState = GameState.ACTIVE;
this.mines = mines;
activeTiles = width * height;
this.mines = config.mines;
activeTiles = boardWidth * boardHeight;
flaggedTiles = 0;
board = new Tile[width][height];
for (int i = 0; i < width; i++)
for (int j = 0; j < height; j++)
// Init board
board = new Tile[boardWidth][boardHeight];
for (int i = 0; i < boardWidth; i++)
for (int j = 0; j < boardHeight; j++)
board[i][j] = new Tile();
repaint();
}
public void reset() {
init(initialConfig);
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
for (int i = 0; i < width; i++)
for (int j = 0; j < height; j++) {
for (int i = 0; i < boardWidth; i++)
for (int j = 0; j < boardHeight; j++) {
Tile tile = board[i][j];
int x = screen.x + i * tileSize, y = screen.y + j * tileSize;
int x = i * tileSize, y = j * tileSize;
// Draw background with grid
g.setColor(Color.gray);
@ -77,11 +115,11 @@ public class Board extends JPanel {
switch (gameState) {
case LOST:
// Draw tile with normal mine
g.drawImage(icons.get("mine2"), x, y, this);
if (tile.isMine()) g.drawImage(icons.get("mine2"), x, y, this);
break;
case WON:
// Draw tile with diffused mine
g.drawImage(icons.get("mine4"), x, y, this);
if (tile.isMine()) g.drawImage(icons.get("mine4"), x, y, this);
break;
default:
if (tile.isTouched()) {
@ -109,8 +147,12 @@ public class Board extends JPanel {
}
}
private void repaintTile(int n, int m) {
repaint(n * tileSize, m * tileSize, (n + 1) * tileSize, (n + 1) * tileSize);
}
public Point getTilePos(int x, int y) {
return new Point((x - screen.x) / tileSize, (y - screen.y) / tileSize);
return new Point(x / tileSize, y / tileSize);
}
public void initMines() {
@ -118,8 +160,8 @@ public class Board extends JPanel {
Random random = new Random();
while (remaining > 0) {
// Randomly select a tile
int n = random.nextInt(width);
int m = random.nextInt(height);
int n = random.nextInt(boardWidth);
int m = random.nextInt(boardHeight);
// Check if the selected tile already is a mine
if (!board[n][m].isMine()) {
@ -156,12 +198,11 @@ public class Board extends JPanel {
// Touch surrounding tiles when there are zero surrounding mines
else if (tile.getSurroundingMines() == 0)
for (int i = Math.max(0, n - 1); i < Math.min(n + 1, board.length); i++)
for (int j = Math.max(0, m - 1); j < Math.min(m + 1, board[i].length); j++)
for (int i = Math.max(0, n - 1); i < Math.min(n + 2, board.length); i++)
for (int j = Math.max(0, m - 1); j < Math.min(m + 2, board[i].length); j++)
touchTile(i, j);
// Redraw the touched tile
repaint(n * tileSize, m * tileSize, (n + 1) * tileSize, (n + 1) * tileSize);
repaintTile(n, m);
}
}
@ -175,7 +216,7 @@ public class Board extends JPanel {
tile.setFlagged(true);
flaggedTiles++;
}
repaint(n * tileSize, m * tileSize, (n + 1) * tileSize, (n + 1) * tileSize);
repaintTile(n, m);
}
}
}

View File

@ -0,0 +1,20 @@
package dev.kske.minesweeper;
/**
* Project: <strong>Minesweeper</strong><br>
* File: <strong>BoardConfig.java</strong><br>
* Created: <strong>01.04.2019</strong><br>
* Author: <strong>Kai S. K. Engelbart</strong>
*/
public class BoardConfig {
public final int x, y, width, height, mines;
public BoardConfig(int x, int y, int width, int height, int mines) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.mines = mines;
}
}

View File

@ -23,7 +23,9 @@ public class Minesweeper {
private JFrame mframe;
private Board board;
private Board board;
private final BoardConfig easyConfig = new BoardConfig(0, 48, 8, 8, 10),
mediumConfig = new BoardConfig(0, 48, 16, 16, 40), hardConfig = new BoardConfig(0, 48, 30, 16, 99);
/**
* Launch the application.
@ -56,22 +58,24 @@ public class Minesweeper {
mframe = new JFrame();
mframe.setResizable(false);
mframe.setTitle("Minesweeper");
mframe.setBounds(100, 100, 450, 300);
mframe.setBounds(100, 100, 384, 308);
mframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
createMenuBar();
board = new Board(0, 0, 10, 10, 10);
board = new Board();
board.init(easyConfig);
mframe.getContentPane().add(board);
JButton btnRestart = new JButton("Restart");
btnRestart.addActionListener((evt) -> { board.reset(); });
mframe.getContentPane().add(btnRestart, BorderLayout.NORTH);
}
private void createMenuBar() {
var menubar = new JMenuBar();
var gameMenu = new JMenu("Game");
var gameMenu = new JMenu("Game");
var aboutMenuItem = new JMenuItem("About");
var easyMenuItem = new JMenuItem("Easy");
@ -85,10 +89,13 @@ public class Minesweeper {
hardMenuItem.setMnemonic(KeyEvent.VK_H);
customMenuItem.setMnemonic(KeyEvent.VK_C);
aboutMenuItem.addActionListener((event) -> {
easyMenuItem.addActionListener((evt) -> { board.init(easyConfig); });
mediumMenuItem.addActionListener((evt) -> { board.init(mediumConfig); });
hardMenuItem.addActionListener((evt) -> { board.init(hardConfig); });
aboutMenuItem.addActionListener((evt) -> {
JOptionPane.showMessageDialog(board, "Minesweeper version " + VERSION + "\nby Kai S. K. Engelbart");
});
gameMenu.add(easyMenuItem);
gameMenu.add(mediumMenuItem);
gameMenu.add(hardMenuItem);