diff --git a/.classpath b/.classpath
index fe80859..07b86b3 100644
--- a/.classpath
+++ b/.classpath
@@ -1,11 +1,11 @@
-
+
diff --git a/res/Flag.ico b/res/Flag.ico
deleted file mode 100644
index 3bda547..0000000
Binary files a/res/Flag.ico and /dev/null differ
diff --git a/res/Mine.ico b/res/Mine.ico
deleted file mode 100644
index 21bddb1..0000000
Binary files a/res/Mine.ico and /dev/null differ
diff --git a/res/Mine2.ico b/res/Mine2.ico
deleted file mode 100644
index 84b5963..0000000
Binary files a/res/Mine2.ico and /dev/null differ
diff --git a/res/Mine3.ico b/res/Mine3.ico
deleted file mode 100644
index 726dc08..0000000
Binary files a/res/Mine3.ico and /dev/null differ
diff --git a/res/Mine4.ico b/res/Mine4.ico
deleted file mode 100644
index 5e1aed0..0000000
Binary files a/res/Mine4.ico and /dev/null differ
diff --git a/res/Smiley.ico b/res/Smiley.ico
deleted file mode 100644
index d251eab..0000000
Binary files a/res/Smiley.ico and /dev/null differ
diff --git a/res/Smiley1.ico b/res/Smiley1.ico
deleted file mode 100644
index c33e93a..0000000
Binary files a/res/Smiley1.ico and /dev/null differ
diff --git a/res/Smiley2.ico b/res/Smiley2.ico
deleted file mode 100644
index 7a49a43..0000000
Binary files a/res/Smiley2.ico and /dev/null differ
diff --git a/res/Smiley3.ico b/res/Smiley3.ico
deleted file mode 100644
index 7975f49..0000000
Binary files a/res/Smiley3.ico and /dev/null differ
diff --git a/res/Tile.ico b/res/Tile.ico
deleted file mode 100644
index 316d900..0000000
Binary files a/res/Tile.ico and /dev/null differ
diff --git a/res/Tile2.ico b/res/Tile2.ico
deleted file mode 100644
index 6872dcb..0000000
Binary files a/res/Tile2.ico and /dev/null differ
diff --git a/res/Tile3.ico b/res/Tile3.ico
deleted file mode 100644
index eb9d7fc..0000000
Binary files a/res/Tile3.ico and /dev/null differ
diff --git a/res/Tile4.ico b/res/Tile4.ico
deleted file mode 100644
index cfe2139..0000000
Binary files a/res/Tile4.ico and /dev/null differ
diff --git a/res/flag.png b/res/flag.png
new file mode 100644
index 0000000..70bde50
Binary files /dev/null and b/res/flag.png differ
diff --git a/res/mine.png b/res/mine.png
new file mode 100644
index 0000000..658d93b
Binary files /dev/null and b/res/mine.png differ
diff --git a/res/mine2.png b/res/mine2.png
new file mode 100644
index 0000000..47fe196
Binary files /dev/null and b/res/mine2.png differ
diff --git a/res/mine3.png b/res/mine3.png
new file mode 100644
index 0000000..b707ffd
Binary files /dev/null and b/res/mine3.png differ
diff --git a/res/mine4.png b/res/mine4.png
new file mode 100644
index 0000000..c529c82
Binary files /dev/null and b/res/mine4.png differ
diff --git a/res/smiley.png b/res/smiley.png
new file mode 100644
index 0000000..f3dac13
Binary files /dev/null and b/res/smiley.png differ
diff --git a/res/smiley1.png b/res/smiley1.png
new file mode 100644
index 0000000..40132d3
Binary files /dev/null and b/res/smiley1.png differ
diff --git a/res/smiley2.png b/res/smiley2.png
new file mode 100644
index 0000000..6487c0f
Binary files /dev/null and b/res/smiley2.png differ
diff --git a/res/smiley3.png b/res/smiley3.png
new file mode 100644
index 0000000..f736de4
Binary files /dev/null and b/res/smiley3.png differ
diff --git a/res/tile.png b/res/tile.png
new file mode 100644
index 0000000..d66d495
Binary files /dev/null and b/res/tile.png differ
diff --git a/res/tile2.png b/res/tile2.png
new file mode 100644
index 0000000..9e9ceb1
Binary files /dev/null and b/res/tile2.png differ
diff --git a/res/tile3.png b/res/tile3.png
new file mode 100644
index 0000000..706eb4d
Binary files /dev/null and b/res/tile3.png differ
diff --git a/res/tile4.png b/res/tile4.png
new file mode 100644
index 0000000..164a82a
Binary files /dev/null and b/res/tile4.png differ
diff --git a/src/dev/kske/minesweeper/Board.java b/src/dev/kske/minesweeper/Board.java
index a1a0803..2580511 100644
--- a/src/dev/kske/minesweeper/Board.java
+++ b/src/dev/kske/minesweeper/Board.java
@@ -1,12 +1,17 @@
package dev.kske.minesweeper;
import java.awt.Color;
+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.util.HashMap;
+import java.util.Map;
import java.util.Random;
-import javax.swing.JFrame;
+import javax.swing.JPanel;
/**
* Project: Minesweeper
@@ -14,23 +19,34 @@ import javax.swing.JFrame;
* Created: 22.03.2019
* Author: Kai S. K. Engelbart
*/
-public class Board {
+public class Board extends JPanel {
- private int tileSize, width, height;
+ private static final long serialVersionUID = -279269871397851420L;
+ private static final int tileSize = 32;
+
+ private static Map icons;
+
+ private int width, height;
private Rectangle screen;
private GameState gameState;
private int mines, activeTiles, flaggedTiles;
private Tile[][] board;
- private final JFrame viewport;
+ static {
+ icons = new HashMap<>();
+ final String[] names = { "mine2", "mine4", "tile", "tile3", "flag" };
+ for (String name : names) {
+ icons.put(name, TextureLoader.loadScaledImage(name, tileSize));
+ }
+ }
- public Board(int x, int y, int width, int height, int tileSize, int mines, JFrame viewport) {
- this.tileSize = tileSize;
- this.width = width;
- this.height = height;
- screen = new Rectangle(x, y, x + width * tileSize, y + height * tileSize);
- this.viewport = viewport;
+ public Board(int x, int y, int width, int height, int mines) {
+ // Not using a layout manager
+ super(null);
+ this.width = width;
+ this.height = height;
+ screen = new Rectangle(x, y, x + width * tileSize, y + height * tileSize);
gameState = GameState.ACTIVE;
this.mines = mines;
@@ -43,6 +59,56 @@ public class Board {
board[i][j] = new Tile();
}
+ @Override
+ public void paintComponent(Graphics g) {
+ super.paintComponent(g);
+ for (int i = 0; i < width; i++)
+ for (int j = 0; j < height; j++) {
+ Tile tile = board[i][j];
+ int x = screen.x + i * tileSize, y = screen.y + j * tileSize;
+
+ // Draw background with grid
+ g.setColor(Color.gray);
+ g.fillRect(x, y, x + tileSize, y + tileSize);
+ g.setColor(Color.black);
+ 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
+ g.drawImage(icons.get("mine2"), x, y, this);
+ break;
+ case WON:
+ // Draw tile with diffused mine
+ g.drawImage(icons.get("mine4"), x, y, this);
+ break;
+ default:
+ if (tile.isTouched()) {
+
+ // Draw tile with mine
+ if (tile.isMine()) g.drawImage(icons.get("mine2"), x, y, this);
+
+ // Draw flagged tile
+ else if (tile.isDrawSurroundingMines() && tile.getSurroundingMines() > 0) {
+ // Draw number of surrounding mines
+ String numStr = String.valueOf(tile.getSurroundingMines());
+ FontMetrics fm = g.getFontMetrics();
+ 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);
+ }
+ }
+
+ // Draw flagged tile
+ else if (tile.isFlagged()) g.drawImage(icons.get("flag"), x, y, this);
+
+ // Draw normal tile
+ else g.drawImage(icons.get("tile"), x, y, this);
+ }
+ }
+ }
+
public Point getTilePos(int x, int y) {
return new Point((x - screen.x) / tileSize, (y - screen.y) / tileSize);
}
@@ -95,7 +161,7 @@ public class Board {
touchTile(i, j);
// Redraw the touched tile
- drawTile(n, m);
+ repaint(n * tileSize, m * tileSize, (n + 1) * tileSize, (n + 1) * tileSize);
}
}
@@ -109,28 +175,7 @@ public class Board {
tile.setFlagged(true);
flaggedTiles++;
}
- drawTile(n, m);
+ repaint(n * tileSize, m * tileSize, (n + 1) * tileSize, (n + 1) * tileSize);
}
}
-
- public void draw() {
- for(int i = 0; i < width; i++)
- for (int j = 0; j < height; j++)
- drawTile(i, j);
- }
-
- public void drawTile(int n, int m) {
- Tile tile = board[n][m];
- int x = screen.x + n * tileSize, y = screen.y + m * tileSize;
- Graphics g = viewport.getGraphics();
-
- // Draw background with grid
- g.setColor(Color.gray);
- g.fillRect(x, y, x + tileSize, y + tileSize);
- g.setColor(Color.black);
- g.drawRect(x, y, x + tileSize, y + tileSize);
-
- // Draw all mines if the game is lost
- // if(gameState == GameState.LOST)
- }
}
diff --git a/src/dev/kske/minesweeper/Minesweeper.java b/src/dev/kske/minesweeper/Minesweeper.java
index 14ac0eb..8af2231 100644
--- a/src/dev/kske/minesweeper/Minesweeper.java
+++ b/src/dev/kske/minesweeper/Minesweeper.java
@@ -1,8 +1,15 @@
package dev.kske.minesweeper;
+import java.awt.BorderLayout;
import java.awt.EventQueue;
+import java.awt.event.KeyEvent;
+import javax.swing.JButton;
import javax.swing.JFrame;
+import javax.swing.JMenu;
+import javax.swing.JMenuBar;
+import javax.swing.JMenuItem;
+import javax.swing.JOptionPane;
/**
* Project: Minesweeper
@@ -12,6 +19,8 @@ import javax.swing.JFrame;
*/
public class Minesweeper {
+ private static final String VERSION = "1.0 JE";
+
private JFrame mframe;
private Board board;
@@ -50,8 +59,44 @@ public class Minesweeper {
mframe.setBounds(100, 100, 450, 300);
mframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
- board = new Board(0, 0, 10, 10, 32, 10, mframe);
- board.draw();
+ createMenuBar();
+
+ board = new Board(0, 0, 10, 10, 10);
+ mframe.getContentPane().add(board);
+
+ JButton btnRestart = new JButton("Restart");
+ mframe.getContentPane().add(btnRestart, BorderLayout.NORTH);
}
+ private void createMenuBar() {
+ var menubar = new JMenuBar();
+
+ var gameMenu = new JMenu("Game");
+ var aboutMenuItem = new JMenuItem("About");
+
+ var easyMenuItem = new JMenuItem("Easy");
+ var mediumMenuItem = new JMenuItem("Medium");
+ var hardMenuItem = new JMenuItem("Hard");
+ var customMenuItem = new JMenuItem("Custom");
+
+ gameMenu.setMnemonic(KeyEvent.VK_G);
+ easyMenuItem.setMnemonic(KeyEvent.VK_E);
+ mediumMenuItem.setMnemonic(KeyEvent.VK_M);
+ hardMenuItem.setMnemonic(KeyEvent.VK_H);
+ customMenuItem.setMnemonic(KeyEvent.VK_C);
+
+ aboutMenuItem.addActionListener((event) -> {
+ JOptionPane.showMessageDialog(board, "Minesweeper version " + VERSION + "\nby Kai S. K. Engelbart");
+ });
+
+ gameMenu.add(easyMenuItem);
+ gameMenu.add(mediumMenuItem);
+ gameMenu.add(hardMenuItem);
+ gameMenu.addSeparator();
+ gameMenu.add(customMenuItem);
+ menubar.add(gameMenu);
+ menubar.add(aboutMenuItem);
+
+ mframe.setJMenuBar(menubar);
+ }
}
diff --git a/src/dev/kske/minesweeper/TextureLoader.java b/src/dev/kske/minesweeper/TextureLoader.java
new file mode 100644
index 0000000..7059649
--- /dev/null
+++ b/src/dev/kske/minesweeper/TextureLoader.java
@@ -0,0 +1,38 @@
+package dev.kske.minesweeper;
+
+import java.awt.Image;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+
+import javax.imageio.ImageIO;
+
+/**
+ * Project: Minesweeper
+ * File: TextureLoader.java
+ * Created: 25.03.2019
+ * Author: Kai S. K. Engelbart
+ */
+public class TextureLoader {
+
+ private TextureLoader() {}
+
+ /**
+ * Loads an image from the resource folder and scales it to a square.
+ *
+ * @param name The name of the file without the PNG extension in the resource
+ * folder
+ * @param scale The side length of the square to which the image will be scaled
+ * @return The scaled image
+ */
+ public static Image loadScaledImage(String name, int scale) {
+ BufferedImage in = null;
+ try {
+ in = ImageIO.read(new File("res" + File.separator + name + ".png"));
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ Image scaled = in.getScaledInstance(scale, scale, Image.SCALE_SMOOTH);
+ return scaled;
+ }
+}
diff --git a/src/dev/kske/minesweeper/Tile.java b/src/dev/kske/minesweeper/Tile.java
index 38f48a0..ccfa7e1 100644
--- a/src/dev/kske/minesweeper/Tile.java
+++ b/src/dev/kske/minesweeper/Tile.java
@@ -1,13 +1,5 @@
package dev.kske.minesweeper;
-import java.awt.image.BufferedImage;
-import java.io.IOException;
-import java.net.URL;
-import java.util.HashMap;
-import java.util.Map;
-
-import javax.imageio.ImageIO;
-
/**
* Project: Minesweeper
* File: Tile.java
@@ -16,27 +8,11 @@ import javax.imageio.ImageIO;
*/
public class Tile {
- private static Map icons;
-
private boolean mine, flagged, touched;
private boolean drawSurroundingMines;
private int surroundingMines;
- static {
- icons = new HashMap<>();
- final String[] names = { "Mine2", "Mine4", "Tile", "Tile3" };
- for (String name : names) {
- URL file = Tile.class.getResource(name + ".ico");
- try {
- icons.put(name, ImageIO.read(file));
- } catch (IOException e) {
- System.err.println("Error loading texture: " + name);
- e.printStackTrace();
- }
- }
- }
-
public Tile() {
mine = flagged = touched = drawSurroundingMines = false;