Stop! Please be sure you fully read and finished doing all tasks in Homework 0: Introduction and Environment Setup and Homework 0: Explosive Debugging before continuing.
This is the main part of Homework 0, and it is intended as a refresher to help you review concepts so you can jump right into the CIS 1210 material and be successful. It is also meant to introduce you to the types of problems we will explore and solve in CIS 1210 – mainly data structures and algorithms.
We have put together several stub files –– click here to download them.
2 files to submit: MazeSolverImpl.java
and MazeSolverImplTest.java
Please do not submit any additional files.
Be sure to follow these guidelines:
package src;
).[compilation]
, and
two free submissions on the autograder marked [full]
.[full]
autograder that get 0 points (usually due to forgetting or misnaming a file) do not use up a submission.You will submit this and all future programming assignments on Gradescope. You should have been automatically added to Gradescope, and received a confirmation email if you are an enrolled student. If you are not yet enrolled in Gradescope, please email cis1210@seas.upenn.edu with your full name and the email address associated with your Gradescope account. Here are full details on how CIS 1210 has set up autograders on Gradescope. Please make sure you read through this carefully!
[compilation]
Autograder[compilation]
, you will have unlimited submissions.[full]
Autograder[compilation]
autograder does, and if your files compile, it
will report your full autograder grade.[full]
, you will have two free submissions. Each additional submission
will cost you 5pts. If you would like to check if your code compiles / if you would receive no deductions
for style and code coverage, you can use the [compilation]
autograder for that.Important: Only what you submit to the [full]
autograder will be graded! That is, you must submit to the [full]
autograder by the submission deadline – no exceptions will be made.
Follow these instructions to submit your programming assignment: 2. You should see [COMPILATION] HW0: Maze Solver
and [FULL] HW0: Maze Solver
.
Clicking on these will open a window where you can submit your files. 3. Either drag and drop the required files listed above, or browse and
select them on your computer. Do not upload a zip file of a folder
containing the files. 4. Click “Upload”. 5. Wait for the autograder to finish executing. This will take 1-5 minutes.
Make sure there were no errors that appeared. If you see an error, try
reading it and see if you can diagnose the issue yourself. Usually it’s
forgetting to submit a file, modifying our method headers, or submitting
failing test cases. If you receive a “Test Suite Error” upon submitting, this is
a likely indication that your code is timing out on our autograder. 6. Be sure to submit to the [full]
autograder once you’re ready! This is the
only one we will grade.
Gradescope issues? Be sure to check out our Gradescope help page before posting to Ed Discussion.
Understanding the problem is the first step to solving it. Take time to read through this writeup and the Javadocs for the provided interface before starting. Familiarize yourself with Java syntax and the style conventions outlined in the course website. Go over the requirements this homework and plan things out before you start writing code.
This assignment will give you the opportunity to learn how to write proper unit tests. Be sure to read the testing guide for some pointers on what level of testing we expect from you.
Big changes from CIS 1200: The code you write in this course will allow for more freedom than in CIS 1200. You will be given interfaces to implement, rather than stub files to fill, which means that you have more freedom over implementation. You will have to make conscious code decisions and eventually defend the efficiency of your code in future assignments. More importantly, you must be confident in your unit tests. Unit testing is a critical skill that allows you to be confident in the accuracy of your code, and building good practices now will carry a long way through your computer science careers.
Files to submit: MazeSolverImpl.java
and MazeSolverImplTest.java
In this section, you will be implementing an algorithm to solve a maze and find a path from an arbitrary starting point to a goal state. Later on in the course, you will learn other ways of solving this problem, but for now we’ll stick with this current implementation as an introduction. We’ll revisit this problem later in the semester.
Why are we writing a program to solve a maze? There are many applications of this algorithm for problems in robotics and other areas of AI which require “exploration” techniques such as the one seen here, and additionally the point of this exercise is to get you re-familiar with recursion.
Coordinate
ClassYou’ll note in the stub files you downloaded that we provided the Coordinate
and CoordinateTest
classes.
The Coordinate
class serves as a wrapper class to make dealing with coordinates easier when
implementing your MazeSolverImpl
solution as well as encourage Object Oriented design.
We’ve fully annotated both files, and highly recommend reading through them thoroughly to understand
what the Coordinate
class is and see an example of how we expect you to test your code.
You may use the class as you see fit, however:
Do not modify the Coordinate
or CoordinateTest
classes. Doing so may cause your solution
to not compile on our autograder.
To make this problem more concrete, we will assume the maze consists of an $m \times n$ grid, where each cell is either open (white) or blocked (black). You can only pass through open cells, and if you bump into a blocked cell or a cell outside the maze you must try a different direction. Positions in the maze are labeled with $(x,y)$ coordinates, with $(0, 0)$ being the top left corner and $(n-1, m-1)$ being the bottom right corner.
You can move in the following 4 directions:
Recall from CIS 1200 that a recursive algorithm always has the following 2 parts: base case(s) and recursive call(s). If you don’t remember recursion, it might be a good idea to stop here and go back to your CIS 1200 notes and review those first.
Since you have not taken CIS 1210 yet, you decide to try the following systematic recursive procedure, which you know is guaranteed to work as it exhausts all possible paths!
There’s just one detail we missed. Consider coordinate $(0, 1)$ in the $10 \times 10$ maze above. Currently, our algorithm will run into an infinite loop switching between $(0, 1)$ and $(0, 2)$. Therefore, we need to remember which cells we have visited before in order to avoid this issue. Luckily for us, recursion helps us keep track of that with little additional storage. How? We’d like you to think about that!
Let us now hint you towards some base cases. We will need to consider 4 of them. Hopefully after reading the instructions above, you came up with some of these on your own:
Now, putting everything together, here’s a GIF showing how we expect your code to procedurally explore the sample maze presented earlier.
Hopefully this GIF clears up some of the confusion about the procedure! Please don’t analyze this GIF to test if your code is correct, but instead use it to make sure that your understanding of the problem and procedure is correct.
Now, that we have provided you with an outline of the algorithm, it’s up to you to fill in the missing details and
implement the maze solving algorithm!
We’d like you to implement the following method header:
public static int[][] solveMaze(int[][] maze, Coordinate sourceCoord, Coordinate goalCoord) {
// TODO: implement.
}
int[][] maze
: The $m \times n$ maze will be represented as a 2d-array where 1s represent blocked
cells, and 0s represent open cells. You may assume that the maze will be rectangular (i.e., not ragged) and that sourceCoord
and goalCoord
are non-null.
Here is an example of a $4\times 4$ maze:
int[][] maze = {
{0, 0, 0, 0},
{1, 1, 0, 0},
{0, 0, 0, 1},
{0, 0, 1, 0}
};
As mentioned before, we will be using a row-major order coordinate addressing scheme, which means that
when getting a value, we first index into the correct row, and then index into the column. In general,
the $(x, y)$ coordinate of the maze corresponds to maze[y][x]
.
For the example maze above:
sourceCoord.getX() = 0
sourceCoord.getY() = 0
goalCoord.getX() = 0
goalCoord.getY() = 2
You should throw an IllegalArgumentException
in the following cases:
int[][]
: You should output a 2d-int array which contains 1s along the solution path from S $\to$ G,
and 0s everywhere else. If no solution is possible, you should return null
. Since we have required a very
specific iteration sequence from you, there will only be one correct solution. Please follow our algorithm closely.
Here is an example of the maze shown above:
int[][] solutionPath = {
{1, 1, 1, 0},
{0, 0, 1, 0},
{1, 1, 1, 0},
{1, 1, 0, 0}
};
Note that the solution path above is not the shortest path, and it does not have to be. This is the path you get if you follow the down, up, left, right order when traversing the maze. Later in the course, you will learn how to find the shortest solution path. Like we said before, we will be revisiting this problem multiple times throughout the semester.
Please note that this should not serve as a replacement to extensive unit tests.
For this assignment, we have provided a visualizer for you to test your
implementation of the maze solver. To run the visualizer, run the MazeSolverVisualizer.java
class.
The format to import a maze is as an $m\times n$ grid of 0s and 1s. The small example in the writeup is:
0000
1100
0001
0010
Our visualizer also has the ability to guess the format of the input, so just copy and pasting the code used to generate the array in your test cases should be fine, e.g.,
{1, 1, 1, 0},
{0, 0, 1, 0},
{1, 1, 1, 0},
{1, 1, 0, 0}
If you run into any difficulties using the visualizer, please post on Ed Discussion.
Known issue: Student using macOS may encounter a problem with failing to paste text into the text area when importing a maze.
The above parts together are worth a total of 30 points. Style and code coverage are graded on a subtractive basis with deductions as specified in the Setup and Logistics section of the writeup, and you will be graded according to the CIS 1210 style guide. Gradescope will give you your grade on this section immediately upon submission to either autograder.
IMPORTANT: Please DO NOT use any external files (.txt, etc.) to write your JUnit tests for this assignment. Our code coverage tool will fail, and you will not be able to submit your code due to failing test cases.
You will need to write comprehensive unit test cases for each of the classes, inner classes, and methods you implement (including helper methods!) in order to ensure correctness. Make sure you consider edge cases and exceptional cases in addition to typical use cases. Use multiple methods instead of cramming a bunch of asserts into a single test method. Your test cases will be auto-graded for code coverage. Be sure to read the testing guide for some pointers on what level of testing we expect from you. Finally, due to the Code Coverage tools we use, please be sure to use JUnit 4 as it is the only version supported.
Note: You will not be able to write JUnit test cases for any private
methods. Instead, make them package-private by leaving off any privacy modifier
(i.e., do not write public
or private
).