diff --git a/.gitignore b/.gitignore
index e524a17..8e9219b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,19 +1,6 @@
-*.class
-*.log
-
-# sbt specific
-.cache
-.history
-.lib/
-dist/*
target/
-lib_managed/
-src_managed/
-project/boot/
-project/plugins/project/
-
-# Scala-IDE specific
-.scala_dependencies
-.worksheet
-.idea/
-*.iml
+.cache
+.classpath
+.project
+.settings/
+.idea
\ No newline at end of file
diff --git a/build.sbt b/build.sbt
index 4906dc6..7bb01b2 100644
--- a/build.sbt
+++ b/build.sbt
@@ -1,13 +1,26 @@
-enablePlugins(ScalaJSPlugin)
+// Build file for example applications written in ScalaJS using scala-js-dom and scala-js-workbench
+lazy val root = (project in file(".")).enablePlugins(ScalaJSPlugin)
+workbenchSettings
-name := "A Star Maze Solver"
-
-scalaVersion := "2.11.5"
+// Name is a prefix in the object code filename.
+name := "A*Star Maze Solver"
+scalaVersion := "2.11.7"
+// Optional, necessary to sbt run, needs phantomJS to be installed.
+jsDependencies += RuntimeDOM
scalaJSStage in Global := FastOptStage
-libraryDependencies += "org.scala-js" %%% "scalajs-dom" % "0.8.0"
-libraryDependencies += "org.scala-js" % "scalajs-tools_2.11" % "0.6.0"
-libraryDependencies += "com.lihaoyi" %%% "utest" % "0.3.0" % "test"
+libraryDependencies ++= Seq(
+ "org.scala-js" %%% "scalajs-dom" % "0.8.1",
+ "com.lihaoyi" %%% "scalatags" % "0.5.2",
+ "be.doeraene" %%% "scalajs-jquery" % "0.8.0",
+ "com.lihaoyi" %%% "utest" % "0.3.1" % "test"
+)
+skip in packageJSDependencies := false // All JavaScript dependencies to be concatenated to a single file
+
+// Workbench has to know how to restart your application.
+bootSnippet := "astar.AStarApp().doDynContent();"
+// Update without refreshing the page every time fastOptJS completes
+updateBrowsers <<= updateBrowsers.triggeredBy(fastOptJS in Compile)
-testFrameworks += new TestFramework("utest.runner.Framework")
\ No newline at end of file
+testFrameworks += new TestFramework("utest.runner.Framework")
diff --git a/project/build.properties b/project/build.properties
index 748703f..176a863 100644
--- a/project/build.properties
+++ b/project/build.properties
@@ -1 +1 @@
-sbt.version=0.13.7
+sbt.version=0.13.9
\ No newline at end of file
diff --git a/project/plugins.sbt b/project/plugins.sbt
index 0dd657b..605d7a6 100644
--- a/project/plugins.sbt
+++ b/project/plugins.sbt
@@ -1 +1,2 @@
-addSbtPlugin("org.scala-js" % "sbt-scalajs" % "0.6.1")
+addSbtPlugin("org.scala-js" % "sbt-scalajs" % "0.6.4")
+addSbtPlugin("com.lihaoyi" % "workbench" % "0.2.3")
\ No newline at end of file
diff --git a/src/main/resources/astar-demo-20.html b/src/main/resources/astar-demo-20.html
deleted file mode 100644
index 07b900e..0000000
--- a/src/main/resources/astar-demo-20.html
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
-
- A* Maze Solver
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/main/resources/index-dev.html b/src/main/resources/index-dev.html
new file mode 100644
index 0000000..ae8f581
--- /dev/null
+++ b/src/main/resources/index-dev.html
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+ A*Star Maze Solver
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/scala/astar/AStarApp.scala b/src/main/scala/astar/AStarApp.scala
index cb39ad7..6229c47 100644
--- a/src/main/scala/astar/AStarApp.scala
+++ b/src/main/scala/astar/AStarApp.scala
@@ -1,69 +1,60 @@
package astar
-import astar.maze.Mazes
-import astar.maze.Cell
-import astar.search.{Heuristics, Agent}
+import astar.maze.{Cell, Mazes}
+import astar.search.{Agent, Heuristics}
+import org.scalajs.dom
import org.scalajs.dom.html
import scala.scalajs.js.JSApp
-import org.scalajs.dom
-
import scala.scalajs.js.annotation.JSExport
@JSExport
-object AStarApp extends JSApp {
+object AStarApp {
- private val GREY = "#333333"
- private val BLUE = "#4682b4"
- private val YELLOW = "#ffb958"
- private val zoom = 10 //px
- private val offset = 5 //px
- private val drawRate = 10 //milliseconds
+ private val (grey, blue, yellow) = ("#333333", "#4682b4", "#ffb958")
+ private val (zoom, offset, drawRate) = (10 /*px*/ , 5 /*px*/ , 10 /*milliseconds*/ )
- def main(): Unit = {
- val canvas = dom.document
- .getElementById("canvas")
- .asInstanceOf[html.Canvas]
+ @JSExport
+ def doDynContent(): Unit = {
+ val canvas = dom.document.getElementById("canvas").asInstanceOf[html.Canvas]
- val ctx = canvas.getContext("2d")
- .asInstanceOf[dom.CanvasRenderingContext2D]
+ val ctx = canvas.getContext("2d").asInstanceOf[dom.CanvasRenderingContext2D]
- val maze = Mazes.maze20
+ val maze = Mazes.maze40
val agent = new Agent(maze, Heuristics.manhattan)
- val solution:Option[List[Cell]] = agent.search()
+ val solution: Option[List[Cell]] = agent.search()
- canvas.height = maze.height * zoom
- canvas.width = maze.width * zoom
+ canvas.height = maze.height * zoom; canvas.width = maze.width * zoom
- ctx.clearRect (0, 0, canvas.width, canvas.height)
+ ctx.clearRect(0, 0, canvas.width, canvas.height)
- ctx.fillStyle = GREY
- for(wall <- maze.walls) {
+ ctx.fillStyle = grey
+ for (wall <- maze.walls) {
ctx.fillRect(wall.x * zoom, wall.y * zoom, zoom, zoom)
}
- if(solution.isDefined) {
+ if (solution.isDefined) {
dom.console.log("Nodes expanded:" + agent.searchHistory.size)
draw(agent.searchHistory)
}
- def draw(fringe:Seq[List[Cell]]):Unit = {
- if(fringe.nonEmpty) {
- ctx.fillStyle = BLUE
+ def draw(fringe: Seq[List[Cell]]): Unit = {
+ if (fringe.nonEmpty) {
+ ctx.fillStyle = blue
for (cell <- fringe.head) {
ctx.beginPath()
- ctx.arc(cell.x * zoom + offset, cell.y * zoom + offset, (zoom -2)/ 2, 0, 2 * math.Pi)
+ ctx.arc(cell.x * zoom + offset, cell.y * zoom + offset, (zoom - 2) / 2, 0, 2 * math.Pi)
ctx.fill()
}
dom.setTimeout(() => draw(fringe.tail), drawRate)
} else {
val path = solution.get
- ctx.fillStyle = YELLOW
- for(cell <- path) {
+ ctx.fillStyle = yellow
+ for (cell <- path) {
ctx.beginPath()
- ctx.arc(cell.x * zoom + offset, cell.y * zoom + offset, (zoom -2)/ 2, 0, 2 * math.Pi)
+ ctx.arc(cell.x * zoom + offset, cell.y * zoom + offset, (zoom - 2) / 2, 0, 2 * math.Pi)
ctx.fill()
}
}
diff --git a/src/main/scala/astar/maze/Cell.scala b/src/main/scala/astar/maze/Cell.scala
deleted file mode 100644
index 7fdce0b..0000000
--- a/src/main/scala/astar/maze/Cell.scala
+++ /dev/null
@@ -1,25 +0,0 @@
-package astar.maze
-
-/**
- * Author: Phillip Johnson
- * Date: 3/15/15
- */
-class Cell(val x:Int, val y:Int) {
-
- override def toString = "(" + x + ", " + y + ")"
-
- def canEqual(other: Any): Boolean = other.isInstanceOf[Cell]
-
- override def equals(other: Any): Boolean = other match {
- case that: Cell =>
- (that canEqual this) &&
- x == that.x &&
- y == that.y
- case _ => false
- }
-
- override def hashCode(): Int = {
- val state = Seq(x, y)
- state.map(_.hashCode()).foldLeft(0)((a, b) => 31 * a + b)
- }
-}
diff --git a/src/main/scala/astar/maze/Maze.scala b/src/main/scala/astar/maze/Maze.scala
index 25701e9..1ea1b11 100644
--- a/src/main/scala/astar/maze/Maze.scala
+++ b/src/main/scala/astar/maze/Maze.scala
@@ -1,58 +1,63 @@
-package astar.maze
+package astar
+package maze
/**
* A problem for the A* agent to traverse.
*
* Mazes are generated from text strings using:
- * +- for horizontal walls
- * | for vertical walls
- * spaces for paths
- * I for the entrance
- * O for the exit
+ * +- for horizontal walls
+ * | for vertical walls
+ * spaces for paths
+ * I for the entrance
+ * O for the exit
*
* Author: Phillip Johnson
* Date: 3/14/15 (mmmm...π)
*/
-class Maze(val pattern:String) {
- require(pattern.contains("I"))
- require(pattern.contains("O"))
+case class Cell(x: Int, y: Int) {
+ override def toString = s"($x, $y)"
+}
+
+class Maze(val pattern: String) {
+ require(pattern.contains("I") && pattern.contains("O"), "Missing maze entrance or exit")
- private val WALL_STRINGS = Set('+','-','|')
- private val PATH_STRINGS = Set(' ','I','O')
+ private val WALL_STRINGS = Set('+', '-', '|')
+ private val PATH_STRINGS = Set(' ', 'I', 'O')
private val ENTRANCE_STRING = 'I'
private val EXIT_STRING = 'O'
- private val stringRows = pattern.split("\n")
-
- val width = stringRows.head.length
- val height = stringRows.size
+ //private val stringRows = pattern.split('\n')
+ val (width, height) = sizeOfMaze
- lazy val walls:Set[Cell] = {
+ lazy val walls: Set[Cell] = {
searchMaze(WALL_STRINGS)
}
- lazy val paths:Set[Cell] = {
+ lazy val paths: Set[Cell] = {
searchMaze(PATH_STRINGS)
}
- lazy val entrance:(Cell) = {
+ lazy val entrance: (Cell) = {
searchMaze(Set(ENTRANCE_STRING)).head
}
- lazy val exit:(Cell) = {
+ lazy val exit: (Cell) = {
searchMaze(Set(EXIT_STRING)).head
}
- private def searchMaze(chars:Set[Char]) = {
- val rows = stringRows
- val results = for {
- (rowStr:String, row:Int) <- rows.zipWithIndex
- (char:Char, col:Int) <- rowStr.zipWithIndex
- if chars.contains(char)
- } yield new Cell(col, row)
+ def sizeOfMaze = {
+ val stringRows = pattern.split('\n')
+ (stringRows.head.length - 1, stringRows.length)
+ }
- results.toSet
+ private def searchMaze(chars: Set[Char]) = {
+ val stringRows = pattern.split('\n')
+ (for {
+ (rowStr: String, row: Int) <- stringRows.zipWithIndex
+ (char: Char, col: Int) <- rowStr.zipWithIndex
+ if chars.contains(char)
+ } yield Cell(col, row)).toSet
}
}
diff --git a/src/main/scala/astar/maze/Mazes.scala b/src/main/scala/astar/maze/Mazes.scala
index fe1b840..cd37d80 100644
--- a/src/main/scala/astar/maze/Mazes.scala
+++ b/src/main/scala/astar/maze/Mazes.scala
@@ -1,15 +1,137 @@
-package astar.maze
+package astar
+package maze
/**
- * Author: Phillip Johnson
+ * Author: Phillip C Johnson
* Date: 3/8/15
*/
object Mazes {
- private val maze40Str = "+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\nI | | | | | | | | | | | | | |\n+-+-+-+-+-+ + + + + +-+-+ + + +-+ + +-+ +-+-+-+ + + + + + + +-+-+ + + + + +-+ + +\n| | | | | | | | | | | | | | | | | | | | | | | | |\n+ +-+-+ + + + +-+-+ + +-+-+ + +-+-+ + +-+-+ + + + +-+-+-+-+ +-+ + +-+-+ + + + +-+\n| | | | | | | | | | | | | | | | | | | | | | |\n+ + + +-+-+-+-+ + + + + +-+-+-+ +-+-+ + + + + + +-+-+ + + +-+ + + +-+ +-+-+-+ + +\n| | | | | | | | | | | | | | | | | | | | | | | |\n+-+-+ + + +-+-+-+-+-+ + + + +-+ + + +-+ + + +-+-+ + +-+ + + +-+-+-+ +-+ + +-+-+ +\n| | | | | | | | | | | | | | | | | | | | | | | | |\n+ + +-+-+-+ + +-+ +-+ +-+-+-+-+-+ +-+ +-+ + + + + +-+ + + + + + + + + + + +-+ + +\n| | | | | | | | | | | | | | | | | | | | | | | |\n+ + + + +-+ + +-+-+ +-+ +-+-+-+-+-+ + + + + +-+-+-+-+-+-+ + + + +-+ +-+-+ + + + +\n| | | | | | | | | | | | | | | | | | | | | | |\n+ + + +-+ +-+ +-+ + + +-+-+-+ + + + + +-+-+ + + +-+-+-+ + + +-+-+-+ + + +-+-+ + +\n| | | | | | | | | | | | | | | | | | | | |\n+ +-+-+-+-+ +-+ + + + + +-+-+-+ + + +-+-+ + +-+-+-+ +-+-+-+ +-+-+-+-+-+-+ +-+-+ +\n| | | | | | | | | | | | | | | | | |\n+ + + +-+ +-+-+ +-+-+-+-+-+-+-+-+-+ + +-+-+-+-+-+ +-+-+ +-+-+-+ + + + +-+-+ + + +\n| | | | | | | | | | | | | | | | | | | | | | |\n+ + + + + + + +-+ +-+ +-+-+-+ + +-+-+-+ + + +-+ +-+ + +-+-+ + +-+ + + + +-+ + +-+\n| | | | | | | | | | | | | | | | | | | | | | | |\n+-+-+ +-+-+-+ + +-+ + + + +-+-+-+-+-+-+-+ +-+ +-+ + +-+ + +-+ + + +-+ +-+-+-+-+ +\n| | | | | | | | | | | | | | | | | | | |\n+ +-+-+-+-+-+-+ + + +-+-+-+-+-+-+-+ + + +-+ +-+ + + + +-+-+ + +-+-+ +-+ + + + + +\n| | | | | | | | | | | | | | | | | | | | | | |\n+ +-+-+-+ + + +-+ +-+-+ +-+-+ + + +-+ + + +-+-+-+ + +-+ + + + +-+ + + +-+ + +-+ +\n| | | | | | | | | | | | | | | | | | | | | |\n+-+ + + +-+ + + + + +-+-+ + +-+-+-+ +-+ +-+-+ + +-+-+ + +-+-+-+-+ + + + +-+-+ +-+\n| | | | | | | | | | | | | | | | | | | | |\n+-+ +-+ + +-+-+-+ +-+ +-+-+-+ + +-+-+ + + +-+-+-+ +-+-+ + + + +-+-+ +-+ +-+ +-+ +\n| | | | | | | | | | | | | | | | | | | | |\n+ +-+-+-+ + +-+ +-+-+-+ +-+ + + + +-+-+-+ + + +-+-+-+ +-+ + +-+ + + +-+-+ + + +-+\n| | | | | | | | | | | | | | | | | | | | |\n+-+-+ + + +-+ +-+-+-+-+-+-+ + + +-+-+ + +-+-+-+ +-+ +-+ + + + +-+ +-+ +-+ +-+-+ +\n| | | | | | | | | | | | | | | | | | | | |\n+ +-+-+-+-+ +-+-+ + + + + + + +-+-+ + +-+-+ +-+-+-+ + +-+-+-+-+-+ + + + +-+ + + +\n| | | | | | | | | | | | | | | | | | | |\n+-+-+-+-+ +-+-+-+-+-+ + + + +-+-+ +-+-+-+ +-+ + + + + +-+ +-+-+ + +-+-+-+-+-+-+ +\n| | | | | | | | | | | | | | | | | | |\n+ +-+-+-+-+-+ + + + + +-+ + + +-+-+ +-+-+-+ +-+-+ +-+-+ +-+ + +-+-+-+ +-+ + + +-+\n| | | | | | | | | | | | | | | | | | | | | |\n+-+ + +-+ + +-+-+-+ +-+ + + + + + +-+-+-+ +-+ + +-+ + + +-+ +-+-+ +-+-+ +-+-+ + +\n| | | | | | | | | | | | | | | | | | | | | | |\n+ + +-+ +-+-+ +-+ + + +-+-+ +-+-+ +-+-+ +-+ + +-+-+-+-+ + +-+ +-+-+ +-+-+ + +-+ +\n| | | | | | | | | | | | | | | | | | | |\n+ +-+ + + +-+ + + +-+-+ +-+-+-+ +-+-+ + + +-+-+-+ +-+-+-+ + +-+-+-+-+ + + + + +-+\n| | | | | | | | | | | | | | | | | | | |\n+ +-+-+-+ + +-+ +-+-+ +-+ + +-+-+-+ + + + +-+-+-+ +-+ + +-+-+-+-+ +-+-+ +-+-+-+ +\n| | | | | | | | | | | | | | | | | | | |\n+-+ +-+ + + + +-+ + + +-+-+ + + +-+ + +-+-+ + +-+-+ +-+-+-+-+-+ + + + +-+-+ + +-+\n| | | | | | | | | | | | | | | | | | | | | | |\n+ + + +-+ + + + +-+ +-+-+ +-+-+-+ + +-+ +-+ +-+ + +-+-+ + + +-+ + + +-+-+-+-+-+ +\n| | | | | | | | | | | | | | | | | | | | | |\n+ + + + +-+ + + + +-+ + +-+-+-+-+-+ + +-+ +-+-+-+-+ + +-+ +-+ + +-+-+-+-+ +-+-+ +\n| | | | | | | | | | | | | | | | | | | | |\n+ +-+-+-+-+ +-+ +-+ + + + +-+-+-+ + +-+ + + + + + + + +-+ + +-+ +-+-+-+ +-+-+ + +\n| | | | | | | | | | | | | | | | | | | | | | |\n+ +-+-+-+-+-+ + + + +-+-+-+ + + +-+-+-+ +-+-+ +-+-+-+-+-+ +-+ + + + + +-+ +-+ + +\n| | | | | | | | | | | | | | | | | | |\n+ +-+-+ + + +-+-+-+ + + +-+ + +-+ +-+ +-+ + +-+ +-+-+-+ + +-+ + +-+-+-+ +-+ + + +\n| | | | | | | | | | | | | | | | | | | | | |\n+ + + + + +-+-+ + +-+ + + +-+-+-+-+ + + +-+ + +-+-+ + +-+-+-+-+ + +-+ +-+-+-+-+ +\n| | | | | | | | | | | | | | | | | | |\n+-+-+ +-+ + +-+-+ + +-+ +-+ + + +-+-+-+-+-+-+ + + +-+-+-+ +-+ +-+-+-+ + +-+-+ +-+\n| | | | | | | | | | | | | | | | | | | |\n+ + + + +-+ + +-+-+ + +-+-+ + + + +-+-+ + + +-+-+-+-+-+-+-+ +-+ + + +-+ + +-+ +-+\n| | | | | | | | | | | | | | | | | | | | | |\n+ + +-+-+ +-+-+ + +-+ + +-+-+ + +-+ + +-+-+-+-+-+-+ + + +-+ + +-+-+-+ +-+-+ +-+ +\n| | | | | | | | | | | | | | | | | | | | |\n+ +-+-+-+-+-+ +-+-+ + +-+-+ +-+-+-+-+-+-+ + + + + +-+-+-+-+-+ +-+ + + + + + +-+ +\n| | | | | | | | | | | | | | | | |\n+ + +-+-+-+ +-+-+-+-+-+ + +-+-+-+ + + + +-+-+-+-+ +-+ +-+-+ +-+ +-+-+ +-+ +-+-+ +\n| | | | | | | | | | | | | | | | | | |\n+ +-+ +-+ +-+-+-+-+-+-+-+ + +-+ + +-+ + +-+-+-+ +-+ +-+-+-+-+ + + + +-+ +-+-+ + +\n| | | | | | | | | | | | | | | | | |\n+-+ +-+ +-+-+ + +-+-+ + +-+ + + + + + +-+-+-+-+ +-+-+ +-+-+ +-+-+ +-+ +-+-+-+-+-+\n| | | | | | | | | | | | | | | | | | | |\n+ +-+ +-+-+-+ + + + +-+ + + + + +-+-+-+ + + +-+-+-+ + + + +-+-+-+-+-+-+ + + +-+ +\n| | | | | | | | | | | | O\n+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+"
+ private def maze40Str =
+ """+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ !I | | | | | | | | | | | | | |
+ !+-+-+-+-+-+ + + + + +-+-+ + + +-+ + +-+ +-+-+-+ + + + + + + +-+-+ + + + + +-+ + +
+ !| | | | | | | | | | | | | | | | | | | | | | | | |
+ !+ +-+-+ + + + +-+-+ + +-+-+ + +-+-+ + +-+-+ + + + +-+-+-+-+ +-+ + +-+-+ + + + +-+
+ !| | | | | | | | | | | | | | | | | | | | | | |
+ !+ + + +-+-+-+-+ + + + + +-+-+-+ +-+-+ + + + + + +-+-+ + + +-+ + + +-+ +-+-+-+ + +
+ !| | | | | | | | | | | | | | | | | | | | | | | |
+ !+-+-+ + + +-+-+-+-+-+ + + + +-+ + + +-+ + + +-+-+ + +-+ + + +-+-+-+ +-+ + +-+-+ +
+ !| | | | | | | | | | | | | | | | | | | | | | | | |
+ !+ + +-+-+-+ + +-+ +-+ +-+-+-+-+-+ +-+ +-+ + + + + +-+ + + + + + + + + + + +-+ + +
+ !| | | | | | | | | | | | | | | | | | | | | | | |
+ !+ + + + +-+ + +-+-+ +-+ +-+-+-+-+-+ + + + + +-+-+-+-+-+-+ + + + +-+ +-+-+ + + + +
+ !| | | | | | | | | | | | | | | | | | | | | | |
+ !+ + + +-+ +-+ +-+ + + +-+-+-+ + + + + +-+-+ + + +-+-+-+ + + +-+-+-+ + + +-+-+ + +
+ !| | | | | | | | | | | | | | | | | | | | |
+ !+ +-+-+-+-+ +-+ + + + + +-+-+-+ + + +-+-+ + +-+-+-+ +-+-+-+ +-+-+-+-+-+-+ +-+-+ +
+ !| | | | | | | | | | | | | | | | | |
+ !+ + + +-+ +-+-+ +-+-+-+-+-+-+-+-+-+ + +-+-+-+-+-+ +-+-+ +-+-+-+ + + + +-+-+ + + +
+ !| | | | | | | | | | | | | | | | | | | | | | |
+ !+ + + + + + + +-+ +-+ +-+-+-+ + +-+-+-+ + + +-+ +-+ + +-+-+ + +-+ + + + +-+ + +-+
+ !| | | | | | | | | | | | | | | | | | | | | | | |
+ !+-+-+ +-+-+-+ + +-+ + + + +-+-+-+-+-+-+-+ +-+ +-+ + +-+ + +-+ + + +-+ +-+-+-+-+ +
+ !| | | | | | | | | | | | | | | | | | | |
+ !+ +-+-+-+-+-+-+ + + +-+-+-+-+-+-+-+ + + +-+ +-+ + + + +-+-+ + +-+-+ +-+ + + + + +
+ !| | | | | | | | | | | | | | | | | | | | | | |
+ !+ +-+-+-+ + + +-+ +-+-+ +-+-+ + + +-+ + + +-+-+-+ + +-+ + + + +-+ + + +-+ + +-+ +
+ !| | | | | | | | | | | | | | | | | | | | | |
+ !+-+ + + +-+ + + + + +-+-+ + +-+-+-+ +-+ +-+-+ + +-+-+ + +-+-+-+-+ + + + +-+-+ +-+
+ !| | | | | | | | | | | | | | | | | | | | |
+ !+-+ +-+ + +-+-+-+ +-+ +-+-+-+ + +-+-+ + + +-+-+-+ +-+-+ + + + +-+-+ +-+ +-+ +-+ +
+ !| | | | | | | | | | | | | | | | | | | | |
+ !+ +-+-+-+ + +-+ +-+-+-+ +-+ + + + +-+-+-+ + + +-+-+-+ +-+ + +-+ + + +-+-+ + + +-+
+ !| | | | | | | | | | | | | | | | | | | | |
+ !+-+-+ + + +-+ +-+-+-+-+-+-+ + + +-+-+ + +-+-+-+ +-+ +-+ + + + +-+ +-+ +-+ +-+-+ +
+ !| | | | | | | | | | | | | | | | | | | | |
+ !+ +-+-+-+-+ +-+-+ + + + + + + +-+-+ + +-+-+ +-+-+-+ + +-+-+-+-+-+ + + + +-+ + + +
+ !| | | | | | | | | | | | | | | | | | | |
+ !+-+-+-+-+ +-+-+-+-+-+ + + + +-+-+ +-+-+-+ +-+ + + + + +-+ +-+-+ + +-+-+-+-+-+-+ +
+ !| | | | | | | | | | | | | | | | | | |
+ !+ +-+-+-+-+-+ + + + + +-+ + + +-+-+ +-+-+-+ +-+-+ +-+-+ +-+ + +-+-+-+ +-+ + + +-+
+ !| | | | | | | | | | | | | | | | | | | | | |
+ !+-+ + +-+ + +-+-+-+ +-+ + + + + + +-+-+-+ +-+ + +-+ + + +-+ +-+-+ +-+-+ +-+-+ + +
+ !| | | | | | | | | | | | | | | | | | | | | | |
+ !+ + +-+ +-+-+ +-+ + + +-+-+ +-+-+ +-+-+ +-+ + +-+-+-+-+ + +-+ +-+-+ +-+-+ + +-+ +
+ !| | | | | | | | | | | | | | | | | | | |
+ !+ +-+ + + +-+ + + +-+-+ +-+-+-+ +-+-+ + + +-+-+-+ +-+-+-+ + +-+-+-+-+ + + + + +-+
+ !| | | | | | | | | | | | | | | | | | | |
+ !+ +-+-+-+ + +-+ +-+-+ +-+ + +-+-+-+ + + + +-+-+-+ +-+ + +-+-+-+-+ +-+-+ +-+-+-+ +
+ !| | | | | | | | | | | | | | | | | | | |
+ !+-+ +-+ + + + +-+ + + +-+-+ + + +-+ + +-+-+ + +-+-+ +-+-+-+-+-+ + + + +-+-+ + +-+
+ !| | | | | | | | | | | | | | | | | | | | | | |
+ !+ + + +-+ + + + +-+ +-+-+ +-+-+-+ + +-+ +-+ +-+ + +-+-+ + + +-+ + + +-+-+-+-+-+ +
+ !| | | | | | | | | | | | | | | | | | | | | |
+ !+ + + + +-+ + + + +-+ + +-+-+-+-+-+ + +-+ +-+-+-+-+ + +-+ +-+ + +-+-+-+-+ +-+-+ +
+ !| | | | | | | | | | | | | | | | | | | | |
+ !+ +-+-+-+-+ +-+ +-+ + + + +-+-+-+ + +-+ + + + + + + + +-+ + +-+ +-+-+-+ +-+-+ + +
+ !| | | | | | | | | | | | | | | | | | | | | | |
+ !+ +-+-+-+-+-+ + + + +-+-+-+ + + +-+-+-+ +-+-+ +-+-+-+-+-+ +-+ + + + + +-+ +-+ + +
+ !| | | | | | | | | | | | | | | | | | |
+ !+ +-+-+ + + +-+-+-+ + + +-+ + +-+ +-+ +-+ + +-+ +-+-+-+ + +-+ + +-+-+-+ +-+ + + +
+ !| | | | | | | | | | | | | | | | | | | | | |
+ !+ + + + + +-+-+ + +-+ + + +-+-+-+-+ + + +-+ + +-+-+ + +-+-+-+-+ + +-+ +-+-+-+-+ +
+ !| | | | | | | | | | | | | | | | | | |
+ !+-+-+ +-+ + +-+-+ + +-+ +-+ + + +-+-+-+-+-+-+ + + +-+-+-+ +-+ +-+-+-+ + +-+-+ +-+
+ !| | | | | | | | | | | | | | | | | | | |
+ !+ + + + +-+ + +-+-+ + +-+-+ + + + +-+-+ + + +-+-+-+-+-+-+-+ +-+ + + +-+ + +-+ +-+
+ !| | | | | | | | | | | | | | | | | | | | | |
+ !+ + +-+-+ +-+-+ + +-+ + +-+-+ + +-+ + +-+-+-+-+-+-+ + + +-+ + +-+-+-+ +-+-+ +-+ +
+ !| | | | | | | | | | | | | | | | | | | | |
+ !+ +-+-+-+-+-+ +-+-+ + +-+-+ +-+-+-+-+-+-+ + + + + +-+-+-+-+-+ +-+ + + + + + +-+ +
+ !| | | | | | | | | | | | | | | | |
+ !+ + +-+-+-+ +-+-+-+-+-+ + +-+-+-+ + + + +-+-+-+-+ +-+ +-+-+ +-+ +-+-+ +-+ +-+-+ +
+ !| | | | | | | | | | | | | | | | | | |
+ !+ +-+ +-+ +-+-+-+-+-+-+-+ + +-+ + +-+ + +-+-+-+ +-+ +-+-+-+-+ + + + +-+ +-+-+ + +
+ !| | | | | | | | | | | | | | | | | |
+ !+-+ +-+ +-+-+ + +-+-+ + +-+ + + + + + +-+-+-+-+ +-+-+ +-+-+ +-+-+ +-+ +-+-+-+-+-+
+ !| | | | | | | | | | | | | | | | | | | |
+ !+ +-+ +-+-+-+ + + + +-+ + + + + +-+-+-+ + + +-+-+-+ + + + +-+-+-+-+-+-+ + + +-+ +
+ !| | | | | | | | | | | | O
+ !+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+""".stripMargin('!')
lazy val maze40 = new Maze(maze40Str)
- private val maze20Str = "+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\nI | | | | | | |\n+ +-+-+-+ + + + + + + + + + + +-+ +-+ + +\n| | | | | | | | | | | | | |\n+-+-+-+-+-+ +-+-+-+-+ + +-+ + + + + +-+-+\n| | | | | | | |\n+ + +-+-+-+-+-+ + +-+-+ + +-+-+-+ +-+-+ +\n| | | | | | | | | | |\n+-+-+ +-+-+-+-+-+ + + + +-+ + + + + + + +\n| | | | | | | | | | | | | | |\n+ +-+-+ + + + + +-+ + + + + + + +-+-+ + +\n| | | | | | | | | | | | | |\n+ +-+ + + + +-+-+ +-+ + +-+-+-+ +-+-+-+-+\n| | | | | | | | | | |\n+-+-+-+ + +-+ + + + +-+-+-+ + +-+ + + + +\n| | | | | | | | | | | | |\n+ + + + +-+-+-+ + + +-+ + +-+ + + +-+ + +\n| | | | | | | | | | | |\n+ + +-+ +-+-+ +-+-+-+ +-+ + +-+ +-+ +-+ +\n| | | | | | | | | | | | |\n+-+-+ + + +-+-+ + +-+-+ +-+ + + + +-+ + +\n| | | | | | | | | | | |\n+ +-+-+-+-+-+-+-+ + + +-+ + + +-+-+ +-+ +\n| | | | | | | | | | | |\n+ + +-+-+-+-+ + + + +-+ + +-+ + + + + + +\n| | | | | | | | | | | | | |\n+ + +-+ + + + +-+-+ + + + + + +-+-+ +-+-+\n| | | | | | | | | | | |\n+-+-+ +-+-+-+-+-+-+ +-+-+ + + + +-+-+ + +\n| | | | | | | | | | | |\n+ + +-+ +-+ +-+ +-+-+-+ +-+-+-+ + + + + +\n| | | | | | | | | | | | | |\n+ +-+ +-+ +-+ +-+ +-+ + + + + +-+ + + + +\n| | | | | | | | | | | | | | | |\n+ + +-+ + +-+ + +-+ +-+-+ + + + + +-+ + +\n| | | | | | | | | | |\n+-+-+ +-+-+ +-+-+ +-+-+ +-+-+ +-+-+ + + +\n| | | | | | |\n+ +-+-+ + + +-+-+ +-+-+ +-+-+-+-+-+-+-+ +\n| | | | O\n+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+"
+ private def maze20Str =
+ """+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ !I | | | | | | |
+ !+ +-+-+-+ + + + + + + + + + + +-+ +-+ + +
+ !| | | | | | | | | | | | | |
+ !+-+-+-+-+-+ +-+-+-+-+ + +-+ + + + + +-+-+
+ !| | | | | | | |
+ !+ + +-+-+-+-+-+ + +-+-+ + +-+-+-+ +-+-+ +
+ !| | | | | | | | | | |
+ !+-+-+ +-+-+-+-+-+ + + + +-+ + + + + + + +
+ !| | | | | | | | | | | | | | |
+ !+ +-+-+ + + + + +-+ + + + + + + +-+-+ + +
+ !| | | | | | | | | | | | | |
+ !+ +-+ + + + +-+-+ +-+ + +-+-+-+ +-+-+-+-+
+ !| | | | | | | | | | |
+ !+-+-+-+ + +-+ + + + +-+-+-+ + +-+ + + + +
+ !| | | | | | | | | | | | |
+ !+ + + + +-+-+-+ + + +-+ + +-+ + + +-+ + +
+ !| | | | | | | | | | | |
+ !+ + +-+ +-+-+ +-+-+-+ +-+ + +-+ +-+ +-+ +
+ !| | | | | | | | | | | | |
+ !+-+-+ + + +-+-+ + +-+-+ +-+ + + + +-+ + +
+ !| | | | | | | | | | | |
+ !+ +-+-+-+-+-+-+-+ + + +-+ + + +-+-+ +-+ +
+ !| | | | | | | | | | | |
+ !+ + +-+-+-+-+ + + + +-+ + +-+ + + + + + +
+ !| | | | | | | | | | | | | |
+ !+ + +-+ + + + +-+-+ + + + + + +-+-+ +-+-+
+ !| | | | | | | | | | | |
+ !+-+-+ +-+-+-+-+-+-+ +-+-+ + + + +-+-+ + +
+ !| | | | | | | | | | | |
+ !+ + +-+ +-+ +-+ +-+-+-+ +-+-+-+ + + + + +
+ !| | | | | | | | | | | | | |
+ !+ +-+ +-+ +-+ +-+ +-+ + + + + +-+ + + + +
+ !| | | | | | | | | | | | | | | |
+ !+ + +-+ + +-+ + +-+ +-+-+ + + + + +-+ + +
+ !| | | | | | | | | | |
+ !+-+-+ +-+-+ +-+-+ +-+-+ +-+-+ +-+-+ + + +
+ !| | | | | | |
+ !+ +-+-+ + + +-+-+ +-+-+ +-+-+-+-+-+-+-+ +
+ !| | | | O
+ !+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+""".stripMargin('!')
lazy val maze20 = new Maze(maze20Str)
-
}
diff --git a/src/main/scala/astar/search/Agent.scala b/src/main/scala/astar/search/Agent.scala
index 3f9c1f3..b997764 100644
--- a/src/main/scala/astar/search/Agent.scala
+++ b/src/main/scala/astar/search/Agent.scala
@@ -1,4 +1,5 @@
-package astar.search
+package astar
+package search
import astar.maze.{Cell, Maze}
@@ -14,48 +15,55 @@ import scala.collection.mutable.ListBuffer
* Author: Phillip Johnson
* Date: 3/15/15
*/
-class Agent(maze:Maze, heuristic: (State, Maze) => Int) {
- class Direction(val dx:Int, val dy:Int)
- val NORTH = new Direction(0, -1)
- val SOUTH = new Direction(0, 1)
- val EAST = new Direction(1, 0)
- val WEST = new Direction(-1, 0)
+case class State(cell: Cell) {
+ val (x, y) = (cell.x, cell.y)
+}
+
+class Agent(maze: Maze, heuristic: (State, Maze) => Int) {
+
+ case class Direction(dx: Int, dy: Int)
+
+ val NORTH = Direction(0, -1)
+ val SOUTH = Direction(0, 1)
+ val EAST = Direction(1, 0)
+ val WEST = Direction(-1, 0)
var searchHistory = new ListBuffer[List[Cell]]
- class Successor(val move:Cell, val direction:Direction, val cost:Int)
+ class Successor(val move: Cell, val direction: Direction, val cost: Int)
- def successors(state:State):Set[Successor] = {
- Set(NORTH,SOUTH,EAST,WEST)
+ def successors(state: State): Set[Successor] = {
+ Set(NORTH, SOUTH, EAST, WEST)
.withFilter(d => maze.paths.contains(new Cell(state.x + d.dx, state.y + d.dy)))
.map(d => new Successor(new Cell(state.x + d.dx, state.y + d.dy), d, 1))
}
- def isGoal(state:State) = new Cell(state.x, state.y) == maze.exit
+ def isGoal(state: State) = new Cell(state.x, state.y) == maze.exit
- class FringeElement(val state:State, val path:List[Cell], val cost:Int) extends Ordered[FringeElement] {
+ class FringeElement(val state: State, val path: List[Cell], val cost: Int) extends Ordered[FringeElement] {
override def compare(that: FringeElement): Int = {
val thisCost = this.cost + heuristic.apply(this.state, maze)
val thatCost = that.cost + heuristic.apply(that.state, maze)
thatCost.compare(thisCost)
}
- override def toString = "(" + state.x + ", " + state.y + ")" + " Cells: " + path.size + " Cost: " + cost
+
+ override def toString = s"($state.x, ${state.y}) Cells: ${path.size} Cost: $cost"
}
- def search():Option[List[Cell]] = {
- var closed:Set[State] = Set.empty
+ def search(): Option[List[Cell]] = {
+ var closed: Set[State] = Set.empty
val fringe = new mutable.PriorityQueue[FringeElement]()
fringe += new FringeElement(new State(maze.entrance), List.empty, 0)
- while(fringe.nonEmpty) {
+ while (fringe.nonEmpty) {
val next = fringe.dequeue()
- if(isGoal(next.state)) {
+ if (isGoal(next.state)) {
//Bookend with the entrance and exit for clarity
return Some(next.path.::(maze.exit).+:(maze.entrance))
}
- if(!closed.contains(next.state)) {
+ if (!closed.contains(next.state)) {
closed = closed + next.state
- for(s <- successors(next.state)) {
+ for (s <- successors(next.state)) {
val newPath = next.path.::(s.move)
val newCost = next.cost + s.cost
val expansion = new FringeElement(new State(s.move), newPath, newCost)
diff --git a/src/main/scala/astar/search/State.scala b/src/main/scala/astar/search/State.scala
deleted file mode 100644
index 8787aef..0000000
--- a/src/main/scala/astar/search/State.scala
+++ /dev/null
@@ -1,28 +0,0 @@
-package astar.search
-
-import astar.maze.Cell
-
-/**
- * Author: Phillip Johnson
- * Date: 3/15/15
- */
-class State(cell:Cell) {
- val x = cell.x
- val y = cell.y
-
-
- def canEqual(other: Any): Boolean = other.isInstanceOf[State]
-
- override def equals(other: Any): Boolean = other match {
- case that: State =>
- (that canEqual this) &&
- x == that.x &&
- y == that.y
- case _ => false
- }
-
- override def hashCode(): Int = {
- val state = Seq(x, y)
- state.map(_.hashCode()).foldLeft(0)((a, b) => 31 * a + b)
- }
-}