Implemented basic gameplay and window adjustment

This commit is contained in:
Kai S. K. Engelbart 2019-04-02 18:54:42 +02:00
parent 4e63dea497
commit 0b927c5c9f
2 changed files with 54 additions and 59 deletions

View File

@ -6,7 +6,6 @@ import java.awt.Font;
import java.awt.FontMetrics; import java.awt.FontMetrics;
import java.awt.Graphics; import java.awt.Graphics;
import java.awt.Image; import java.awt.Image;
import java.awt.Point;
import java.awt.event.MouseAdapter; import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent; import java.awt.event.MouseEvent;
import java.util.HashMap; import java.util.HashMap;
@ -29,7 +28,6 @@ public class Board extends JPanel {
private static Map<String, Image> icons; private static Map<String, Image> icons;
private int boardWidth, boardHeight; private int boardWidth, boardHeight;
private GameState gameState; private GameState gameState;
private int mines, activeTiles, flaggedTiles; private int mines, activeTiles, flaggedTiles;
private Tile[][] board; private Tile[][] board;
@ -47,26 +45,22 @@ public class Board extends JPanel {
public Board() { public Board() {
// Not using a layout manager // Not using a layout manager
super(null); super(null);
addMouseListener(new MouseAdapter() { addMouseListener(new MouseAdapter() {
@Override @Override
public void mousePressed(MouseEvent evt) { public void mousePressed(MouseEvent evt) {
Point tilePos = getTilePos(evt.getX(), evt.getY()); int n = evt.getX() / tileSize, m = evt.getY() / tileSize;
int n = tilePos.x, m = tilePos.y;
Tile tile = board[n][m]; Tile tile = board[n][m];
if (tile.isTouched() || gameState != GameState.ACTIVE) return; if (tile.isTouched() || gameState != GameState.ACTIVE) return;
switch (evt.getButton()) { switch (evt.getButton()) {
case MouseEvent.BUTTON1: case MouseEvent.BUTTON1:
// Touch tile
touchTile(n, m); touchTile(n, m);
break; break;
case MouseEvent.BUTTON3: case MouseEvent.BUTTON3:
// Flag tile
flagTile(n, m); flagTile(n, m);
} }
if (gameState != GameState.ACTIVE) repaint();
} }
}); });
} }
@ -84,12 +78,12 @@ public class Board extends JPanel {
activeTiles = boardWidth * boardHeight; activeTiles = boardWidth * boardHeight;
flaggedTiles = 0; flaggedTiles = 0;
// Init board // Initialize board
board = new Tile[boardWidth][boardHeight]; board = new Tile[boardWidth][boardHeight];
for (int i = 0; i < boardWidth; i++) for (int i = 0; i < boardWidth; i++)
for (int j = 0; j < boardHeight; j++) for (int j = 0; j < boardHeight; j++)
board[i][j] = new Tile(); board[i][j] = new Tile();
initMines();
repaint(); repaint();
} }
@ -111,18 +105,11 @@ public class Board extends JPanel {
g.setColor(Color.black); g.setColor(Color.black);
g.drawRect(x, y, x + tileSize, y + tileSize); g.drawRect(x, y, x + tileSize, y + tileSize);
// Draw all mines when the game is won or lost
switch (gameState) {
case LOST:
// Draw tile with normal mine // Draw tile with normal mine
if (tile.isMine()) g.drawImage(icons.get("mine2"), x, y, this); if (gameState == GameState.LOST && tile.isMine()) g.drawImage(icons.get("mine2"), x, y, this);
break;
case WON:
// Draw tile with diffused mine // Draw tile with diffused mine
if (tile.isMine()) g.drawImage(icons.get("mine4"), x, y, this); else if (gameState == GameState.WON && tile.isMine()) g.drawImage(icons.get("mine4"), x, y, this);
break; else if (tile.isTouched()) {
default:
if (tile.isTouched()) {
// Draw tile with mine // Draw tile with mine
if (tile.isMine()) g.drawImage(icons.get("mine2"), x, y, this); if (tile.isMine()) g.drawImage(icons.get("mine2"), x, y, this);
@ -131,10 +118,10 @@ public class Board extends JPanel {
else if (tile.isDrawSurroundingMines() && tile.getSurroundingMines() > 0) { else if (tile.isDrawSurroundingMines() && tile.getSurroundingMines() > 0) {
// Draw number of surrounding mines // Draw number of surrounding mines
String numStr = String.valueOf(tile.getSurroundingMines()); String numStr = String.valueOf(tile.getSurroundingMines());
g.setFont(new Font("Helvetica", Font.PLAIN, 18));
FontMetrics fm = g.getFontMetrics(); FontMetrics fm = g.getFontMetrics();
int w = fm.stringWidth(numStr), h = fm.getHeight(); int w = fm.stringWidth(numStr), h = fm.getHeight();
g.setFont(new Font("Helvetica", Font.PLAIN, 12)); g.drawString(numStr, x + tileSize / 2 - w / 2, y + tileSize / 2 + h / 2);
g.drawString(numStr, x + tileSize / 2 - w / 2, y + tileSize / 2 - h / 2);
} }
} }
@ -145,17 +132,12 @@ public class Board extends JPanel {
else g.drawImage(icons.get("tile"), x, y, this); else g.drawImage(icons.get("tile"), x, y, this);
} }
} }
}
private void repaintTile(int n, int m) { private void repaintTile(int n, int m) {
repaint(n * tileSize, m * tileSize, (n + 1) * tileSize, (n + 1) * tileSize); repaint(n * tileSize, m * tileSize, (n + 1) * tileSize, (n + 1) * tileSize);
} }
public Point getTilePos(int x, int y) { private void initMines() {
return new Point(x / tileSize, y / tileSize);
}
public void initMines() {
int remaining = mines; int remaining = mines;
Random random = new Random(); Random random = new Random();
while (remaining > 0) { while (remaining > 0) {
@ -163,7 +145,7 @@ public class Board extends JPanel {
int n = random.nextInt(boardWidth); int n = random.nextInt(boardWidth);
int m = random.nextInt(boardHeight); int m = random.nextInt(boardHeight);
// Check if the selected tile already is a mine // Check if the selected tile already is a mine and is not touched
if (!board[n][m].isMine()) { if (!board[n][m].isMine()) {
// Decrement the counter // Decrement the counter
remaining--; remaining--;
@ -172,14 +154,14 @@ public class Board extends JPanel {
board[n][m].setMine(true); board[n][m].setMine(true);
// Adjust surrounding mine counters // Adjust surrounding mine counters
for (int i = Math.max(0, n - 1); i < Math.min(n + 1, board.length); i++) 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 + 1, board[i].length); j++) for (int j = Math.max(0, m - 1); j < Math.min(m + 2, board[i].length); j++)
if (i != n || j != m) board[i][j].setSurroundingMines(board[i][j].getSurroundingMines() + 1); board[i][j].setSurroundingMines(board[i][j].getSurroundingMines() + 1);
} }
} }
} }
public void touchTile(int n, int m) { private void touchTile(int n, int m) {
Tile tile = board[n][m]; Tile tile = board[n][m];
if (!tile.isTouched()) { if (!tile.isTouched()) {
tile.setTouched(true); tile.setTouched(true);
@ -200,13 +182,13 @@ public class Board extends JPanel {
else if (tile.getSurroundingMines() == 0) else if (tile.getSurroundingMines() == 0)
for (int i = Math.max(0, n - 1); i < Math.min(n + 2, board.length); i++) 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++) for (int j = Math.max(0, m - 1); j < Math.min(m + 2, board[i].length); j++)
touchTile(i, j); if (i != n || j != m && board[i][j].getSurroundingMines() == 0) touchTile(i, j);
repaintTile(n, m); repaintTile(n, m);
} }
} }
public void flagTile(int n, int m) { private void flagTile(int n, int m) {
Tile tile = board[n][m]; Tile tile = board[n][m];
if (!tile.isTouched()) { if (!tile.isTouched()) {
if (tile.isFlagged()) { if (tile.isFlagged()) {
@ -219,4 +201,10 @@ public class Board extends JPanel {
repaintTile(n, m); repaintTile(n, m);
} }
} }
public int getMines() { return mines; }
public int getActiveTiles() { return activeTiles; }
public int getFlaggedTiles() { return flaggedTiles; }
} }

View File

@ -58,18 +58,20 @@ public class Minesweeper {
mframe = new JFrame(); mframe = new JFrame();
mframe.setResizable(false); mframe.setResizable(false);
mframe.setTitle("Minesweeper"); mframe.setTitle("Minesweeper");
mframe.setBounds(100, 100, 384, 308); mframe.setBounds(100, 100, 198, 123);
mframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); mframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
createMenuBar(); createMenuBar();
board = new Board(); board = new Board();
board.init(easyConfig); board.init(easyConfig);
mframe.getContentPane().add(board); mframe.getContentPane().setLayout(new BorderLayout(0, 0));
mframe.getContentPane().add(board, BorderLayout.CENTER);
JButton btnRestart = new JButton("Restart"); JButton btnRestart = new JButton("Restart");
btnRestart.addActionListener((evt) -> { board.reset(); }); btnRestart.addActionListener((evt) -> board.reset());
mframe.getContentPane().add(btnRestart, BorderLayout.NORTH); mframe.getContentPane().add(btnRestart, BorderLayout.NORTH);
mframe.pack();
} }
private void createMenuBar() { private void createMenuBar() {
@ -89,9 +91,9 @@ public class Minesweeper {
hardMenuItem.setMnemonic(KeyEvent.VK_H); hardMenuItem.setMnemonic(KeyEvent.VK_H);
customMenuItem.setMnemonic(KeyEvent.VK_C); customMenuItem.setMnemonic(KeyEvent.VK_C);
easyMenuItem.addActionListener((evt) -> { board.init(easyConfig); }); easyMenuItem.addActionListener((evt) -> initGame(easyConfig));
mediumMenuItem.addActionListener((evt) -> { board.init(mediumConfig); }); mediumMenuItem.addActionListener((evt) -> initGame(mediumConfig));
hardMenuItem.addActionListener((evt) -> { board.init(hardConfig); }); hardMenuItem.addActionListener((evt) -> initGame(hardConfig));
aboutMenuItem.addActionListener((evt) -> { aboutMenuItem.addActionListener((evt) -> {
JOptionPane.showMessageDialog(board, "Minesweeper version " + VERSION + "\nby Kai S. K. Engelbart"); JOptionPane.showMessageDialog(board, "Minesweeper version " + VERSION + "\nby Kai S. K. Engelbart");
}); });
@ -106,4 +108,9 @@ public class Minesweeper {
mframe.setJMenuBar(menubar); mframe.setJMenuBar(menubar);
} }
private void initGame(BoardConfig config) {
board.init(config);
mframe.pack();
}
} }