In this assignment you will add screens to the app you created in the Android lab exercise (see menu at left) that allow the user to solve the Farmer, Wolf, Goat and Cabbage (FWGC) and 8-Puzzle problems.

This will involve porting the non-GUI aspects of your Java ProblemSolver project to your Android ProblemSolver project.

Project requirements are described next.

In the lab exercise you created description screens for the FWGC and 8-Puzzle problems that provided buttons for launching the problems, but the buttons were non-responsive.

For this assignment, when the user clicks one of these buttons, a solver screen is presented.

See the menu for layout and behavior requirements.

When the user begins a problem, a screen is presented that includes: See the menu at left for examples.
Behavior requirements with examples are shown through the menu at left.
If an attempted move is illegal, an error message is displayed.

In this FWGC example the user clicks TAKES WOLF in the start state.

If the user solves the problem, a congratulatory message is displayed as shown below.

If the user presses the Reset button:

This reset behavior is possible any time during step-through of an automated solution. In addition, any components disabled during a step-through are re-enabled.

The Solve button is enabled any time the user is trying to solve the problem.

When Solve is pressed:

See the menu at left for examples.
Here the user has clicked Solve in the start state of the FWGC problem.

Note that although the move buttons are not dithered out, they are indeed disabled. This appears to be an Android glitch.

Here the user has clicked Solve in the start state of one of the 30-move benchmark problems for the 8-Puzzle.

While stepping through a solution, the Solve and move buttons remain disabled, and the solution statistics remain visible.

Clicking Next causes:

Clicking Reset causes:

See the menu at left for examples.
Here the user has stepped through one move in an automatically generated solution from the start state.

Note that the TAKES GOAT move has been highlighted.

Here the user has stepped through 23 moves in an automatically generated solution to one of the 30-move benchmark problems for the 8-Puzzle.

The 8-Puzzle benchmarks are the same as used for the previous assignment (shown in menu at left).

Below is how it looks when the Benchmarks spinner has been clicked. When a benchmark is selected the new current state is displayed and the move count set to zero.

For extra credit, add Solve and Next buttons:
This section presents screen shots following those of the Android lab exercise.
The initial solver screen for the FWGC problem is shown below. Note:

The initial solver screen for the 8-Puzzle problem is shown below. The Benchmarks spinner is described later.

This section offers suggestions for screen layout and implementing the required behavior.
The solver screens have similar structure but different content depending on the problem. Here are two possible approaches to creating them:
An alternative is a "hybrid" approach that uses Studio's editor to create the top-level designs of the solver screens but includes containers that can be populated by Java code.

The menu at left shows layouts created with Studio's editor. There is some layout duplication, but there are aspects that are incomplete:

We leave these responsibilities to Java code because we have FarmerProblem and PuzzleProblem classes that facilitate them.
You should read through these suggestions in their entirety before beginning to code.

The suggestions end with hints regarding code organization and testing.

Giving Android buttons and spinners behavior is done with Java (or Kotlin) code. We want to take full advantage of the Java problem solving framework that we already have.

Each of our solver screens has its own activity class that has code that responds to screen events and updates screen content.

For example, your activity classes might be FarmerSolveActivity and PuzzleSolveActivity:

This requires you to reuse packages from your NetBeans JavaFX project.
In order to use problems, movers, and states, you should port the following packages from your JavaFX project to your Android app: although you can omit the console and GUI classes, which depend on JavaFX.

For automated solutions, you will also need:

Place these packages under app > java > ...problemsolver in your project tree.

You will have to change the package statements in your .java files from, for example, to something like: depending on the domain you chose when you created the project.

The SolvingAssistant class took advantage of a JavaFX problemSolved property to indicate whether the problem had been solved.

Recall that JavaFX properties are enhanced POJO (plain old Java object) properties.

If you want to use SolvingAssistant in Android it will have to be modified so that problemSolved is a POJO property. This can be done with some relatively simple changes:

