save before refactor

This commit is contained in:
SowinskiBraeden committed 2025-11-26 15:46:22 -08:00
1 parent 67fdd1c8c8
commit d5692ab1e9
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;
}
}
+206 -12
View File
@@ -1,9 +1,11 @@
package ca.bcit.comp2522.project; package ca.bcit.comp2522.project;
import javafx.animation.Timeline;
import javafx.application.Application; import javafx.application.Application;
import javafx.geometry.Insets; import javafx.geometry.Insets;
import javafx.geometry.Pos; import javafx.geometry.Pos;
import javafx.scene.Scene; import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Button; import javafx.scene.control.Button;
import javafx.scene.control.Label; import javafx.scene.control.Label;
import javafx.scene.input.MouseButton; 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_WIDTH = 60;
private static final int BUTTON_HEIGHT = 60; private static final int BUTTON_HEIGHT = 60;
private static final int MENU_BUTTON_WIDTH = 180; 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_WIDTH = 8;
private static final int EASY_HEIGHT = 8; private static final int EASY_HEIGHT = 8;
private static final int HARD_WIDTH = 36; private static final int HARD_WIDTH = 36;
@@ -77,6 +78,37 @@ public class Mines extends Application
private int height; private int height;
private int flags; 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 @Override
public void start(final Stage stage) public void start(final Stage stage)
{ {
@@ -214,30 +246,55 @@ public class Mines extends Application
final int height, final int height,
final int mines final int mines
) { ) {
this.flags = NO_FLAG; this.flags = NO_FLAG;
this.buttons = new Button[width * height]; this.buttons = new Button[width * height];
this.width = width; this.width = width;
this.height = height; this.height = height;
this.totalMines = mines;
generateField(mines); generateField(mines);
final Stage gameStage; final Stage gameStage;
final VBox box; final VBox box;
final VBox topBar;
final GridPane grid; final GridPane grid;
final Label modeLabel;
final Button toggleModeBtn;
gameStage = new Stage(); gameStage = new Stage();
box = new VBox(); box = new VBox();
grid = createGrid(width, height); 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.getChildren().add(grid);
box.setAlignment(Pos.CENTER); box.setAlignment(Pos.CENTER);
grid.setAlignment(Pos.CENTER);
final Scene scene; final Scene scene;
scene = new Scene(box, WINDOW_WIDTH, WINDOW_HEIGHT); scene = new Scene(box, WINDOW_WIDTH, WINDOW_HEIGHT);
root.getChildren().addAll(title, smallBtn, largeBtn, modeLabel, toggleModeBtn);
gameStage.setScene(scene); gameStage.setScene(scene);
gameStage.setTitle("Random Mines " + width + "x" + height); gameStage.setTitle("Random Mines " + width + "x" + height);
gameStage.show(); gameStage.show();
startTimer();
} }
private void flag(final int index) private void flag(final int index)
@@ -253,7 +310,49 @@ public class Mines extends Application
this.flags = this.flagged[index] == FLAG ? this.flags = this.flagged[index] == FLAG ?
this.flags + 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( private GridPane createGrid(
@@ -285,7 +384,26 @@ public class Mines extends Application
button.setOnMouseClicked(e -> { button.setOnMouseClicked(e -> {
if (e.getButton() == MouseButton.PRIMARY) 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) else if (e.getButton() == MouseButton.SECONDARY)
{ {
@@ -306,11 +424,85 @@ public class Mines extends Application
return grid; 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]) if (this.revealed[index])
{ {
return; return false;
} }
final String buttonText; final String buttonText;
@@ -333,6 +525,8 @@ public class Mines extends Application
{ {
popFieldVoid(index); popFieldVoid(index);
} }
return this.field[index] == MINE;
} }
public static void main(final String[] args) public static void main(final String[] args)
@@ -12,9 +12,8 @@ import javafx.scene.control.Label;
import javafx.scene.layout.VBox; import javafx.scene.layout.VBox;
import javafx.scene.control.Button; 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 STARTING_NUMBERS_PLACED = 0;
private static final int INDEX_OFFSET = 1; private static final int INDEX_OFFSET = 1;
@@ -35,13 +34,15 @@ public class NumberGame extends Application
private Label numberLabel; private Label numberLabel;
private int currentNumber; private int currentNumber;
private int[] positions; private int[] positions;
private RandomNumberGenerator generator;
@Override @Override
public void start(final Stage stage) public void start(final Stage stage)
{ {
this.generator = new RandomNumberGenerator(MIN_RAND_NUM, MAX_RAND_NUM);
this.numbersPlaced = STARTING_NUMBERS_PLACED; this.numbersPlaced = STARTING_NUMBERS_PLACED;
this.currentNumber = generateRandomNumber(); this.currentNumber = this.generator.generate();
this.positions = new int[GRID_WIDTH * GRID_HEIGHT]; this.positions = new int[GRID_WIDTH * GRID_HEIGHT];
this.numberLabel = new Label("Next number: " + this.currentNumber + " - Select a slot."); this.numberLabel = new Label("Next number: " + this.currentNumber + " - Select a slot.");
this.numberLabel.setFont(FONT); this.numberLabel.setFont(FONT);
@@ -49,14 +50,14 @@ public class NumberGame extends Application
this.numberLabel.setAlignment(Pos.CENTER); this.numberLabel.setAlignment(Pos.CENTER);
final VBox root; final VBox root;
root = new VBox();
root.getChildren().add(this.numberLabel);
final GridPane grid; final GridPane grid;
final Scene scene;
root = new VBox();
grid = createGrid(); grid = createGrid();
root.getChildren().add(this.numberLabel);
root.getChildren().add(grid); root.getChildren().add(grid);
final Scene scene;
scene = new Scene(root, WINDOW_WIDTH, WINDOW_HEIGHT); scene = new Scene(root, WINDOW_WIDTH, WINDOW_HEIGHT);
stage.setScene(scene); stage.setScene(scene);
@@ -95,13 +96,6 @@ public class NumberGame extends Application
return grid; 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() private void triggerFailed()
{ {
this.numberLabel.setText("Next number: " + this.currentNumber + " - Impossible to place next number"); this.numberLabel.setText("Next number: " + this.currentNumber + " - Impossible to place next number");
@@ -181,7 +175,7 @@ public class NumberGame extends Application
return; return;
} }
this.currentNumber = generateRandomNumber(); this.currentNumber = this.generator.generate();
final boolean canPlaceNext; final boolean canPlaceNext;
canPlaceNext = canBePlaced(); 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;
}
}