Compare commits
9 Commits
1.2.0
...
2827d79556
Author | SHA1 | Date | |
---|---|---|---|
2827d79556
|
|||
![]() |
367ad5921a | ||
![]() |
fd82088a08 | ||
8e836b1183
|
|||
44125ce13a
|
|||
76b44d22cf
|
|||
d19f9899cf
|
|||
![]() |
7e536cf644 | ||
![]() |
f5c63f9401 |
12
README.md
12
README.md
@@ -2,6 +2,9 @@
|
|||||||
|
|
||||||
"named this way because i didn't realise there was another libremines!"
|
"named this way because i didn't realise there was another libremines!"
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
## Building
|
## Building
|
||||||
|
|
||||||
### Requirements:
|
### Requirements:
|
||||||
@@ -11,14 +14,13 @@
|
|||||||
|
|
||||||
### Instructions:
|
### Instructions:
|
||||||
|
|
||||||
Optional, create maven wrapper:
|
Create the maven wrapper. gluonfx does not like versions of maven that are not 3.8.8:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
mvn wrapper:wrapper
|
mvn wrapper:wrapper -Dmaven=3.8.8
|
||||||
```
|
```
|
||||||
|
|
||||||
This is helpful for version management, in case you have an incompatible version of maven installed, but most people will not need this.
|
This is helpful for version management, in case you have an incompatible version of maven installed.
|
||||||
|
|
||||||
Install dependencies:
|
Install dependencies:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
@@ -31,4 +33,4 @@ Build and run:
|
|||||||
GRAALVM_HOME=/path/to/graalvm ./mvnw gluonfx:build
|
GRAALVM_HOME=/path/to/graalvm ./mvnw gluonfx:build
|
||||||
```
|
```
|
||||||
|
|
||||||
A native binary should be placed at `target/gluonfx/<your architecture>/libremines`
|
A native binary should be placed at `target/gluonfx/<your architecture>/libremines`
|
||||||
|
@@ -4,9 +4,11 @@ import java.net.URL;
|
|||||||
import java.util.Timer;
|
import java.util.Timer;
|
||||||
import java.util.TimerTask;
|
import java.util.TimerTask;
|
||||||
|
|
||||||
|
import javafx.event.ActionEvent;
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
import javafx.scene.Node;
|
import javafx.scene.Node;
|
||||||
import javafx.scene.control.Button;
|
import javafx.scene.control.Button;
|
||||||
|
import javafx.scene.control.RadioMenuItem;
|
||||||
import javafx.scene.image.Image;
|
import javafx.scene.image.Image;
|
||||||
import javafx.scene.image.ImageView;
|
import javafx.scene.image.ImageView;
|
||||||
import javafx.scene.input.MouseButton;
|
import javafx.scene.input.MouseButton;
|
||||||
@@ -20,6 +22,9 @@ public class Controller {
|
|||||||
@FXML
|
@FXML
|
||||||
private ImageView smiley, time_1, time_2, time_3, bomb_2, bomb_3;
|
private ImageView smiley, time_1, time_2, time_3, bomb_2, bomb_3;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private RadioMenuItem color, marks;
|
||||||
|
|
||||||
private Grid gridHandler;
|
private Grid gridHandler;
|
||||||
private GridWrapper wrapper;
|
private GridWrapper wrapper;
|
||||||
private boolean gameOver = false;
|
private boolean gameOver = false;
|
||||||
@@ -33,12 +38,18 @@ public class Controller {
|
|||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private void initialize() {
|
private void initialize() {
|
||||||
|
setNotYetImplemented(color);
|
||||||
|
setNotYetImplemented(marks);
|
||||||
setupGrid();
|
setupGrid();
|
||||||
gridHandler = new Grid();
|
gridHandler = new Grid();
|
||||||
wrapper = gridHandler.grid;
|
wrapper = gridHandler.grid;
|
||||||
expandedTiles = new boolean[30][16];
|
expandedTiles = new boolean[30][16];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setNotYetImplemented(RadioMenuItem node) {
|
||||||
|
node.setOnAction((ActionEvent e) -> System.out.println("https://http.cat/images/501.jpg"));
|
||||||
|
}
|
||||||
|
|
||||||
private void setupGrid() {
|
private void setupGrid() {
|
||||||
for (int column = 0; column < 30; ++column) {
|
for (int column = 0; column < 30; ++column) {
|
||||||
for (int row = 0; row < 16; ++row) {
|
for (int row = 0; row < 16; ++row) {
|
||||||
@@ -109,6 +120,33 @@ public class Controller {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String getButtonURL(Button button) {
|
||||||
|
ImageView graphic = (ImageView) button.getGraphic();
|
||||||
|
Image image = graphic.getImage();
|
||||||
|
return image.getUrl();
|
||||||
|
}
|
||||||
|
|
||||||
|
private int numberOfUnrevealedTiles() {
|
||||||
|
int unrevealedTiles = 0;
|
||||||
|
int column, row;
|
||||||
|
for (column = 0; column < 30; ++column) {
|
||||||
|
for (row = 0; row < 16; ++row) {
|
||||||
|
Button current = (Button) getNodeByRowColumnIndex(row, column);
|
||||||
|
assert current != null;
|
||||||
|
String currentURL = getButtonURL(current);
|
||||||
|
if (currentURL.contains("blank.png") || currentURL.contains("flag.png")) {
|
||||||
|
unrevealedTiles++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return unrevealedTiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean checkWinCondition() {
|
||||||
|
int unrevealedTiles = numberOfUnrevealedTiles();
|
||||||
|
return unrevealedTiles == 99;
|
||||||
|
}
|
||||||
|
|
||||||
private void handlePrimaryClick(Button clicked, int column, int row) {
|
private void handlePrimaryClick(Button clicked, int column, int row) {
|
||||||
if (wrapper.atColumn(column).atRow(row).isBomb() && !isFirstClick) {
|
if (wrapper.atColumn(column).atRow(row).isBomb() && !isFirstClick) {
|
||||||
gameOver(clicked);
|
gameOver(clicked);
|
||||||
@@ -122,14 +160,18 @@ public class Controller {
|
|||||||
int rowMovedTo = chosenColumnAndRow[1];
|
int rowMovedTo = chosenColumnAndRow[1];
|
||||||
wrapper.atColumn(column).atRow(row).switchBomb(columnMovedTo, rowMovedTo);
|
wrapper.atColumn(column).atRow(row).switchBomb(columnMovedTo, rowMovedTo);
|
||||||
recursiveExpandTiles(column, row);
|
recursiveExpandTiles(column, row);
|
||||||
isFirstClick = false;
|
clicked = (Button) getNodeByRowColumnIndex(row, column);
|
||||||
}
|
}
|
||||||
|
isFirstClick = false;
|
||||||
int adjacentBombs = wrapper.adjacentBombCount();
|
int adjacentBombs = wrapper.adjacentBombCount();
|
||||||
setAdjacentCount(clicked, adjacentBombs);
|
setAdjacentCount(clicked, adjacentBombs);
|
||||||
if (adjacentBombs == 0) {
|
if (adjacentBombs == 0) {
|
||||||
recursiveExpandTiles(column, row);
|
recursiveExpandTiles(column, row);
|
||||||
}
|
}
|
||||||
|
boolean win = checkWinCondition();
|
||||||
|
if (win) {
|
||||||
|
win();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void recursiveExpandTiles(int column, int row) {
|
private void recursiveExpandTiles(int column, int row) {
|
||||||
@@ -213,6 +255,28 @@ public class Controller {
|
|||||||
showAllBombs(GridPane.getColumnIndex(tileClicked), GridPane.getRowIndex(tileClicked));
|
showAllBombs(GridPane.getColumnIndex(tileClicked), GridPane.getRowIndex(tileClicked));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void win() {
|
||||||
|
gameOver = true;
|
||||||
|
timer.cancel();
|
||||||
|
setImage(smiley, "img/face_win.png");
|
||||||
|
flagAllRemaining();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void flagAllRemaining() {
|
||||||
|
int column, row;
|
||||||
|
for (column = 0; column < 30; ++column) {
|
||||||
|
for (row = 0; row < 16; ++row) {
|
||||||
|
Button current = (Button) getNodeByRowColumnIndex(row, column);
|
||||||
|
assert current != null;
|
||||||
|
String currentURL = getButtonURL(current);
|
||||||
|
boolean tileIsBomb = wrapper.atColumn(column).atRow(row).isBomb();
|
||||||
|
if (currentURL.contains("blank.png") && tileIsBomb) {
|
||||||
|
setImage(current, "img/bomb_flagged.png");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void flag(Node tileClicked) {
|
private void flag(Node tileClicked) {
|
||||||
Button tileAsButton = (Button) tileClicked;
|
Button tileAsButton = (Button) tileClicked;
|
||||||
ImageView tileGraphic = (ImageView) tileAsButton.getGraphic();
|
ImageView tileGraphic = (ImageView) tileAsButton.getGraphic();
|
||||||
@@ -229,7 +293,8 @@ public class Controller {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
bombCount--;
|
bombCount--;
|
||||||
updateBombCounter();
|
if (bombCount > 0)
|
||||||
|
updateBombCounter();
|
||||||
setImage((Button) tileClicked, "img/bomb_flagged.png");
|
setImage((Button) tileClicked, "img/bomb_flagged.png");
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -280,8 +345,8 @@ public class Controller {
|
|||||||
String buttonURL = ((ImageView) b.getGraphic()).getImage().getUrl();
|
String buttonURL = ((ImageView) b.getGraphic()).getImage().getUrl();
|
||||||
int column = GridPane.getColumnIndex(node);
|
int column = GridPane.getColumnIndex(node);
|
||||||
int row = GridPane.getRowIndex(node);
|
int row = GridPane.getRowIndex(node);
|
||||||
if (!(column == clickedColumn && row == clickedRow) &&
|
// if the tile isn't the one that was clicked AND the tile is a bomb
|
||||||
wrapper.atColumn(column).atRow(row).isBomb()) {
|
if (!(column == clickedColumn && row == clickedRow) && wrapper.atColumn(column).atRow(row).isBomb()) {
|
||||||
setImage((Button) node, "img/bomb_revealed.png");
|
setImage((Button) node, "img/bomb_revealed.png");
|
||||||
}
|
}
|
||||||
if (buttonURL.contains("flagged.png") && !wrapper.atColumn(column).atRow(row).isBomb()) {
|
if (buttonURL.contains("flagged.png") && !wrapper.atColumn(column).atRow(row).isBomb()) {
|
||||||
|
4
src/main/resources/com/shr4pnel/minesweeper/fix-glow.css
Normal file
4
src/main/resources/com/shr4pnel/minesweeper/fix-glow.css
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
* {
|
||||||
|
-fx-focus-color: transparent;
|
||||||
|
-fx-faint-focus-color: transparent;
|
||||||
|
}
|
@@ -6,7 +6,7 @@
|
|||||||
<?import javafx.scene.layout.*?>
|
<?import javafx.scene.layout.*?>
|
||||||
<?import javafx.scene.shape.*?>
|
<?import javafx.scene.shape.*?>
|
||||||
|
|
||||||
<VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="350.0" prefWidth="500.0" style="-fx-border-color: black; -fx-border-width: 1px;" xmlns="http://javafx.com/javafx/11.0.14-internal" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.shr4pnel.minesweeper.Controller">
|
<VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="350.0" prefWidth="500.0" style="-fx-border-color: black; -fx-border-width: 1px;" stylesheets="@fix-glow.css" xmlns="http://javafx.com/javafx/17.0.2-ea" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.shr4pnel.minesweeper.Controller">
|
||||||
<children>
|
<children>
|
||||||
<MenuBar style="-fx-background-color: white;">
|
<MenuBar style="-fx-background-color: white;">
|
||||||
<menus>
|
<menus>
|
||||||
@@ -26,8 +26,8 @@
|
|||||||
<RadioMenuItem mnemonicParsing="false" text="Internmediate" toggleGroup="$difficulty" />
|
<RadioMenuItem mnemonicParsing="false" text="Internmediate" toggleGroup="$difficulty" />
|
||||||
<RadioMenuItem mnemonicParsing="false" selected="true" text="Expert" toggleGroup="$difficulty" />
|
<RadioMenuItem mnemonicParsing="false" selected="true" text="Expert" toggleGroup="$difficulty" />
|
||||||
<SeparatorMenuItem mnemonicParsing="false" />
|
<SeparatorMenuItem mnemonicParsing="false" />
|
||||||
<RadioMenuItem mnemonicParsing="false" selected="true" text="Marks (?)" />
|
<RadioMenuItem fx:id="marks" mnemonicParsing="false" selected="true" text="Marks (?)" />
|
||||||
<RadioMenuItem mnemonicParsing="false" selected="true" text="Color" />
|
<RadioMenuItem fx:id="color" mnemonicParsing="false" selected="true" text="Color" />
|
||||||
<SeparatorMenuItem mnemonicParsing="false" />
|
<SeparatorMenuItem mnemonicParsing="false" />
|
||||||
<MenuItem mnemonicParsing="false" style="-fx-padding-right: 15; -fx-border-insets: 10px; -fx-background-insets: 10px;" text="Best Times..." />
|
<MenuItem mnemonicParsing="false" style="-fx-padding-right: 15; -fx-border-insets: 10px; -fx-background-insets: 10px;" text="Best Times..." />
|
||||||
<SeparatorMenuItem mnemonicParsing="false" />
|
<SeparatorMenuItem mnemonicParsing="false" />
|
||||||
|
Reference in New Issue
Block a user