IMPORTANT: The suggestions and code samples that follow use the FWGC problem. However, everything described here will need to be duplicated for the 8-Puzzle problem.
Suppose your FWGC layout includes a TextView component with id farmer_solve_start that holds the string representation of the current state.

Although you can use the Studio editor and strings.xml to initially get text into farmer_solve_start, as the user attempts to solve the problem we need to get text into the component under Java program control.

We can use the onCreate method in FarmerSolveActivity (and also in PuzzleSolveActivity with appropriate changes) to initialize a Java object to the component:

Now we can change the text in startView when the user attempts a move:

The onCreate method, since it has access to a FarmerProblem object and therefore a FarmerMover object, can get a list of move names. So, Suppose your FWGC layout includes a vertical LinearLayout component with id farmer_moves that is to hold the move buttons.

Then onCreate can get the layout component, which at the time will be empty:

Now you can loop through the list of move names to create buttons and add them to the layout. Here is the structure of a method that creates and returns a button given a move name:

Once created, a button can be added to the layout:

The Button constructor, like all View constructors, requires an application Context.
If you used the SolvingAssistant class from the framework.solution package when you implemented your JavaFX ProblemGUI class, you can use it in the same way in your Android move button listeners: The move button listener will need to update the current state display (described earlier) and possibly display an Illegal Move or Congratulations message.

For these messages, the onCreate method should obtain the message view. For example:

Messages should be defined in strings.xml. Suppose the "Congratulations" string is given the name "congrats". Then the move button listener can retrieve the string with:

where context is the application context. Then the message can be displayed with:

Similar considerations apply to the Reset button. Although it can be created and positioned using the drag-and-drop editor, its behavior is configured in its activity class.

Suppose the Reset button's component id is farmer_reset. Then the onCreate method will need to include:

Clicking the Solve button must result in an optimal solution to the current problem.

So the onCreate method for each activity class should:

The Solve button listener should: The Next button listener should:
Unless you created the benchmark spinner component using the drag-and-drop editor, the onCreate method can do so with:

To give the spinner selection options:

After giving benchSpinner a listener (see menu), it can be added to the layout using addView.
Now give the spinner an OnItemSelectedListener using the code below.

As mentioned, all steps mentioned in these suggestions must be repeated for each of the FWGC and 8-Puzzle problems.

Rather than having nearly identical (and extensive) code in the onCreate methods of your FarmerSolveActivity and PuzzleSolveActivity classes, some suggestions for code reuse and incremental testing follow.

The onCreate methods differ only in: The beginning of onCreate in FarmerSolveActivity may look like:

while the beginning of onCreate in PuzzleSolveActivity may look like:

In your JavaFX problem solver, the framework.ui package has a ProblemGUI class that uses JavaFX to create GUIs given problem objects.

Your Android problem solver could also benefit from a ProblemGUI class, added to its framework, that performs the processing outlined in these suggestions.

For example, ProblemGUI's constructor could have this structure:

Now all the work is done, not by the onCreate methods, but by the ProblemGUI constructor.

The constructor would be called in FarmerSolveActivity's onCreate method using:

The constructor would be called in PuzzleSolveActivity's onCreate method using:

To keep your code organized and to facilitate testing, the ProblemGUI constructor can call private helper methods that incrementally add functionality to the layout.

For example, the body of the constructor might call the helper methods shown below. As their names suggest, they can be developed and tested in the order in which they appear.

See the procedure for submitting Android projects on the menu to the left.

Your project will be inspected, tested, and run by the lab instructor. Grading criteria:

For extra credit, add the 15-Puzzle to your problem solver, as shown in the opening screen below. Additional details are in the menu at left.

The welcome screen for the problem is very similar to the 8-Puzzle:

However, it would be awkward to layout and use fifteen buttons, so for this problem we will dispense with the moves, including only the solving controls:

The benchmarks named in the spinner options shown below are the same as those used before (shown in menu at left—note that benchmark "15-Puz 8," with a 54-move solution, may run out of memory in Android).

In the screen below left, benchmark "15-Puz 7," with a 50-move solution, has been selected and solved. In the screen below right, the solution has been stepped through.