Jenkins
3 years ago
5 changed files with 440 additions and 0 deletions
-
143src/main/java/Minesweeper/Cell.java
-
33src/main/java/Minesweeper/MinesweeperGame.java
-
151src/main/java/Minesweeper/Playfield.java
-
60src/main/java/Minesweeper/TimerLable.java
-
53src/test/java/Minesweeper/MinesweeperGameTest.java
@ -0,0 +1,143 @@ |
|||||
|
package Minesweeper; |
||||
|
|
||||
|
import java.awt.Color; |
||||
|
import java.awt.Point; |
||||
|
import java.awt.event.ActionEvent; |
||||
|
import java.awt.event.ActionListener; |
||||
|
import java.awt.event.MouseAdapter; |
||||
|
import java.awt.event.MouseEvent; |
||||
|
|
||||
|
import javax.swing.JButton; |
||||
|
import javax.swing.JOptionPane; |
||||
|
|
||||
|
enum CellType { |
||||
|
Number, Bomb |
||||
|
} |
||||
|
|
||||
|
public class Cell extends JButton { |
||||
|
|
||||
|
private static final Color FLAGCOLOR = Color.RED; |
||||
|
private static final Color FLOODEDCOLOR = Color.LIGHT_GRAY; |
||||
|
private static final Color HIDDENCOLOR = Color.WHITE; |
||||
|
private static final Color MINECOLOR = Color.BLACK; |
||||
|
private static final long serialVersionUID = 1L; |
||||
|
private Playfield playfield; |
||||
|
|
||||
|
public CellType type; |
||||
|
public Point cord; |
||||
|
public boolean flagged = false; |
||||
|
public int value = 0; |
||||
|
|
||||
|
public Cell(CellType _type, Playfield _playfield, Point _cord) { |
||||
|
type = _type; |
||||
|
cord = _cord; |
||||
|
playfield = _playfield; |
||||
|
|
||||
|
setBackground(HIDDENCOLOR); |
||||
|
addActionListener(new ActionListener() { |
||||
|
@Override |
||||
|
public void actionPerformed(ActionEvent e) { |
||||
|
OnMouseClick(); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
addMouseListener(new MouseAdapter() { |
||||
|
@Override |
||||
|
public void mousePressed(MouseEvent e) { |
||||
|
// TODO Auto-generated method stub |
||||
|
super.mousePressed(e); |
||||
|
if (e.getButton() == 3) { |
||||
|
OnMouseRightClick(); |
||||
|
} |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
protected void OnMouseClick() { |
||||
|
if (!flagged) { |
||||
|
reveal(); |
||||
|
if (type != CellType.Bomb) { |
||||
|
flood(); |
||||
|
} else { |
||||
|
playfield.revealAllBombs(); |
||||
|
JOptionPane.showMessageDialog(getParent(),"KABOOM! Try again!"); |
||||
|
playfield.reset(); |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
|
||||
|
protected void OnMouseRightClick() { |
||||
|
if (isEnabled()) { |
||||
|
if (flagged) { |
||||
|
flagged = false; |
||||
|
|
||||
|
setBackground(HIDDENCOLOR); |
||||
|
if (type == CellType.Number) { |
||||
|
playfield.cellDried(); |
||||
|
} |
||||
|
|
||||
|
} else { |
||||
|
flagged = true; |
||||
|
setBackground(FLAGCOLOR); |
||||
|
if (type == CellType.Number) { |
||||
|
playfield.cellFlooded(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public void reveal() { |
||||
|
if (type == CellType.Number) { |
||||
|
if(value > 0) { |
||||
|
setText(String.valueOf(value)); |
||||
|
} |
||||
|
} else { |
||||
|
setBackground(MINECOLOR); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public void flood() { |
||||
|
if (type == CellType.Bomb || flagged) { |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
setBackground(FLOODEDCOLOR); |
||||
|
setEnabled(false); |
||||
|
reveal(); |
||||
|
playfield.cellFlooded(); |
||||
|
|
||||
|
if (value == 0) { |
||||
|
if (cord.y > 0) { |
||||
|
if (playfield.cells[cord.y - 1][cord.x].type == CellType.Number |
||||
|
&& playfield.cells[cord.y - 1][cord.x].isEnabled()) { |
||||
|
playfield.cells[cord.y - 1][cord.x].flood(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (cord.x < playfield.Size - 1) { |
||||
|
if (playfield.cells[cord.y][cord.x + 1].type == CellType.Number |
||||
|
&& playfield.cells[cord.y][cord.x + 1].isEnabled()) { |
||||
|
playfield.cells[cord.y][cord.x + 1].flood(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (cord.y < playfield.Size - 1) { |
||||
|
if (playfield.cells[cord.y + 1][cord.x].type == CellType.Number |
||||
|
&& playfield.cells[cord.y + 1][cord.x].isEnabled()) { |
||||
|
playfield.cells[cord.y + 1][cord.x].flood(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (cord.x > 0) { |
||||
|
if (playfield.cells[cord.y][cord.x - 1].type == CellType.Number |
||||
|
&& playfield.cells[cord.y][cord.x - 1].isEnabled()) { |
||||
|
playfield.cells[cord.y][cord.x - 1].flood(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,33 @@ |
|||||
|
package Minesweeper; |
||||
|
|
||||
|
import javax.swing.JFrame; |
||||
|
import javax.swing.JPanel; |
||||
|
|
||||
|
public class MinesweeperGame extends JPanel { |
||||
|
|
||||
|
private static final long serialVersionUID = 1L; |
||||
|
public static final int WIDTH = 600, HEIGTH = 600; |
||||
|
public Playfield playfield; |
||||
|
public TimerLable tl; |
||||
|
|
||||
|
public MinesweeperGame(int _playfieldSize, int _bombAmount) { |
||||
|
this.setSize(WIDTH, HEIGTH); |
||||
|
setLayout(null); |
||||
|
playfield = new Playfield(this, _playfieldSize, _bombAmount); |
||||
|
|
||||
|
tl = new TimerLable(); |
||||
|
tl.setBounds((WIDTH / 2 - 5), HEIGTH / 2 - 240, 20, 20); |
||||
|
add(tl); |
||||
|
tl.start(); |
||||
|
} |
||||
|
|
||||
|
public static void main(String[] args) { |
||||
|
JFrame f = new JFrame(); |
||||
|
MinesweeperGame MsG = new MinesweeperGame(8, 10); |
||||
|
|
||||
|
f.add(MsG); |
||||
|
f.setSize(WIDTH, HEIGTH); |
||||
|
f.setLayout(null); |
||||
|
f.setVisible(true); |
||||
|
} |
||||
|
} |
@ -0,0 +1,151 @@ |
|||||
|
package Minesweeper; |
||||
|
|
||||
|
import java.awt.Point; |
||||
|
|
||||
|
import javax.swing.JOptionPane; |
||||
|
|
||||
|
public class Playfield { |
||||
|
|
||||
|
private static final int CELLSIZE = 50; |
||||
|
public int Size; |
||||
|
private MinesweeperGame MsG; |
||||
|
public Cell[][] cells; |
||||
|
private int bombAmount; |
||||
|
private int cellsFlooded = 0; |
||||
|
|
||||
|
public Playfield(MinesweeperGame _MsG, int _Size, int _bombAmount) { |
||||
|
MsG = _MsG; |
||||
|
Size = _Size; |
||||
|
bombAmount = _bombAmount; |
||||
|
generatePlayfield(); |
||||
|
} |
||||
|
|
||||
|
public void generatePlayfield() { |
||||
|
|
||||
|
cells = new Cell[Size][Size]; |
||||
|
|
||||
|
int[] bPlacement = new int[bombAmount]; |
||||
|
for (int i = 0; i < bPlacement.length; i++) { |
||||
|
bPlacement[i] = (int) (Math.random() * Size * Size); |
||||
|
|
||||
|
for (int j = 0; j < i; j++) { |
||||
|
if (bPlacement[i] == bPlacement[j]) { |
||||
|
i--; |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
for (int i = 0; i < Size; i++) { |
||||
|
for (int j = 0; j < Size; j++) { |
||||
|
cells[i][j] = new Cell(CellType.Number, this, new Point(j, i)); |
||||
|
|
||||
|
cells[i][j].setBounds(j * CELLSIZE + (MsG.WIDTH / 2 - Size * CELLSIZE / 2), |
||||
|
i * CELLSIZE + (MsG.HEIGTH / 2 - Size * CELLSIZE / 2), CELLSIZE, CELLSIZE); |
||||
|
MsG.add(cells[i][j]); |
||||
|
for (int k = 0; k < bPlacement.length; k++) { |
||||
|
if (bPlacement[k] == i * Size + j) { |
||||
|
cells[i][j].type = CellType.Bomb; |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
for (int i = 0; i < Size; i++) { |
||||
|
for (int j = 0; j < Size; j++) { |
||||
|
if (cells[i][j].type == CellType.Number) { |
||||
|
calculateBombProximity(i, j); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
MsG.repaint(); |
||||
|
} |
||||
|
|
||||
|
public void reset() { |
||||
|
cellsFlooded = 0; |
||||
|
for (int i = 0; i < Size; i++) { |
||||
|
for (int j = 0; j < Size; j++) { |
||||
|
MsG.remove(cells[i][j]); |
||||
|
} |
||||
|
} |
||||
|
MsG.tl.reset(); |
||||
|
generatePlayfield(); |
||||
|
} |
||||
|
|
||||
|
public void calculateBombProximity(int row, int column) { |
||||
|
|
||||
|
if (row > 0) { |
||||
|
if (column > 0) { |
||||
|
if (cells[row - 1][column - 1].type == CellType.Bomb) { |
||||
|
cells[row][column].value++; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (cells[row - 1][column].type == CellType.Bomb) { |
||||
|
cells[row][column].value++; |
||||
|
} |
||||
|
|
||||
|
if (column < cells.length - 1) { |
||||
|
if (cells[row - 1][column + 1].type == CellType.Bomb) { |
||||
|
cells[row][column].value++; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (row < cells.length - 1) { |
||||
|
if (column > 0) { |
||||
|
if (cells[row + 1][column - 1].type == CellType.Bomb) { |
||||
|
cells[row][column].value++; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (cells[row + 1][column].type == CellType.Bomb) { |
||||
|
cells[row][column].value++; |
||||
|
} |
||||
|
|
||||
|
if (column < cells.length - 1) { |
||||
|
if (cells[row + 1][column + 1].type == CellType.Bomb) { |
||||
|
cells[row][column].value++; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (column > 0) { |
||||
|
if (cells[row][column - 1].type == CellType.Bomb) { |
||||
|
cells[row][column].value++; |
||||
|
} |
||||
|
} |
||||
|
if (column < cells.length - 1) { |
||||
|
if (cells[row][column + 1].type == CellType.Bomb) { |
||||
|
cells[row][column].value++; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
public void cellFlooded() { |
||||
|
cellsFlooded++; |
||||
|
if (cellsFlooded >= Size * Size - bombAmount) { |
||||
|
revealAllBombs(); |
||||
|
JOptionPane.showMessageDialog(MsG, "You won, congratulations!"); |
||||
|
reset(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public void revealAllBombs() { |
||||
|
for (int i = 0; i < Size; i++) { |
||||
|
for (int j = 0; j < Size; j++) { |
||||
|
if(cells[i][j].type == CellType.Bomb) { |
||||
|
cells[i][j].reveal(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
MsG.tl.stop(); |
||||
|
MsG.repaint(); |
||||
|
} |
||||
|
|
||||
|
public void cellDried() { |
||||
|
cellsFlooded--; |
||||
|
} |
||||
|
} |
@ -0,0 +1,60 @@ |
|||||
|
package Minesweeper; |
||||
|
|
||||
|
import java.util.Timer; |
||||
|
import java.util.TimerTask; |
||||
|
|
||||
|
import javax.swing.JLabel; |
||||
|
|
||||
|
public class TimerLable extends JLabel { |
||||
|
|
||||
|
private static final long serialVersionUID = 1L; |
||||
|
protected int counter = 0; |
||||
|
private Helper task; |
||||
|
|
||||
|
public void start() { |
||||
|
Timer timer = new Timer(); |
||||
|
task = new Helper(this); |
||||
|
|
||||
|
timer.schedule(task, 0, 1000); |
||||
|
} |
||||
|
|
||||
|
public void update() { |
||||
|
setText(String.valueOf(++counter)); |
||||
|
} |
||||
|
|
||||
|
public void reset() { |
||||
|
task.reset = true; |
||||
|
counter = 0; |
||||
|
setText(String.valueOf(counter)); |
||||
|
repaint(); |
||||
|
task.stop = false; |
||||
|
} |
||||
|
|
||||
|
public void stop() { |
||||
|
task.stop = true; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
class Helper extends TimerTask |
||||
|
{ |
||||
|
public boolean reset; |
||||
|
public boolean stop; |
||||
|
public static int i = 0; |
||||
|
private TimerLable timerLable; |
||||
|
|
||||
|
public Helper(TimerLable _timerLable) { |
||||
|
timerLable = _timerLable; |
||||
|
} |
||||
|
public void run() |
||||
|
{ |
||||
|
if(stop) { |
||||
|
return; |
||||
|
} |
||||
|
if(reset) { |
||||
|
reset = false; |
||||
|
timerLable.counter = 0; |
||||
|
} |
||||
|
timerLable.update(); |
||||
|
} |
||||
|
} |
@ -0,0 +1,53 @@ |
|||||
|
package Minesweeper; |
||||
|
|
||||
|
import static org.junit.jupiter.api.Assertions.*; |
||||
|
|
||||
|
import java.util.stream.Stream; |
||||
|
|
||||
|
import org.junit.jupiter.api.Test; |
||||
|
import org.junit.jupiter.params.ParameterizedTest; |
||||
|
import org.junit.jupiter.params.provider.Arguments; |
||||
|
import org.junit.jupiter.params.provider.MethodSource; |
||||
|
|
||||
|
class MinesweeperGameTest { |
||||
|
|
||||
|
@ParameterizedTest |
||||
|
@MethodSource("testBombs") |
||||
|
void testBombPlacement(int _playfieldSize, int _bombAmount) { |
||||
|
MinesweeperGame m = new MinesweeperGame(_playfieldSize, _bombAmount); |
||||
|
|
||||
|
int bombCounter = 0; |
||||
|
|
||||
|
for(Cell[] row : m.playfield.cells){ |
||||
|
for (Cell c : row) { |
||||
|
if(c.type == CellType.Bomb) { |
||||
|
bombCounter++; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
assertEquals(_bombAmount, bombCounter); |
||||
|
} |
||||
|
|
||||
|
@Test |
||||
|
void testProximityPoints() { |
||||
|
MinesweeperGame m = new MinesweeperGame(3, 0); |
||||
|
m.playfield.cells[0][0].type = CellType.Bomb; |
||||
|
m.playfield.calculateBombProximity(1, 1); |
||||
|
|
||||
|
assertEquals(1, m.playfield.cells[1][1].value); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
private static Stream<Arguments> testBombs(){ |
||||
|
return Stream.of( |
||||
|
Arguments.of(8, 10), |
||||
|
Arguments.of(8, 0), |
||||
|
Arguments.of(4, 12), |
||||
|
Arguments.of(10, 100), |
||||
|
Arguments.of(5, 1) |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue