Compare commits

...

7 Commits

Author SHA1 Message Date
Jonathan Turner
6b88415ac2 Implemented functionality to convert BoardNode to Treeitem for displaying iterations. 2024-02-11 04:08:58 -05:00
Jonathan Turner
c944ce121a Implemented Code Behind and VM file. 2024-02-11 03:39:09 -05:00
Jonathan Turner
1e554fbdb0 Added an interface to allow for simplier traversal. Need to implement to DFS as well. 2024-02-11 03:38:54 -05:00
Jonathan Turner
f7d888305d Fixed pathing. 2024-02-11 03:38:32 -05:00
Jonathan Turner
85f9abea53 Designed the FXML file. 2024-02-11 03:38:20 -05:00
Jonathan Turner
3b56a1fb50 Added RichTextFX (May be removed later. 2024-02-11 01:45:37 -05:00
Jonathan Turner
2714b23dab Added base start for javafx setup. 2024-02-11 01:39:33 -05:00
16 changed files with 385 additions and 16 deletions

View File

@ -6,6 +6,11 @@
<option name="name" value="Central Repository" />
<option name="url" value="https://repo.maven.apache.org/maven2" />
</remote-repository>
<remote-repository>
<option name="id" value="snapshots" />
<option name="name" value="Sonatype Snapshots" />
<option name="url" value="https://oss.sonatype.org/content/repositories/snapshots/" />
</remote-repository>
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Maven Central repository" />

View File

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/CS3642-Artificial_Intelligence.iml" filepath="$PROJECT_DIR$/CS3642-Artificial_Intelligence.iml" />
</modules>
</component>
</project>

View File

@ -2,6 +2,5 @@
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

View File

@ -14,6 +14,11 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.fxmisc.richtext</groupId>
<artifactId>richtextfx</artifactId>
<version>0.11.0</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>

View File

@ -0,0 +1,26 @@
package Assignments.A1;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class GUIDriver extends Application {
@Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("/A1/view/BoardView.fxml"));
Scene scene = new Scene(root);
scene.getStylesheets().add(getClass().getResource("/A1/view/styles.css").toExternalForm());
stage.setTitle("Jonathan Turner - CS3642 - Assignment 1");
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}

View File

@ -0,0 +1,9 @@
package Assignments.A1;
public class GUILauncher {
public static void main(final String[] args) {
GUIDriver.main(args);
}
}

View File

@ -249,10 +249,9 @@ public class Board {
// }
@Override
public String toString() {
String result = "";
for (int i = 0; i < 9; i++) {
result += pieces[i] + " ";
}
String result = pieces[0] + " " + pieces[1] + " " + pieces[2] + "\n"
+ pieces[3] + " " + pieces[4] + " " + pieces[5] + "\n"
+ pieces[6] + " " + pieces[7] + " " + pieces[8];
return result;
}

View File

@ -84,4 +84,9 @@ public class BoardNode implements Comparable<BoardNode> {
public int compareTo(BoardNode o) { // BFS
return Integer.compare(this.heuristic, o.heuristic);
}
@Override
public String toString() {
return this.board.toString().replaceAll("\n", " ");
}
}

View File

@ -0,0 +1,9 @@
package Assignments.A1.models;
import Assignments.A1.models.Board;
import Assignments.A1.models.BoardNode;
public interface Solver {
BoardNode traverse(Board board);
}

View File

@ -3,13 +3,14 @@ package Assignments.A1.solving_algorithms;
import Assignments.A1.models.Board;
import Assignments.A1.models.BoardNode;
import Assignments.A1.models.Move;
import Assignments.A1.models.Solver;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.PriorityQueue;
public class AStar {
public class AStar implements Solver {
private final Board solved = new Board();
private final HashSet<Board> visited = new HashSet<>();

View File

@ -3,13 +3,14 @@ package Assignments.A1.solving_algorithms;
import Assignments.A1.models.Board;
import Assignments.A1.models.BoardNode;
import Assignments.A1.models.Move;
import Assignments.A1.models.Solver;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.PriorityQueue;
public class BFS {
public class BFS implements Solver {
private final HashSet<Board> visited = new HashSet<>();
private static final Board solved = new Board();

View File

@ -3,13 +3,14 @@ package Assignments.A1.solving_algorithms;
import Assignments.A1.models.Board;
import Assignments.A1.models.BoardNode;
import Assignments.A1.models.Move;
import Assignments.A1.models.Solver;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.PriorityQueue;
public class UCS {
public class UCS implements Solver {
private final Board solved = new Board();
private final HashSet<Board> visited = new HashSet<>();

View File

@ -0,0 +1,106 @@
package Assignments.A1.view;
import Assignments.A1.models.BoardNode;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.*;
import javax.swing.tree.TreeNode;
public class BoardViewCodeBehind {
@FXML
private TreeView<BoardNode> spanning_tree;
@FXML
private Label current_board;
@FXML
private Button generate_board;
@FXML
private MenuButton menu_alg;
@FXML
private ToggleButton showSolvedPath;
@FXML
private MenuItem AStar;
@FXML
private MenuItem BFS;
@FXML
private MenuItem DFS;
@FXML
private MenuItem UCS;
@FXML
private Button solve_button;
@FXML
private ProgressBar solving_prog;
@FXML
private Label gen_board_err;
@FXML
private Label no_solv_alg_err;
private MainViewModel viewModel;
public BoardViewCodeBehind() {
this.viewModel = new MainViewModel();
}
@FXML
private void initialize() {
this.current_board.textProperty().bindBidirectional(viewModel.getCurrentBoardProperty());
this.DFS.disableProperty().bindBidirectional(viewModel.DFSProperty());
this.UCS.disableProperty().bindBidirectional(viewModel.UCSProperty());
this.BFS.disableProperty().bindBidirectional(viewModel.BFSProperty());
this.AStar.disableProperty().bindBidirectional(viewModel.AStarProperty());
this.gen_board_err.visibleProperty().bindBidirectional(viewModel.genBoardErrProperty());
this.no_solv_alg_err.visibleProperty().bindBidirectional(viewModel.solvingAlgErrProperty());
}
public void onGenerateBoard(ActionEvent actionEvent) {
this.viewModel.generateBoard();
}
public void showSolvedPath(ActionEvent actionEvent) {
}
public void onSolveButton(ActionEvent actionEvent) {
viewModel.solveBoard();
this.spanning_tree.setRoot(viewModel.getSolvedRootNode());
}
public void onAlgChange(ActionEvent actionEvent) {
}
public void onDFS(ActionEvent actionEvent) {
viewModel.setSelectedAlg("DFS");
this.menu_alg.textProperty().set(this.menu_alg.getItems().get(0).textProperty().get());
}
public void onUCS(ActionEvent actionEvent) {
viewModel.setSelectedAlg("UCS");
this.menu_alg.textProperty().set(this.menu_alg.getItems().get(1).textProperty().get());
}
public void onBFS(ActionEvent actionEvent) {
viewModel.setSelectedAlg("BFS");
this.menu_alg.textProperty().set(this.menu_alg.getItems().get(2).textProperty().get());
}
public void onAStar(ActionEvent actionEvent) {
viewModel.setSelectedAlg("AStar");
this.menu_alg.textProperty().set(this.menu_alg.getItems().get(3).textProperty().get());
}
}

View File

@ -0,0 +1,144 @@
package Assignments.A1.view;
import Assignments.A1.models.Board;
import Assignments.A1.models.BoardGenerator;
import Assignments.A1.models.BoardNode;
import Assignments.A1.models.Solver;
import Assignments.A1.solving_algorithms.AStar;
import Assignments.A1.solving_algorithms.BFS;
import Assignments.A1.solving_algorithms.UCS;
import javafx.beans.property.*;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.control.TreeItem;
public class MainViewModel {
private StringProperty currentBoardProperty, algSpeedProperty;
private BooleanProperty showSolvedPath, DFS, UCS, BFS, AStar, solvingAlgErr, genBoardErr;
private DoubleProperty solvingProgressProperty;
private String selectedAlg;
private final ObservableList<BoardNode> spanningTree = FXCollections.observableArrayList();
private final ObjectProperty<ObservableList<BoardNode>> spanningTreeProperty = new SimpleObjectProperty<>(spanningTree);
private BoardNode current = new BoardNode(new Board(), null);
private TreeItem<BoardNode> solvedRootNode = null;
public MainViewModel() {
this.currentBoardProperty = new SimpleStringProperty();
this.algSpeedProperty = new SimpleStringProperty();
this.showSolvedPath = new SimpleBooleanProperty();
this.solvingProgressProperty = new SimpleDoubleProperty();
this.DFS = new SimpleBooleanProperty();
this.UCS = new SimpleBooleanProperty();
this.BFS = new SimpleBooleanProperty();
this.AStar = new SimpleBooleanProperty();
this.solvingAlgErr = new SimpleBooleanProperty();
this.genBoardErr = new SimpleBooleanProperty();
this.solvingAlgErr.set(false);
this.genBoardErr.set(false);
}
public String getSelectedAlg() {
return this.selectedAlg;
}
public void setSelectedAlg(String value) {
this.selectedAlg = value;
this.DFS.set(value.equals("DFS"));
this.UCS.set(value.equals("UCS"));
this.BFS.set(value.equals("BFS"));
this.AStar.set(value.equals("AStar"));
}
public StringProperty getCurrentBoardProperty() {
return this.currentBoardProperty;
}
public void generateBoard() {
this.current = new BoardNode(BoardGenerator.generateBoard(), null);
currentBoardProperty.set(this.current.board.toString());
}
public void solveBoard() {
if (selectedAlg == null || selectedAlg.isEmpty()) {
this.solvingAlgErr.setValue(true);
return;
}
this.solvingAlgErr.setValue(false);
if (current.board.equals(new Board())) {
this.genBoardErr.setValue(true);
return;
}
this.genBoardErr.setValue(false);
Solver solver = null;
if (DFS.getValue()) {
// solver = new DFS();
} else if (UCS.getValue()) {
solver = new UCS();
} else if (BFS.getValue()) {
solver = new BFS();
} else if (AStar.getValue()) {
solver = new AStar();
}
BoardNode solved = solver.traverse(this.current.board);
currentBoardProperty.setValue(solved.board.toString());
BoardNode root = solved;
while (root.parent != null) {
root = root.parent;
}
this.solvedRootNode = rebuildTree(root);
}
public TreeItem<BoardNode> getSolvedRootNode() {
return solvedRootNode;
}
public ObservableList<BoardNode> getSpanningTree() {
return spanningTreeProperty.get();
}
public ObjectProperty<ObservableList<BoardNode>> spanningTreeProperty() {
return spanningTreeProperty;
}
public BooleanProperty DFSProperty() {
return DFS;
}
public BooleanProperty UCSProperty() {
return UCS;
}
public BooleanProperty BFSProperty() {
return BFS;
}
public BooleanProperty AStarProperty() {
return AStar;
}
public BooleanProperty solvingAlgErrProperty() {
return solvingAlgErr;
}
public BooleanProperty genBoardErrProperty() {
return genBoardErr;
}
public TreeItem<BoardNode> rebuildTree(BoardNode root) {
TreeItem<BoardNode> treeItem = new TreeItem<>(root);
// Recursively create TreeItems for child nodes
for (BoardNode child : root.children) {
TreeItem<BoardNode> childItem = rebuildTree(child);
treeItem.getChildren().add(childItem);
}
return treeItem;
}
}

View File

@ -0,0 +1,67 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.Menu?>
<?import javafx.scene.control.MenuBar?>
<?import javafx.scene.control.MenuButton?>
<?import javafx.scene.control.MenuItem?>
<?import javafx.scene.control.ProgressBar?>
<?import javafx.scene.control.ToggleButton?>
<?import javafx.scene.control.TreeView?>
<?import javafx.scene.layout.Pane?>
<?import javafx.scene.text.Font?>
<Pane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="591.0" prefWidth="928.0" xmlns="http://javafx.com/javafx/21" xmlns:fx="http://javafx.com/fxml/1" fx:controller="Assignments.A1.view.BoardViewCodeBehind">
<children>
<MenuBar layoutY="2.0" prefHeight="25.0" prefWidth="134.0">
<menus>
<Menu mnemonicParsing="false" text="File">
<items>
<MenuItem mnemonicParsing="false" text="Close" />
</items>
</Menu>
<Menu mnemonicParsing="false" text="Edit">
<items>
<MenuItem mnemonicParsing="false" text="Delete" />
</items>
</Menu>
<Menu mnemonicParsing="false" text="Help">
<items>
<MenuItem mnemonicParsing="false" text="About" />
</items>
</Menu>
</menus>
</MenuBar>
<TreeView fx:id="spanning_tree" layoutX="334.0" layoutY="67.0" prefHeight="416.0" prefWidth="532.0" />
<ToggleButton fx:id="showSolvedPath" layoutX="545.0" layoutY="34.0" mnemonicParsing="false" onAction="#showSolvedPath" text="Show Solved Path" />
<ProgressBar id="solve_board_progress" fx:id="solving_prog" layoutX="500.0" layoutY="538.0" mouseTransparent="true" prefWidth="200.0" progress="0.0" />
<Button id="generate_board" fx:id="generate_board" layoutX="97.0" layoutY="367.0" mnemonicParsing="false" onAction="#onGenerateBoard" text="Generate Random Board" />
<Label fx:id="current_board" alignment="CENTER" layoutX="104.0" layoutY="129.0" prefHeight="184.0" prefWidth="134.0" text="0 1 2 8 0 4 7 6 5" textAlignment="JUSTIFY" wrapText="true">
<font>
<Font size="41.0" />
</font>
</Label>
<Button id="solve_board" fx:id="solve_button" layoutX="561.0" layoutY="503.0" mnemonicParsing="false" onAction="#onSolveButton" text="Solve Board" />
<MenuButton fx:id="menu_alg" layoutX="103.0" layoutY="416.0" mnemonicParsing="false" onAction="#onAlgChange" text="Traversal Algorithm">
<items>
<MenuItem fx:id="DFS" mnemonicParsing="false" onAction="#onDFS" text="Depth-First Search" />
<MenuItem fx:id="UCS" mnemonicParsing="false" onAction="#onUCS" text="Uniform-Cost Search" />
<MenuItem fx:id="BFS" mnemonicParsing="false" onAction="#onBFS" text="Best-First Search" />
<MenuItem fx:id="AStar" mnemonicParsing="false" onAction="#onAStar" text="A* (A Star)" />
</items>
</MenuButton>
<Label layoutX="728.0" layoutY="507.0" text="Algorithm Speed (ms): " />
<Label layoutX="849.0" layoutY="507.0" text="0" />
<Label fx:id="gen_board_err" layoutX="37.0" layoutY="525.0" prefHeight="26.0" prefWidth="325.0" text="You must generate a board before solving" textFill="RED" visible="false">
<font>
<Font size="17.0" />
</font>
</Label>
<Label fx:id="no_solv_alg_err" layoutX="37.0" layoutY="525.0" prefHeight="26.0" prefWidth="408.0" text="You must select a Traversal Algorithm before solving" textFill="RED" visible="false">
<font>
<Font size="14.0" />
</font>
</Label>
</children>
</Pane>

View File