diff --git a/.gitignore b/.gitignore index db44c8a723e017349e18633821c8ee475d15621c..77935f0f254d4e049c949cbcaa4fd0b3699ef042 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ .settings/ .project .classpath +/game-score.csv diff --git a/src/main/java/lab/GameController.java b/src/main/java/lab/GameController.java index 9d52ea1e382775d3ee6ea3edaa3da27dc2c2ad85..074ac61ef2ad19e63d875971bfcac01c70366f92 100644 --- a/src/main/java/lab/GameController.java +++ b/src/main/java/lab/GameController.java @@ -1,14 +1,32 @@ package lab; +import static java.util.Comparator.comparingInt; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Random; +import java.util.Scanner; +import java.util.Set; + import javafx.animation.AnimationTimer; import javafx.beans.value.ObservableValue; +import javafx.collections.FXCollections; import javafx.fxml.FXML; import javafx.scene.canvas.Canvas; import javafx.scene.control.Label; +import javafx.scene.control.ListView; import javafx.scene.control.Slider; +import javafx.scene.control.TextField; public class GameController { + private static final String FILE_NAME = "game-score.csv"; + private World world; @FXML @@ -26,16 +44,30 @@ public class GameController { @FXML private Label hits; + @FXML + private TextField nameField; + + @FXML + private ListView<Score> scoreList; + + private List<Score> highScores; + + private AnimationTimer animationTimer; + + private final Random rnd = new Random(); + public GameController() { } public void startGame() { + scoreList.setItems(FXCollections.observableList(new ArrayList<>())); + highScores = scoreList.getItems(); this.world = new World(canvas.getWidth(), canvas.getHeight()); this.world.setGameListener(new GameListenerImpl()); //Draw scene on a separate thread to avoid blocking UI. - animationTimer = new DrawingThread(canvas, world); + animationTimer = new DrawingThread(canvas, world); angleSlider.valueProperty().addListener(this::angleChanged); world.setCannonAngle(angleSlider.getValue()); @@ -55,6 +87,55 @@ public class GameController { world.fire(); } + @FXML + private void gameOver() { + int score = rnd.nextInt(11); + String name = nameField.getText(); + highScores.add(new Score(name, score)); + //highScores.sort((o1, o2)->Integer.compare(o1.getScore(), o2.getScore())); + highScores.sort(comparingInt(Score::getScore).reversed()); + } + + @FXML + private void highScore() { + Set<Score> tempSet = new LinkedHashSet<>(); + tempSet.addAll(highScores); + highScores.clear(); + highScores.addAll(tempSet); + } + + @FXML + private void save() { + try(PrintWriter pw = new PrintWriter(new FileWriter(FILE_NAME))) { + for (Score score: highScores) { + pw.printf("%s;%d\n", score.getName(), score.getScore()); + } + + /* + Iterator<Score> iterator = highScores.iterator(); + while(iterator.hasNext()) { + Score score = iterator.next(); + pw.printf("%s;%d\n", score.getName(), score.getScore()); + //iterator.remove(); + }*/ + } catch (IOException e) { + e.printStackTrace(); + } + } + + @FXML + private void load() { + highScores.clear(); + try(Scanner scanner = new Scanner(new File(FILE_NAME)).useDelimiter(";\\n")) { + while(scanner.hasNext()) { + String name = scanner.next(); + int score = scanner.nextInt(); + highScores.add(new Score(name, score)); + } + } catch (IOException e) { + e.printStackTrace(); + } + } private void angleChanged(ObservableValue<? extends Number> observable , Number oldValue, Number newValue) { diff --git a/src/main/java/lab/Score.java b/src/main/java/lab/Score.java new file mode 100644 index 0000000000000000000000000000000000000000..8e14b9007e9f0aea028c69746e262916bf19237c --- /dev/null +++ b/src/main/java/lab/Score.java @@ -0,0 +1,38 @@ +package lab; + +public class Score { + + private final String name; + private final int score; + public Score(String name, int score) { + this.name = name; + this.score = score; + } + + public String getName() { + return name; + } + + public int getScore() { + return score; + } + + @Override + public String toString() { + return name + ": " + score; + } + + + @Override + public boolean equals(Object obj) { + if (obj instanceof Score other) { + return this.name.equals(other.name); + } + return false; + } + + @Override + public int hashCode() { + return name.hashCode(); + } +} diff --git a/src/main/resources/lab/GameView.fxml b/src/main/resources/lab/GameView.fxml index e0732c4641c1ecbf46598064b90e1aa66c27711e..7d71efbd33b11b63049aab1d2b07db1741325fe6 100644 --- a/src/main/resources/lab/GameView.fxml +++ b/src/main/resources/lab/GameView.fxml @@ -5,14 +5,17 @@ <?import javafx.scene.canvas.Canvas?> <?import javafx.scene.control.Button?> <?import javafx.scene.control.Label?> +<?import javafx.scene.control.ListView?> <?import javafx.scene.control.Slider?> +<?import javafx.scene.control.TextField?> <?import javafx.scene.layout.BorderPane?> <?import javafx.scene.layout.ColumnConstraints?> <?import javafx.scene.layout.GridPane?> <?import javafx.scene.layout.HBox?> <?import javafx.scene.layout.RowConstraints?> +<?import javafx.scene.layout.VBox?> -<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1" fx:controller="lab.GameController"> +<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" xmlns="http://javafx.com/javafx/18" xmlns:fx="http://javafx.com/fxml/1" fx:controller="lab.GameController"> <bottom> <HBox alignment="CENTER" BorderPane.alignment="CENTER_LEFT"> <children> @@ -41,11 +44,25 @@ <Label text="Shoots:" /> <Label fx:id="shoots" text="0" GridPane.columnIndex="1" /> <Label text="Hits:" GridPane.rowIndex="1" /> - <Label fx:id="hits" text="0" GridPane.rowIndex="1" GridPane.columnIndex="1" /> + <Label fx:id="hits" text="0" GridPane.columnIndex="1" GridPane.rowIndex="1" /> </children> </GridPane> <Canvas fx:id="canvas" height="400.0" width="600.0" /> </children> </Group> </center> + <left> + <VBox prefWidth="100.0" BorderPane.alignment="CENTER"> + <children> + <TextField fx:id="nameField" /> + <Button mnemonicParsing="false" onAction="#gameOver" prefWidth="100.0" text="Game Over" /> + <Button mnemonicParsing="false" onAction="#highScore" prefWidth="100.0" text="High Score" /> + <Button mnemonicParsing="false" onAction="#save" prefWidth="100.0" text="Save" /> + <Button mnemonicParsing="false" onAction="#load" prefWidth="100.0" text="Load" /> + </children> + </VBox> + </left> + <right> + <ListView fx:id="scoreList" prefWidth="200.0" BorderPane.alignment="CENTER" /> + </right> </BorderPane>