save before refactor
This commit is contained in:
6 files changed
+340
-29
No files matched your search
@@ -0,0 +1,77 @@
|
||||
package ca.bcit.comp2522.project;
|
||||
|
||||
public class AscendingPlacement
|
||||
extends PlacementRule
|
||||
{
|
||||
private static final int FIRST = 0;
|
||||
private static final int NEXT = 1;
|
||||
|
||||
@Override
|
||||
public boolean isValidPlacement(int[] positions, int index, int value)
|
||||
{
|
||||
for (int i = 0; i < positions.length; i++)
|
||||
{
|
||||
if (positions[i] == FIRST)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
boolean invalidBefore;
|
||||
boolean invalidAfter;
|
||||
|
||||
invalidBefore = i < index && positions[i] > value;
|
||||
invalidAfter = i > index && positions[i] < value;
|
||||
|
||||
if (invalidBefore || invalidAfter)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canPlaceNext(int[] positions, int nextValue)
|
||||
{
|
||||
for (int i = 0; i < positions.length; i++)
|
||||
{
|
||||
if (positions[i] != FIRST)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
int left;
|
||||
int right;
|
||||
|
||||
left = Integer.MIN_VALUE;
|
||||
right = Integer.MAX_VALUE;
|
||||
|
||||
// scan left
|
||||
for (int l = i - NEXT; l >= FIRST; l--)
|
||||
{
|
||||
if (positions[l] != FIRST)
|
||||
{
|
||||
left = positions[l];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// scan right
|
||||
for (int r = i + NEXT; r < positions.length; r++)
|
||||
{
|
||||
if (positions[r] != FIRST)
|
||||
{
|
||||
right = positions[r];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (left < nextValue && nextValue < right)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,11 @@
|
||||
package ca.bcit.comp2522.project;
|
||||
|
||||
import javafx.animation.Timeline;
|
||||
import javafx.application.Application;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.control.Alert;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.input.MouseButton;
|
||||
@@ -28,7 +30,6 @@ public class Mines extends Application
|
||||
private static final int BUTTON_WIDTH = 60;
|
||||
private static final int BUTTON_HEIGHT = 60;
|
||||
private static final int MENU_BUTTON_WIDTH = 180;
|
||||
private static final int MENU_BUTTON_HEIGHT = 80;
|
||||
private static final int EASY_WIDTH = 8;
|
||||
private static final int EASY_HEIGHT = 8;
|
||||
private static final int HARD_WIDTH = 36;
|
||||
@@ -77,6 +78,37 @@ public class Mines extends Application
|
||||
private int height;
|
||||
private int flags;
|
||||
|
||||
private Label flagLabel;
|
||||
private Label timerLabel;
|
||||
private int totalMines;
|
||||
|
||||
private int seconds;
|
||||
private Timeline timer;
|
||||
private boolean timerRunning = false;
|
||||
private boolean randomMode = false;
|
||||
|
||||
private void startTimer() {
|
||||
seconds = 0;
|
||||
timerLabel.setText("Time: 0");
|
||||
|
||||
timer = new javafx.animation.Timeline(
|
||||
new javafx.animation.KeyFrame(javafx.util.Duration.seconds(1), e -> {
|
||||
seconds++;
|
||||
timerLabel.setText("Time: " + seconds);
|
||||
})
|
||||
);
|
||||
timer.setCycleCount(javafx.animation.Animation.INDEFINITE);
|
||||
timer.play();
|
||||
timerRunning = true;
|
||||
}
|
||||
|
||||
private void stopTimer() {
|
||||
if (timer != null) {
|
||||
timer.stop();
|
||||
}
|
||||
timerRunning = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start(final Stage stage)
|
||||
{
|
||||
@@ -214,30 +246,55 @@ public class Mines extends Application
|
||||
final int height,
|
||||
final int mines
|
||||
) {
|
||||
this.flags = NO_FLAG;
|
||||
this.buttons = new Button[width * height];
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.flags = NO_FLAG;
|
||||
this.buttons = new Button[width * height];
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.totalMines = mines;
|
||||
|
||||
generateField(mines);
|
||||
|
||||
final Stage gameStage;
|
||||
final VBox box;
|
||||
final VBox topBar;
|
||||
final GridPane grid;
|
||||
final Label modeLabel;
|
||||
final Button toggleModeBtn;
|
||||
|
||||
gameStage = new Stage();
|
||||
box = new VBox();
|
||||
grid = createGrid(width, height);
|
||||
gameStage = new Stage();
|
||||
box = new VBox();
|
||||
grid = createGrid(width, height);
|
||||
modeLabel = new Label("Random Mode: OFF");
|
||||
toggleModeBtn = new Button("Toggle Random Mode");
|
||||
|
||||
this.flagLabel = new Label("Flags: 0 / " + totalMines);
|
||||
this.timerLabel = new Label("Time: 0");
|
||||
this.flagLabel.setFont(FONT);
|
||||
this.timerLabel.setFont(FONT);
|
||||
|
||||
toggleModeBtn.setOnAction(e -> {
|
||||
randomMode = !randomMode;
|
||||
modeLabel.setText("Random Mode: " + (randomMode ? "ON" : "OFF"));
|
||||
});
|
||||
|
||||
|
||||
topBar = new VBox(5, flagLabel, timerLabel);
|
||||
|
||||
topBar.setAlignment(Pos.CENTER);
|
||||
box.getChildren().add(0, topBar);
|
||||
|
||||
box.getChildren().add(grid);
|
||||
box.setAlignment(Pos.CENTER);
|
||||
grid.setAlignment(Pos.CENTER);
|
||||
|
||||
final Scene scene;
|
||||
scene = new Scene(box, WINDOW_WIDTH, WINDOW_HEIGHT);
|
||||
root.getChildren().addAll(title, smallBtn, largeBtn, modeLabel, toggleModeBtn);
|
||||
|
||||
gameStage.setScene(scene);
|
||||
gameStage.setTitle("Random Mines " + width + "x" + height);
|
||||
gameStage.show();
|
||||
startTimer();
|
||||
}
|
||||
|
||||
private void flag(final int index)
|
||||
@@ -253,7 +310,49 @@ public class Mines extends Application
|
||||
|
||||
this.flags = this.flagged[index] == FLAG ?
|
||||
this.flags + FLAG :
|
||||
this.flags - FLAG;
|
||||
this.flagged[index] == FLAG_QUESTION ?
|
||||
this.flags - FLAG :
|
||||
this.flags;
|
||||
|
||||
this.flagLabel.setText("Flags: " + flags + " / " + totalMines);
|
||||
}
|
||||
|
||||
private void checkWin()
|
||||
{
|
||||
int numRevealed;
|
||||
numRevealed = NO_MINE;
|
||||
|
||||
for (int i = 0; i < this.field.length; i++)
|
||||
{
|
||||
if (this.revealed[i])
|
||||
{
|
||||
numRevealed++;
|
||||
}
|
||||
else if (this.field[i] != MINE)
|
||||
{
|
||||
// if a non revealed cell is not a mine, we know its not a win
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// do nothing
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (numRevealed == (this.field.length - totalMines))
|
||||
{
|
||||
// WIN CONDITION
|
||||
stopTimer();
|
||||
|
||||
final Alert win;
|
||||
win = new Alert(Alert.AlertType.INFORMATION);
|
||||
win.setHeaderText("You Win!");
|
||||
win.setContentText("You successfully cleared all safe squares!");
|
||||
win.showAndWait();
|
||||
|
||||
((Stage) buttons[0].getScene().getWindow()).close();
|
||||
}
|
||||
}
|
||||
|
||||
private GridPane createGrid(
|
||||
@@ -285,7 +384,26 @@ public class Mines extends Application
|
||||
button.setOnMouseClicked(e -> {
|
||||
if (e.getButton() == MouseButton.PRIMARY)
|
||||
{
|
||||
reveal(index);
|
||||
final boolean lossed;
|
||||
lossed = reveal(index);
|
||||
|
||||
if (lossed)
|
||||
{
|
||||
final Alert loss;
|
||||
loss = new Alert(Alert.AlertType.ERROR);
|
||||
loss.setHeaderText("You lost...");
|
||||
loss.setContentText("Unfortunately, you dug up a mine and lost your legs. I hear there is a deal on wheelchairs though.");
|
||||
loss.showAndWait();
|
||||
|
||||
final Stage gameStage;
|
||||
gameStage = (Stage) buttons[index].getScene().getWindow();
|
||||
gameStage.close();
|
||||
return;
|
||||
}
|
||||
|
||||
checkWin();
|
||||
|
||||
randomizeRemaining();
|
||||
}
|
||||
else if (e.getButton() == MouseButton.SECONDARY)
|
||||
{
|
||||
@@ -306,11 +424,85 @@ public class Mines extends Application
|
||||
return grid;
|
||||
}
|
||||
|
||||
private void reveal(final int index)
|
||||
private void randomizeRemaining()
|
||||
{
|
||||
int regenMine;
|
||||
|
||||
regenMine = NO_MINE;
|
||||
|
||||
for (int i = 0; i < this.field.length; i++)
|
||||
{
|
||||
// Ignore correctly flagged mines
|
||||
if (this.field[i] == MINE && this.flagged[i] == FLAG)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (this.field[i] == MINE)
|
||||
{
|
||||
regenMine++;
|
||||
}
|
||||
|
||||
this.field[i] = NO_MINE;
|
||||
}
|
||||
|
||||
final Random rand;
|
||||
int placed;
|
||||
|
||||
rand = new Random();
|
||||
placed = NO_MINE;
|
||||
|
||||
while (placed < regenMine)
|
||||
{
|
||||
final int index;
|
||||
index = rand.nextInt(width * height);
|
||||
|
||||
if (this.field[index] == NO_MINE && !this.revealed[index])
|
||||
{
|
||||
this.field[index] = MINE;
|
||||
placed++;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < this.field.length; i++)
|
||||
{
|
||||
if (this.field[i] == MINE)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
final int[] count = { NO_MINE };
|
||||
|
||||
forEachNeighbor(i, neighborIndex -> {
|
||||
if (this.field[neighborIndex] == MINE)
|
||||
{
|
||||
count[SELF_OFFSET]++;
|
||||
}
|
||||
});
|
||||
|
||||
this.field[i] = count[SELF_OFFSET];
|
||||
}
|
||||
|
||||
for (int i = 0; i < this.field.length; i++)
|
||||
{
|
||||
if (this.revealed[i])
|
||||
{
|
||||
this.buttons[i].setText(this.field[i] == NO_MINE ? "" : "" + this.field[i]);
|
||||
this.buttons[i].setStyle(BUTTON_THEMES.get(this.field[i]));
|
||||
}
|
||||
|
||||
if (this.revealed[i] && this.field[i] == NO_MINE)
|
||||
{
|
||||
popFieldVoid(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean reveal(final int index)
|
||||
{
|
||||
if (this.revealed[index])
|
||||
{
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
final String buttonText;
|
||||
@@ -333,6 +525,8 @@ public class Mines extends Application
|
||||
{
|
||||
popFieldVoid(index);
|
||||
}
|
||||
|
||||
return this.field[index] == MINE;
|
||||
}
|
||||
|
||||
public static void main(final String[] args)
|
||||
|
||||
@@ -12,9 +12,8 @@ import javafx.scene.control.Label;
|
||||
import javafx.scene.layout.VBox;
|
||||
import javafx.scene.control.Button;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
public class NumberGame extends Application
|
||||
public class NumberGame
|
||||
extends Application
|
||||
{
|
||||
private static final int STARTING_NUMBERS_PLACED = 0;
|
||||
private static final int INDEX_OFFSET = 1;
|
||||
@@ -35,13 +34,15 @@ public class NumberGame extends Application
|
||||
private Label numberLabel;
|
||||
private int currentNumber;
|
||||
private int[] positions;
|
||||
private RandomNumberGenerator generator;
|
||||
|
||||
@Override
|
||||
public void start(final Stage stage)
|
||||
{
|
||||
this.generator = new RandomNumberGenerator(MIN_RAND_NUM, MAX_RAND_NUM);
|
||||
this.numbersPlaced = STARTING_NUMBERS_PLACED;
|
||||
this.currentNumber = generateRandomNumber();
|
||||
this.positions = new int[GRID_WIDTH * GRID_HEIGHT];
|
||||
this.currentNumber = this.generator.generate();
|
||||
this.positions = new int[GRID_WIDTH * GRID_HEIGHT];
|
||||
|
||||
this.numberLabel = new Label("Next number: " + this.currentNumber + " - Select a slot.");
|
||||
this.numberLabel.setFont(FONT);
|
||||
@@ -49,14 +50,14 @@ public class NumberGame extends Application
|
||||
this.numberLabel.setAlignment(Pos.CENTER);
|
||||
|
||||
final VBox root;
|
||||
root = new VBox();
|
||||
root.getChildren().add(this.numberLabel);
|
||||
|
||||
final GridPane grid;
|
||||
final Scene scene;
|
||||
|
||||
root = new VBox();
|
||||
grid = createGrid();
|
||||
root.getChildren().add(this.numberLabel);
|
||||
root.getChildren().add(grid);
|
||||
|
||||
final Scene scene;
|
||||
scene = new Scene(root, WINDOW_WIDTH, WINDOW_HEIGHT);
|
||||
|
||||
stage.setScene(scene);
|
||||
@@ -95,13 +96,6 @@ public class NumberGame extends Application
|
||||
return grid;
|
||||
}
|
||||
|
||||
private int generateRandomNumber()
|
||||
{
|
||||
final Random rand;
|
||||
rand = new Random();
|
||||
return rand.nextInt(MAX_RAND_NUM - MIN_RAND_NUM) + MIN_RAND_NUM;
|
||||
}
|
||||
|
||||
private void triggerFailed()
|
||||
{
|
||||
this.numberLabel.setText("Next number: " + this.currentNumber + " - Impossible to place next number");
|
||||
@@ -181,7 +175,7 @@ public class NumberGame extends Application
|
||||
return;
|
||||
}
|
||||
|
||||
this.currentNumber = generateRandomNumber();
|
||||
this.currentNumber = this.generator.generate();
|
||||
|
||||
final boolean canPlaceNext;
|
||||
canPlaceNext = canBePlaced();
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
package ca.bcit.comp2522.project;
|
||||
|
||||
public interface NumberGenerator
|
||||
{
|
||||
int generate();
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package ca.bcit.comp2522.project;
|
||||
|
||||
public abstract class PlacementRule
|
||||
{
|
||||
public abstract boolean isValidPlacement(
|
||||
final int[] positions,
|
||||
final int index,
|
||||
final int value
|
||||
);
|
||||
|
||||
public abstract boolean canPlaceNext(
|
||||
final int[] positions,
|
||||
final int nextValue
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package ca.bcit.comp2522.project;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
public class RandomNumberGenerator
|
||||
implements NumberGenerator
|
||||
{
|
||||
private final Random random;
|
||||
private final int min;
|
||||
private final int max;
|
||||
|
||||
public RandomNumberGenerator(int min, int max)
|
||||
{
|
||||
random = new Random();
|
||||
|
||||
this.min = min;
|
||||
this.max = max;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int generate()
|
||||
{
|
||||
return random.nextInt(max - min) + min;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user