Skip to content

Commit

Permalink
feat: can click on discovered cells to click all around
Browse files Browse the repository at this point in the history
  • Loading branch information
Darmo117 committed May 19, 2019
1 parent 748f3bf commit 9b223f4
Show file tree
Hide file tree
Showing 14 changed files with 315 additions and 277 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
apply plugin: 'java'
apply plugin: 'eclipse'

version = '1.1'
version = '1.2'
sourceCompatibility = 1.8
targetCompatibility = 1.8

Expand Down
2 changes: 0 additions & 2 deletions src/main/java/net/darmo_creations/minesweeper/ConfigTags.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,9 @@
*/
package net.darmo_creations.minesweeper;

import net.darmo_creations.gui_framework.config.tags.BooleanTag;
import net.darmo_creations.gui_framework.config.tags.IntegerTag;

public final class ConfigTags {
public static final BooleanTag SEND_SCORES = new BooleanTag("send_scores");
public static final IntegerTag BUTTONS_SIZE = new IntegerTag("buttons_size");

private ConfigTags() {}
Expand Down
198 changes: 24 additions & 174 deletions src/main/java/net/darmo_creations/minesweeper/MainController.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,13 @@
*/
package net.darmo_creations.minesweeper;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Point;
import java.time.Duration;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Random;
import java.util.TreeMap;

import javax.swing.JOptionPane;
Expand All @@ -40,8 +38,9 @@
import net.darmo_creations.minesweeper.events.TimerEvent;
import net.darmo_creations.minesweeper.gui.MainFrame;
import net.darmo_creations.minesweeper.gui.MainFrame.CellLabel;
import net.darmo_creations.minesweeper.model.Cell;
import net.darmo_creations.minesweeper.model.CellLabelProvider;
import net.darmo_creations.minesweeper.model.Difficulty;
import net.darmo_creations.minesweeper.model.Grid;
import net.darmo_creations.minesweeper.model.Score;
import net.darmo_creations.minesweeper.model.Timer;
import net.darmo_creations.utils.I18n;
Expand All @@ -52,13 +51,11 @@
*
* @author Damien Vergnet
*/
public class MainController extends ApplicationController<MainFrame> {
private Cell[][] grid;
public class MainController extends ApplicationController<MainFrame> implements CellLabelProvider {
private Difficulty difficulty;
private Grid grid;
private boolean started;
private boolean finished;
/** Number of remaining flags */
private int flags;
private Timer timer;
private int lastTime;
private Map<Difficulty, List<Score>> scores;
Expand Down Expand Up @@ -96,9 +93,6 @@ public void onUserEvent(UserEvent e) {
case SHOW_BUTTONS_SIZE:
setButtonsSize();
break;
case TOGGLE_SEND_SCORES:
this.config.setValue(ConfigTags.SEND_SCORES, !this.config.getValue(ConfigTags.SEND_SCORES));
break;
case SHOW_SCORES:
this.frame.showScoresDialog(this.scores);
break;
Expand Down Expand Up @@ -147,121 +141,31 @@ private void setGameDifficulty(Difficulty difficulty) {

@SubsribeEvent
public void onCellClicked(CellClickedEvent e) {
Point p = e.getCell().getCoordinates();
if (!this.started) {
startGame(p);
startGame(e.getCell().getCoordinates());
}

Cell cell = this.grid[p.y][p.x];
CellLabel label = e.getCell();

if (e.isMainClick() && !cell.isFlagged()) {
clickCell(cell, label);
}
else if (!e.isMainClick()) {
if (cell.isFlagged()) {
cell.setMarked(true);
label.setIcon(Images.MARK);
if (this.started && !this.finished)
this.flags++;
this.frame.setRemainingMines(this.flags);
}
else if (cell.isMarked()) {
cell.setMarked(false);
label.setIcon(Images.EMPTY_CELL);
if (!this.finished) {
if (e.isMainClick()) {
clickCell(e);
}
else {
cell.setFlagged(true);
label.setIcon(Images.FLAG);
if (this.started && !this.finished)
this.flags--;
this.frame.setRemainingMines(this.flags);
this.grid.performSecondaryClick(e);
this.frame.setRemainingMines(this.grid.getRemainingFlags());
}
}
}

private void clickCell(Cell cell, CellLabel label) {
Point p = label.getCoordinates();
int nearbyMines = getNearbyMinesNumber(p.y, p.x);
int res = cell.click(nearbyMines);

switch (res) {
case Cell.NOTHING:
label.click();
label.setBackground(new Color(150, 150, 150));
label.setIcon(Images.NUMBERS[nearbyMines]);
if (nearbyMines == 0)
exploreGrid(p.y, p.x, true);
if (checkVictory()) {
endGame(true);
}
break;
case Cell.MINE:
label.click();
label.setBackground(Color.RED);
label.setIcon(Images.MINE);
endGame(false);
break;
private void clickCell(CellClickedEvent event) {
int result = this.grid.performMainClick(event);
if (result == Grid.WIN) {
endGame(true);
}
}

/**
* Explores all the non-clicked cells from the given starting cell that don't have any mines
* nearby.
*
* @param row the starting row
* @param col the starting column
*/
private void exploreGrid(int row, int col, boolean ignoreClicked) {
Cell cell = this.grid[row][col];

if ((!ignoreClicked && cell.isClicked()) || cell.isFlagged())
return;

if (!ignoreClicked)
clickCell(cell, this.frame.getCell(new Point(col, row)));

if (getNearbyMinesNumber(row, col) == 0) {
if (row > 0)
exploreGrid(row - 1, col, false);
if (row > 0 && col < this.difficulty.getColumns() - 1)
exploreGrid(row - 1, col + 1, false);
if (col < this.difficulty.getColumns() - 1)
exploreGrid(row, col + 1, false);
if (row < this.difficulty.getRows() - 1 && col < this.difficulty.getColumns() - 1)
exploreGrid(row + 1, col + 1, false);
if (row < this.difficulty.getRows() - 1)
exploreGrid(row + 1, col, false);
if (row < this.difficulty.getRows() - 1 && col > 0)
exploreGrid(row + 1, col - 1, false);
if (col > 0)
exploreGrid(row, col - 1, false);
if (row > 0 && col > 0)
exploreGrid(row - 1, col - 1, false);
else if (result == Grid.LOST) {
endGame(false);
}
}

/**
* Returns {@code true} if the only remaining cells contain mines; false otherwise.
*/
private boolean checkVictory() {
if (!this.started)
return false;

boolean win = true;

loop: for (int row = 0; row < this.difficulty.getRows(); row++) {
for (int col = 0; col < this.difficulty.getColumns(); col++) {
if (!this.grid[row][col].isClicked() && !this.grid[row][col].isMine()) {
win = false;
break loop;
}
}
}

return win;
}

@SubsribeEvent
public void onTimerEvent(TimerEvent e) {
this.lastTime = e.getHours() * 3600 + e.getMinutes() * 60 + e.getSeconds();
Expand All @@ -275,19 +179,11 @@ private void resetGame() {
this.timer = new Timer();

this.started = this.finished = false;
this.flags = this.difficulty.getMines();
this.grid = new Cell[this.difficulty.getRows()][this.difficulty.getColumns()];

// Grid generation.
for (int row = 0; row < this.difficulty.getRows(); row++) {
for (int col = 0; col < this.difficulty.getColumns(); col++) {
this.grid[row][col] = new Cell(row, col);
}
}
this.grid = new Grid(this.difficulty, this);

this.frame.resetGrid(new Dimension(this.difficulty.getColumns(), this.difficulty.getRows()),
this.config.getValue(ConfigTags.BUTTONS_SIZE));
this.frame.setRemainingMines(this.flags);
this.frame.setRemainingMines(this.grid.getRemainingFlags());
this.frame.setTimer(0, 0, 0);
this.frame.updateMenus(false);
this.frame.pack();
Expand All @@ -302,20 +198,7 @@ private void resetGame() {
private void startGame(Point clickedCell) {
this.started = true;
this.frame.updateMenus(true);

// Mines generation
for (int i = 0; i < this.difficulty.getMines(); i++) {
int col, row;
Random rand = new Random();

do {
col = rand.nextInt(this.difficulty.getColumns());
row = rand.nextInt(this.difficulty.getRows());
} while (this.grid[row][col].isMine() || row == clickedCell.y && col == clickedCell.x);

this.grid[row][col].setMine(true);
}

this.grid.generateMines(clickedCell.y, clickedCell.x);
this.timer.start();
}

Expand All @@ -331,20 +214,7 @@ private void endGame(boolean victory) {
this.finished = true;
this.timer.interrupt();

for (int row = 0; row < this.difficulty.getRows(); row++) {
for (int col = 0; col < this.difficulty.getColumns(); col++) {
Cell cell = this.grid[row][col];
CellLabel label = this.frame.getCell(new Point(col, row));

label.lock();
if (cell.isMine()) {
label.setIcon(Images.MINE);
}
else if (!cell.isMine() && cell.isFlagged()) {
label.setIcon(Images.WRONG_MINE);
}
}
}
this.grid.endGame();
this.frame.updateMenus(false);
int choice = 0;

Expand All @@ -357,8 +227,6 @@ else if (!cell.isMine() && cell.isFlagged()) {

this.scores.get(this.difficulty).add(score);
sortScores(this.difficulty);
if (this.config.getValue(ConfigTags.SEND_SCORES))
ScoresDao.getInstance().sendScore(score, this.difficulty);
}
choice = JOptionPane.showConfirmDialog(this.frame, I18n.getLocalizedString("popup.play_again.text"), title, JOptionPane.YES_NO_OPTION,
JOptionPane.QUESTION_MESSAGE);
Expand All @@ -372,26 +240,8 @@ else if (!cell.isMine() && cell.isFlagged()) {
resetGame();
}

/**
* Returns the number of mines in the 8 adjacent cells to the one at the specified coordinates.
*
* @param row the row
* @param col the column
*
* @return the number of nearby mines
*/
private int getNearbyMinesNumber(int row, int col) {
return (row > 0 ? booleanToInt(this.grid[row - 1][col].isMine()) : 0) + //
(col < this.grid[0].length - 1 && row > 0 ? booleanToInt(this.grid[row - 1][col + 1].isMine()) : 0) + //
(col < this.grid[0].length - 1 ? booleanToInt(this.grid[row][col + 1].isMine()) : 0) + //
(col < this.grid[0].length - 1 && row < this.grid.length - 1 ? booleanToInt(this.grid[row + 1][col + 1].isMine()) : 0) + //
(row < this.grid.length - 1 ? booleanToInt(this.grid[row + 1][col].isMine()) : 0) + //
(col > 0 && row < this.grid.length - 1 ? booleanToInt(this.grid[row + 1][col - 1].isMine()) : 0) + //
(col > 0 ? booleanToInt(this.grid[row][col - 1].isMine()) : 0) + //
(col > 0 && row > 0 ? booleanToInt(this.grid[row - 1][col - 1].isMine()) : 0);
}

private int booleanToInt(boolean value) {
return value ? 1 : 0;
}
@Override
public CellLabel getLabel(int row, int col) {
return this.frame.getCell(new Point(col, row));
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,7 @@
import net.darmo_creations.utils.version.Version;

public class Minesweeper implements Application {
public static boolean debug;

public static final Version CURRENT_VERSION = new Version(1, 1, 0, false);
public static final Version CURRENT_VERSION = new Version(1, 2, 0, false);

@Override
public void preInit() {
Expand All @@ -45,7 +43,6 @@ public void preInit() {

ApplicationRegistry.setLanguages(l);

WritableConfig.registerTag(ConfigTags.SEND_SCORES, true);
WritableConfig.registerTag(ConfigTags.BUTTONS_SIZE, 15);
}

Expand Down
Loading

0 comments on commit 9b223f4

Please sign in to comment.