In this lab you will add the
8-Puzzle Problem to the JavaScript
problem solver presented in lecture (see menu at left).
When finished, the
Chooser object should include the 8-puzzle
problem:
When selected, the 8-puzzle problem should present as below, and the
user should be able to make moves to completion.
If you originally installed the
Java SE NetBeans bundle you will
not have the modules required for JavaScript development.
To install them:
- On the NetBeans menu bar click Tools and
select Plugins
- In the Plugins dialog, go to the Available Plugins
tab and search for "JavaScript2 Kit" and "HTML5 Kit"
- Tick the Install checkbox next to both plugins, then
click the Install button
This section lists the files used in this lab exercise.
This section lists the files provided for this lab exercise.
You will add files for the 8-puzzle problem.
The
js folder contains subfolders for the problem solving
framework and problem domains, and a file of test utilities.
This folder also contains the JavaScript code used to test the objects
defined here. However, the HTML files that display the test results in
the browser are contained in the
test folder.
The
domains folder contains subfolders for the FWGC and water
jug problems.
You will add a subfolder for the 8-puzzle problem.
The JavaScript files for the FWGC problem are complete and described in
the lecture.
The JavaScript files for the FWGC problem are complete and described in
the lecture.
The framework folder contains subfolders for representing
problems, finding solutions, and interacting with users, as well as a
folder of utility functions.
The problem folder contains files holding the constructor
functions for the State, Mover, and Problem
prototype objects.
The solution folder contains files for representing and testing
the solving assistant.
The gui folder contains files for representing and testing
the problem panel and problem chooser.
The utils folder currently contains one file for representing a
hash map.
The
test folder contains HTML files used to test the framework
and domain objects.
You can use the domain testing files as models for testing your
8-puzzle code.
Here is a zipped folder to use for this lab:
JSProblemSolver.zip.
Unzip this file and place the resulting
JSProblemSolver folder in a
location where you will create a NetBeans project.
In NetBeans,
- Under File choose New Project...
- In the dialog, select category HTML5/JavaScript
and HTML5/JS Application with Existing Sources.
Note that if this is the first HTML5/JavaScript
project you have created, NetBeans will activate the feature.
- For Site Root select
the unzipped JSProblemSolver folder.
- Click Finish
When finished, your project structure must look as shown to the right.
On the NetBeans tool bar, select your desired browser (ignore browsers
with "NetBeans Connector").
Right click
solve.html and select
Run File. You will be
brought to a problem solver page like the one below.
Note that this problem solver user interface includes jQuery
effects. We will discuss jQuery in class, but understanding jQuery is
not necessary for this lab.
Your job is to create and implement files for the 8-puzzle problem
domain, and to extend the problem solver code to include them.
Open the
Site Root and
js folders in
your
JSProblemSolver project.
Right click on
domains, choose
New > Folder... and create
a
puzzle folder:
Create six empty JavaScript files in the
puzzle folder as shown below
by right clicking the
puzzle folder
and choosing
New > JavaScript File...:
Implement PuzzleState.js, PuzzleMover.js,
and PuzzleProblem.js (in that order) by using their counterparts
in farmer and waterjug as models.
Template code for the
PuzzleState constructor function is shown
to the right.
It should be placed in your newly created
PuzzleState.js file.
You need to provide the
toString and
equals methods, and
any methods that may be required by
PuzzleMover.
See
Suggestions on the menu at left for suggestions on how to
implement 2-D arrays and represent tile locations in JavaScript.
When you are ready to test the
PuzzleState object, use the files
PuzzleStateTest.js and
PuzzleStateTest.html
on the menu at left. Correct test output is also shown.
This code uses
FarmerStateTest.js
and
WaterJugStateTest.js as models.
It should be placed in your newly created
PuzzleStateTest.js
file.
This file should be placed into the
test folder of your NetBeans
project.
To run it, right click the file and select
Run File.
When it runs without errors, move on to the
PuzzleMover object.
Template code for the
PuzzleMover constructor function is shown
to the right.
It should be placed in your newly created
PuzzleMover.js file.
You need to complete the calls to
addMove.
See
Suggestions on the menu at left for suggestions on how to
swap tiles in the array representation.
When you are ready to test the
PuzzleMover object, use the files
PuzzleMoverTest.js and
PuzzleMoverTest.html
on the menu at left. Correct test output is also shown.
This code uses
FarmerMoverTest.js
and
WaterJugMoverTest.js as models.
It should be placed in your newly created
PuzzleMoverTest.js
file.
This file should be placed into the
test folder of your NetBeans
project.
To run it, right click the file and select
Run File.
When it runs without errors, move on to the
PuzzleProblem object.
Template code for the
PuzzleProblem constructor function is shown
to the right.
It should be placed in your newly created
PuzzleProblem.js file.
You need to initialize the required variables.
When you are ready to test the
PuzzleProblem object, use the files
PuzzleProblemTest.js and
PuzzleProblemTest.html
on the menu at left. Correct test output is also shown.
This code uses
FarmerProblemTest.js
and
WaterJugProblemTest.js as models.
It should be placed in your newly created
PuzzleProblemTest.js
file.
This file should be placed into the
test folder of your NetBeans
project.
To run it, right click the file and select
Run File.
When it runs without errors, you are ready to add the puzzle domain to
the problem solver.
This section presents some suggestions for dealing with the 2D array
implementation of states that is used in the
original PuzzleState.java representation.
- Creating: Literal arrays can be created in JavaScript simply by using the
"[]" syntax. For example, the top row of the 8-Puzzle can be
created using "[2, 8, 3]"
Multi-dimensional arrays can use the same syntax. Here is an
initialization of a JavaScript variable to the 8-Puzzle start state:
- Processing: To process multi-dimensional arrays, use nested for
loops. If this.tiles is a 3×3 array:
- Copying: To efficiently copy JavaScript arrays, use the
built-in slice method. slice does not do a deep copy.
Therefore, if any array elements are also arrays (which they are
for 2D arrays), you need to copy not only the top level array but
also the rows individually:
(Note: slice also accepts arguments specifying how much of
the array to copy — thus its name.)
In the
PuzzleState.java class you were given, a
nested
Location class was used to hold row/column information,
and a
getLocation method was provided that returned
a
Location object for a given tile.
Javascript does not have classes, much less nested classes, but you can
achieve the same result with objects:
- Add a getLocation method in your PuzzleState
constructor function that accepts a tile number as argument and
processes the 2D array of tiles as just described
- When the tile is found, return a simple object using the literal
syntax below. Note that r and c are the
indexes used in your processing loop, and row
and column are property names for the object being returned.
- The object returned by getLocation reveals a tile's
row/column information in a state.
Here is
an example of its use:
Most likely, your
PuzzleMover.java class made use of a
second
PuzzleState constructor, that took a state and two
locations and returned a new state with the tiles at those locations
swapped.
You could try writing a second
PuzzleState constructor function
for this purpose, but I found it straightforward to add a
swap
method to the first constructor function that does the same thing. It:
- Takes two location objects as parameters
- Makes a deep copy of this.tiles
- Swaps the tiles at the two locations in the copy
- Returns a new state made up of the new tiles
Here is
an example of using
swap:
Now you are ready to add the 8-puzzle problem to the problem
solver.
- solve.html, shown to the right, is the top-level HTML file that,
when rendered, displays the problem chooser.
You need to modify solve.html so that your
files PuzzleState.js, PuzzleMover.js,
and PuzzleProblem.js are loaded along with the others.
-
Note the function given as value to window.onload.
It creates a list of problems that are given to the Chooser
constructor.
You need to modify the function so that a
new PuzzleProblem object is added to the list.
- Now when you run solve.html, it should present a chooser
that includes the 8-puzzle problem.
- Outside of NetBeans, re-zip (compress)
your JSProblemSolver folder as JSProblemSolver.zip.
- Submit JSProblemSolver.zip by going to
and clicking Submission under Lab Exercise:
JavaScript.
Note the general
Submission Policy in the menu at left.
Your project will be inspected, tested, and run by the lab instructor. Grading criteria:
- PuzzleState.js: 5 points
- PuzzleMove.js: 3 points
- PuzzleProblem.js: 2 points