Skip to content
Snippets Groups Projects
Commit 262bcd35 authored by COUETOUX Basile's avatar COUETOUX Basile
Browse files

Merge branch 'simple' into 'main'

Simple

See merge request couetoux.b/firefighterstarter!2
parents e8ca8aa1 588a2b48
No related branches found
No related tags found
1 merge request!2Simple
Pipeline #38047 passed
Showing
with 625 additions and 262 deletions
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RemoteRepositoriesConfiguration">
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Maven Central repository" />
<option name="url" value="https://repo1.maven.org/maven2" />
</remote-repository>
<remote-repository>
<option name="id" value="jboss.community" />
<option name="name" value="JBoss Community repository" />
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
</remote-repository>
<remote-repository>
<option name="id" value="MavenRepo" />
<option name="name" value="MavenRepo" />
<option name="url" value="https://repo.maven.apache.org/maven2/" />
</remote-repository>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="FrameworkDetectionExcludesConfiguration">
<file type="web" url="file://$PROJECT_DIR$" />
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_16" default="true" project-jdk-name="corretto-16" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>
\ No newline at end of file
plugins { plugins {
id("com.github.johnrengelman.shadow") version "8.1.1"
id 'application' id 'application'
id "org.openjfx.javafxplugin" version "0.0.10" id 'java'
id "org.openjfx.javafxplugin" version "0.1.0"
} }
javafx { javafx {
version = "17" version = "21"
modules = [ 'javafx.controls', 'javafx.fxml' ] modules = [ 'javafx.controls', 'javafx.fxml', 'javafx.graphics']
} }
repositories { repositories {
mavenCentral() mavenCentral()
} }
dependencies { dependencies {
testImplementation group: 'junit', name: 'junit', version: '4.12' testRuntimeOnly("org.junit.platform:junit-platform-launcher")
testImplementation 'org.hamcrest:hamcrest-library:1.3' testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine")
testImplementation("org.assertj:assertj-core:3.24.2")
testImplementation("org.junit.jupiter:junit-jupiter:5.10.0")
} }
mainClassName = "App"
test { test {
useJUnitPlatform() useJUnitPlatform()
} }
application {
mainClass.set("app.SimulatorMain")
}
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
rootProject.name = 'ff' rootProject.name = 'firefighter'
include 'src:main:aapp'
findProject(':src:main:aapp')?.name = 'aapp'
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import static java.lang.Thread.sleep;
public class App extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) throws InterruptedException {
Group root = new Group();
Button restart = new Button("Restart");
VBox buttons = new VBox();
HBox total = new HBox();
Grid grid = new Grid(1000,1000,20,20);
root.getChildren().add(total);
total.getChildren().add(buttons);
total.getChildren().add(grid);
buttons.getChildren().add(restart);
restart.setOnMouseClicked(grid::restart);
primaryStage.setScene(new Scene(root));
primaryStage.show();
grid.repaint();
new Thread(new Runnable() {
@Override
public void run() {
while(true){
try {
sleep(50);
grid.model.activation();
grid.repaint();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
}
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Color;
public class Grid extends Canvas{
int width, height, colCount, rowCount;
Model model;
public Grid(int width, int height, int colCount, int rowCount) {
super(width,height);
this.width = width;
this.height = height;
this.colCount = colCount;
this.rowCount = rowCount;
setFocusTraversable(true);
setOnMousePressed(this::mousePressed);
model = new Model(this);
model.initialisation(3,8);
}
public void restart(MouseEvent mouseEvent){
model = new Model(this);
model.initialisation(3,6);
getGraphicsContext2D().clearRect(0,0,width,height);
repaint();
}
private void mousePressed(MouseEvent mouseEvent) {
model.activation();
repaint();
/*double x = mouseEvent.getX();
double y = mouseEvent.getY();
model.click((int)x*rowCount/height,(int)y*colCount/width);*/
}
void repaint(){
for(int col=0; col<colCount; col++)
getGraphicsContext2D().strokeLine(0, col*width/colCount,height, col*width/colCount);
for(int row=0; row<rowCount;row++)
getGraphicsContext2D().strokeLine(row*height/rowCount,0,row*height/rowCount,width);
}
void paint(int row, int col){
getGraphicsContext2D().setFill(Color.WHITE);
getGraphicsContext2D().fillRect(row*height/rowCount,col*width/colCount,height/rowCount,width/colCount);
}
public void paintFF(int row, int col) {
getGraphicsContext2D().setFill(Color.BLUE);
getGraphicsContext2D().fillRect(row*height/rowCount,col*width/colCount,height/rowCount,width/colCount);
}
public void paintFire(int row, int col) {
getGraphicsContext2D().setFill(Color.RED);
getGraphicsContext2D().fillRect(row*height/rowCount,col*width/colCount,height/rowCount,width/colCount);
}
}
\ No newline at end of file
import java.util.*;
public class Model {
Grid grid;
int colCount, rowCount;
List<Position> firefighters = new ArrayList<>();
Set<Position> fires = new HashSet<>();
List<Position> ffNewPositions;
int step = 0;
public Model(Grid grid) {
this.grid = grid;
colCount = grid.colCount;
rowCount = grid.rowCount;
}
public void initialisation(int fireNumber, int fireFighterNumber){
for(int index=0; index<fireNumber;index++)
fires.add(randomPosition());
for(int index=0; index<fireFighterNumber;index++)
firefighters.add(randomPosition());
}
private Position randomPosition() {
return new Position((int) (Math.random()*rowCount), (int) (Math.random()*colCount));
}
public void activation(){
ffNewPositions = new ArrayList<>();
for(Position ff : firefighters){
Position newPosition = activateFirefighter(ff);
grid.paint(ff.row,ff.col);
grid.paintFF(newPosition.row, newPosition.col);
ffNewPositions.add(newPosition);
}
firefighters = ffNewPositions;
if(step%2==0){
List<Position> newFires = new ArrayList<>();
for(Position fire : fires){
newFires.addAll(activateFire(fire));
}
for(Position newFire : newFires)
grid.paintFire(newFire.row, newFire.col);
fires.addAll(newFires);}
step++;
}
private List<Position> activateFire(Position position) {
return next(position);
}
private Position activateFirefighter(Position position) {
Position randomPosition = aStepTowardFire(position);
//next(position).get((int) (Math.random()*next(position).size()));
List<Position> nextFires = next(randomPosition).stream().filter(fires::contains).toList();
extinguish(randomPosition);
for (Position fire : nextFires)
extinguish(fire);
return randomPosition;
}
private void extinguish(Position position) {
fires.remove(position);
grid.paint(position.row, position.col);
}
private List<Position> next(Position position){
List<Position> list = new ArrayList<>();
if(position.row>0) list.add(new Position(position.row-1, position.col));
if(position.col>0) list.add(new Position(position.row, position.col-1));
if(position.row<rowCount-1) list.add(new Position(position.row+1, position.col));
if(position.col<colCount-1) list.add(new Position(position.row, position.col+1));
return list;
}
private Position aStepTowardFire(Position position){
Queue<Position> toVisit = new LinkedList<>();
Set<Position> seen = new HashSet<>();
HashMap<Position,Position> firstMove = new HashMap<>();
toVisit.addAll(next(position));
for(Position initialMove : toVisit)
firstMove.put(initialMove,initialMove);
while(!toVisit.isEmpty()){
Position current = toVisit.poll();
if(fires.contains(current))
return firstMove.get(current);
for(Position adjacent : next(current)){
if(seen.contains(adjacent)) continue;
toVisit.add(adjacent);
seen.add(adjacent);
firstMove.put(adjacent, firstMove.get(current));
}
}
return position;
}
public record Position(int row, int col){}
}
\ No newline at end of file
package app;
import controller.Controller;
import javafx.application.Platform;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import java.io.IOException;
import java.net.URL;
public class SimulatorApplication extends javafx.application.Application {
private static final String VIEW_RESOURCE_PATH = "/view/view.fxml";
private static final String APP_NAME = "Firefighter simulator";
private static final int ROW_COUNT = 20;
private static final int COLUMN_COUNT = 20;
private static final int BOX_WIDTH = 50;
private static final int BOX_HEIGHT = 50;
public static final int INITIAL_FIRE_COUNT = 3;
public static final int INITIAL_FIREFIGHTER_COUNT = 6;
private Stage primaryStage;
private Parent view;
private void initializePrimaryStage(Stage primaryStage) {
this.primaryStage = primaryStage;
this.primaryStage.setTitle(APP_NAME);
this.primaryStage.setOnCloseRequest(event -> Platform.exit());
this.primaryStage.setResizable(true);
this.primaryStage.sizeToScene();
}
@Override
public void start(Stage primaryStage) throws IOException {
initializePrimaryStage(primaryStage);
initializeView();
showScene();
}
private void initializeView() throws IOException {
FXMLLoader loader = new FXMLLoader();
URL location = SimulatorApplication.class.getResource(VIEW_RESOURCE_PATH);
loader.setLocation(location);
view = loader.load();
Controller controller = loader.getController();
controller.initialize(BOX_WIDTH, BOX_HEIGHT, COLUMN_COUNT, ROW_COUNT,
INITIAL_FIRE_COUNT, INITIAL_FIREFIGHTER_COUNT);
}
private void showScene() {
Scene scene = new Scene(view);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
package app;
public class SimulatorMain {
public static void main(String[] args){
SimulatorApplication.main(args);
}
}
package controller;
import javafx.animation.Animation;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ToggleButton;
import javafx.scene.control.ToggleGroup;
import javafx.util.Duration;
import javafx.util.Pair;
import model.Board;
import model.ModelElement;
import model.FirefighterBoard;
import util.Position;
import view.Grid;
import view.ViewElement;
import java.util.ArrayList;
import java.util.List;
import static java.util.Objects.requireNonNull;
public class Controller {
public static final int PERIOD_IN_MILLISECONDS = 50;
@FXML
public Button restartButton;
@FXML
public Button oneStepButton;
@FXML
public Label generationNumberLabel;
@FXML
private ToggleButton pauseToggleButton;
@FXML
private ToggleButton playToggleButton;
@FXML
private Grid<ViewElement> grid;
private Timeline timeline;
private Board<List<ModelElement>> board;
@FXML
private void initialize() {
initializePlayAndPauseToggleButtons();
initializeTimeline();
}
private void initializePlayAndPauseToggleButtons() {
ToggleGroup toggleGroup = new PersistentToggleGroup();
toggleGroup.getToggles().addAll(playToggleButton, pauseToggleButton);
pauseToggleButton.setSelected(true);
}
private void setModel(FirefighterBoard firefighterBoard) {
this.board = requireNonNull(firefighterBoard, "firefighter.model is null");
}
private void updateBoard(){
List<Position> updatedPositions = board.updateToNextGeneration();
List<Pair<Position, ViewElement>> updatedSquares = new ArrayList<>();
for(Position updatedPosition : updatedPositions){
List<ModelElement> squareState = board.getState(updatedPosition);
ViewElement viewElement = getViewElement(squareState);
updatedSquares.add(new Pair<>(updatedPosition, viewElement));
}
grid.repaint(updatedSquares);
updateGenerationLabel(board.stepNumber());
}
private void repaintGrid(){
int columnCount = board.columnCount();
int rowCount = board.rowCount();
ViewElement[][] viewElements = new ViewElement[rowCount][columnCount];
for(int column = 0; column < columnCount; column++)
for(int row = 0; row < rowCount; row++)
viewElements[row][column] = getViewElement(board.getState(new Position(row, column)));
grid.repaint(viewElements);
updateGenerationLabel(board.stepNumber());
}
private ViewElement getViewElement(List<ModelElement> squareState) {
if(squareState.contains(ModelElement.FIREFIGHTER)){
return ViewElement.FIREFIGHTER;
}
if (squareState.contains(ModelElement.FIRE)){
return ViewElement.FIRE;
}
return ViewElement.EMPTY;
}
private void initializeTimeline() {
Duration duration = new Duration(Controller.PERIOD_IN_MILLISECONDS);
EventHandler<ActionEvent> eventHandler =
event -> updateBoard();
KeyFrame keyFrame = new KeyFrame(duration, eventHandler);
timeline = new Timeline(keyFrame);
timeline.setCycleCount(Animation.INDEFINITE);
}
public void play() {
timeline.play();
}
public void pause() {
timeline.pause();
}
public void pauseToggleButtonAction() {
this.pause();
}
public void playToggleButtonAction() {
this.play();
}
public void restartButtonAction() {
this.pause();
board.reset();
pauseToggleButton.setSelected(true);
repaintGrid();
}
public void initialize(int squareWidth, int squareHeight, int columnCount,
int rowCount, int initialFireCount, int initialFirefighterCount) {
grid.setDimensions(columnCount, rowCount, squareWidth, squareHeight);
this.setModel(new FirefighterBoard(columnCount, rowCount, initialFireCount, initialFirefighterCount));
repaintGrid();
}
public void oneStepButtonAction() {
this.pause();
updateBoard();
}
private void updateGenerationLabel(int value){
generationNumberLabel.setText(Integer.toString(value));
}
}
\ No newline at end of file
package controller;
import javafx.collections.ListChangeListener.Change;
import javafx.scene.control.Toggle;
import javafx.scene.control.ToggleButton;
import javafx.scene.control.ToggleGroup;
import javafx.scene.input.MouseEvent;
/**
* An extension of {@link ToggleGroup} that ensures that a {@link Toggle} in a group must always be
* selected.
*
*/
class PersistentToggleGroup extends ToggleGroup {
/**
* Creates a new {@code PersistentToggleGroup}.
*/
PersistentToggleGroup() {
getToggles().addListener((Change<? extends Toggle> change) -> {
while (change.next()) {
for (Toggle toggle : change.getAddedSubList()) {
ToggleButton toggleButton = (ToggleButton) toggle;
toggleButton.addEventFilter(MouseEvent.MOUSE_RELEASED, mouseEvent -> {
if (toggleButton.equals(getSelectedToggle())) {
mouseEvent.consume();
}
});
}
}
});
}
}
package model;
import util.Position;
import java.util.List;
/**
* This interface represents a generic board for modeling various state-based systems.
*
* @param <S> The type of state represented on the board.
*/
public interface Board<S> {
/**
* Get the state of the board at a specific position.
*
* @param position The position on the board for which to retrieve the state.
* @return The state at the specified position.
*/
S getState(Position position);
/**
* Set the state of a specific position on the board to the specified state.
*
* @param state The state to set for the given position.
* @param position The position on the board for which to set the state.
*/
void setState(S state, Position position);
/**
* Get the number of rows in the board.
*
* @return The number of rows in the board.
*/
int rowCount();
/**
* Get the number of columns in the board.
*
* @return The number of columns in the board.
*/
int columnCount();
/**
* Update the board to its next generation or state. This method may modify the
* internal state of the board and return a list of positions that have changed
* during the update.
*
* @return A list of positions that have changed during the update.
*/
List<Position> updateToNextGeneration();
/**
* Reset the board to its initial state.
*/
void reset();
/**
* Get the current step number or generation of the board.
*
* @return The current step number or generation.
*/
int stepNumber();
}
package model;
import util.Position;
import java.util.*;
public class FirefighterBoard implements Board<List<ModelElement>> {
private final int columnCount;
private final int rowCount;
private final int initialFireCount;
private final int initialFirefighterCount;
private final TargetStrategy targetStrategy = new TargetStrategy();
private List<Position> firefighterPositions;
private Set<Position> firePositions;
private Map<Position, List<Position>> neighbors = new HashMap();
private final Position[][] positions;
private int step = 0;
private final Random randomGenerator = new Random();
public FirefighterBoard(int columnCount, int rowCount, int initialFireCount, int initialFirefighterCount) {
this.columnCount = columnCount;
this.rowCount = rowCount;
this.positions = new Position[rowCount][columnCount];
for (int column = 0; column < columnCount; column++)
for (int row = 0; row < rowCount; row++)
positions[row][column] = new Position(row, column);
for (int column = 0; column < columnCount; column++)
for (int row = 0; row < rowCount; row++) {
List<Position> list = new ArrayList<>();
if (row > 0) list.add(positions[row - 1][column]);
if (column > 0) list.add(positions[row][column - 1]);
if (row < rowCount - 1) list.add(positions[row + 1][column]);
if (column < columnCount - 1) list.add(positions[row][column + 1]);
neighbors.put(positions[row][column], list);
}
this.initialFireCount = initialFireCount;
this.initialFirefighterCount = initialFirefighterCount;
initializeElements();
}
public void initializeElements() {
firefighterPositions = new ArrayList<>();
firePositions = new HashSet<>();
for (int index = 0; index < initialFireCount; index++)
firePositions.add(randomPosition());
for (int index = 0; index < initialFirefighterCount; index++)
firefighterPositions.add(randomPosition());
}
private Position randomPosition() {
return new Position(randomGenerator.nextInt(rowCount), randomGenerator.nextInt(columnCount));
}
@Override
public List<ModelElement> getState(Position position) {
List<ModelElement> result = new ArrayList<>();
for (Position firefighterPosition : firefighterPositions)
if (firefighterPosition.equals(position))
result.add(ModelElement.FIREFIGHTER);
if (firePositions.contains(position))
result.add(ModelElement.FIRE);
return result;
}
@Override
public int rowCount() {
return rowCount;
}
@Override
public int columnCount() {
return columnCount;
}
public List<Position> updateToNextGeneration() {
List<Position> modifiedPositions = updateFirefighters();
modifiedPositions.addAll(updateFires());
step++;
return modifiedPositions;
}
private List<Position> updateFires() {
List<Position> modifiedPositions = new ArrayList<>();
if (step % 2 == 0) {
List<Position> newFirePositions = new ArrayList<>();
for (Position fire : firePositions) {
newFirePositions.addAll(neighbors.get(fire));
}
firePositions.addAll(newFirePositions);
modifiedPositions.addAll(newFirePositions);
}
return modifiedPositions;
}
@Override
public int stepNumber() {
return step;
}
private List<Position> updateFirefighters() {
List<Position> modifiedPosition = new ArrayList<>();
List<Position> firefighterNewPositions = new ArrayList<>();
for (Position firefighterPosition : firefighterPositions) {
Position newFirefighterPosition =
targetStrategy.neighborClosestToFire(firefighterPosition,
firePositions, neighbors);
firefighterNewPositions.add(newFirefighterPosition);
extinguish(newFirefighterPosition);
modifiedPosition.add(firefighterPosition);
modifiedPosition.add(newFirefighterPosition);
List<Position> neighborFirePositions = neighbors.get(newFirefighterPosition).stream()
.filter(firePositions::contains).toList();
for (Position firePosition : neighborFirePositions)
extinguish(firePosition);
modifiedPosition.addAll(neighborFirePositions);
}
firefighterPositions = firefighterNewPositions;
return modifiedPosition;
}
@Override
public void reset() {
step = 0;
initializeElements();
}
private void extinguish(Position position) {
firePositions.remove(position);
}
@Override
public void setState(List<ModelElement> state, Position position) {
firePositions.remove(position);
for (; ; ) {
if (!firefighterPositions.remove(position)) break;
}
for (ModelElement element : state) {
switch (element) {
case FIRE -> firePositions.add(position);
case FIREFIGHTER -> firefighterPositions.add(position);
}
}
}
}
\ No newline at end of file
package model;
public enum ModelElement {
FIREFIGHTER, FIRE
}
module firefighter {
requires javafx.controls;
requires javafx.fxml;
requires javafx.graphics;
opens controller to javafx.fxml;
exports app;
opens app to javafx.fxml;
}
package util;
public record Position(int row, int column) {
}
package model;
import util.Position;
import java.util.*;
public class TargetStrategy {
/**
* @param position current position.
* @param targets positions that are targeted.
* @return the position next to the current position that is on the path to the closest target.
*/
Position neighborClosestToFire(Position position, Collection<Position> targets,
Map<Position,List<Position>>neighbors) {
Set<Position> seen = new HashSet<Position>();
HashMap<Position, Position> firstMove = new HashMap<Position, Position>();
Queue<Position> toVisit = new LinkedList<Position>(neighbors.get(position));
for (Position initialMove : toVisit)
firstMove.put(initialMove, initialMove);
while (!toVisit.isEmpty()) {
Position current = toVisit.poll();
if (targets.contains(current))
return firstMove.get(current);
for (Position adjacent : neighbors.get(current)) {
if (seen.contains(adjacent)) continue;
toVisit.add(adjacent);
seen.add(adjacent);
firstMove.put(adjacent, firstMove.get(current));
}
}
return position;
}
}
\ No newline at end of file
package view;
import javafx.scene.canvas.Canvas;
import javafx.scene.paint.Color;
import javafx.util.Pair;
import util.Position;
import java.util.List;
public class FirefighterGrid extends Canvas implements Grid<ViewElement>{
private void paintElementAtPosition(ViewElement element, Position position) {
paintBox(position.row(), position.column(), element.color);
}
private int boxWidth;
private int boxHeight;
private int columnCount;
private int rowCount;
@Override
public void repaint(List<Pair<Position, ViewElement>> positionedElements) {
clear(positionedElements);
paint(positionedElements);
paintLines();
}
private void clear(List<Pair<Position, ViewElement>> positionedElements) {
for (Pair<Position, ViewElement> positionElement : positionedElements) {
Position position = positionElement.getKey();
clearBox(position.row(), position.column());
}
}
private void paint(List<Pair<Position, ViewElement>> positionedElements) {
for(Pair<Position, ViewElement> pair : positionedElements){
paintElementAtPosition(pair.getValue(), pair.getKey());
}
}
@Override
public void repaint(ViewElement[][] elements) {
clear();
paint(elements);
paintLines();
}
private void clear() {
getGraphicsContext2D().clearRect(0,0,getWidth(), getHeight());
}
private void paint(ViewElement[][] elements) {
for(int column = 0; column < columnCount; column++)
for(int row = 0; row < rowCount; row++){
paintElementAtPosition(elements[row][column], new Position(row, column));
}
}
public int columnCount() {
return columnCount;
}
public int rowCount() {
return rowCount;
}
@Override
public void setDimensions(int columnCount, int rowCount, int boxWidth, int boxHeight) {
this.boxWidth = boxWidth;
this.boxHeight = boxHeight;
this.columnCount = columnCount;
this.rowCount = rowCount;
super.setWidth(boxWidth * columnCount);
super.setHeight(boxHeight * rowCount);
}
private void paintLines(){
paintHorizontalLines();
paintVerticalLines();
}
private void paintVerticalLines() {
for(int column = 0; column < columnCount; column++)
getGraphicsContext2D().strokeLine(column * boxWidth, 0,column * boxWidth, getHeight());
}
private void paintHorizontalLines() {
for(int row = 0; row < rowCount; row++)
getGraphicsContext2D().strokeLine(0, row * boxHeight, getWidth(), row * boxHeight);
}
private void paintBox(int row, int column, Color color){
getGraphicsContext2D().setFill(color);
getGraphicsContext2D().fillRect(column * boxWidth,row * boxHeight, boxWidth, boxHeight);
}
private void clearBox(int row, int column){
getGraphicsContext2D().clearRect(column * boxWidth,row * boxHeight, boxWidth, boxHeight);
}
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment