Big Program 1: Sokoban
In this assignment, you will create a text-based Sokoban (Wikipedia: Sokoban) program. Sokoban is a classic
puzzle game from the early days of personal computers. You are a warehouse worker and you have to move
boxes to particular locations in a warehouse. The boxes are heavy and you can only push them.
A sample run of the finished program (interleaved input and output): SampleFinal.txt
As shown in the sample run above, the worker (denoted by ‘@’) is shown in a warehouse with impassable walls
(denoted by ‘#’). The worker must cover each goal (denoted by ‘.’) with boxes (denoted by ‘=’). The worker
can only push the boxes… so you have to navigate the warehouse carefully or you will get stuck! When a box
is placed on a goal, the symbol in the sample run is ‘*’. If the worker is standing on a goal, the symbol ‘+’ is
used. The exact characters to use will be specified in the Config.java file. So, your program should always use
the constant variable and not the literal character.
Grading Scheme: GradingBigPrograms.pdf - Be sure to read this fully.
Row-major order: In the design of this program, we will view the arrays as row-major order. For a 2-d array,
this means that the first dimension represents the rows and the second dimension represents the columns.
Files: Sokoban.java, Config.java and TestSokoban.java are provided.
● Sokoban.java -- Contains all the methods (as stubs) necessary for all three milestones of this program.
Detailed method headers are provided for you in the file. The implementation of each method must
meet the detailed descriptions in the method headers. Do not change the method headers!
● TestSokoban.java -- Contains a framework for your test bench.
● Config.java -- Whenever you need these values, use the constants defined in Config.java. The testing
may use different values for these constants.
BP1 Team
Students who wish to may work with at most one pair programming partner on Big Program 1.
1. Both students must read the Pair Programming Rules and Guidelines.
2. Both students must individually fill out the TEAM FORM requesting the other as their partner.
A. To use the above form, you need to be logged into the google account that is associated with your UW Netid. If you
see the message “You need permission” when following the link above, please 1) direct your browser to
google.com 2) click on the profile icon in the upper right corner of the screen and choose sign out, 3) then click “Sign
In” and use the link “Sign in with a different account” link at the bottom of the following screen, 4) from there you can
“Add an account” and use your netid-based wisc.edu email address to login to google. Doing all of this should allow
you to subsequently access the Team Form. linked to above. Please report any further problems on piazza for
troubleshooting assistance.
3. The TEAM FORM must be filled out before 6:00 pm on Thursday, Oct 25th (when Milestone 1 is due).
4. Both students must submit the team code to their own zyBooks account for grading. For
milestone 3, from zyBooks, we will pick one partner’s copy of the program to human grade and assign
both partners the same grade.
5. We suggest finding a partner at about your same programming knowledge and skill level.
6. We recommend working closely together (Pair Programming), not dividing up by milestones or steps.
The assignment is designed to be progressive, each step building the previous. If you skip a step, it
may be difficult to continue. Work closely together, discussing as you go.
Students are not required to work with another student on Big Program 1.
Project designed by Marc Renault.
Last update: 2018-10-08 1 of 7
Milestone 1: Basic Interface and Supporting Methods.
1. Create a new project in Eclipse. (Sokoban would be a sensible choice for the project name.)
2. Download Config.java, put in your project src folder and review the contents to become familiar with the
constants.
3. Understand the data structure: Before you start coding make sure you understand the array data
structures in Config.java.
a. Create a new file called MyLevels.java containing the class MyLevels (use Config.java as a
guide).
b. In the MyLevels class, define a LEVELS and a GOALS constant similar to Config.java. To
populate the LEVELS array, you will use the constants defined in Config.java.
c. Using your LEVELS and GOALS constants, create 3 new valid Sokoban (pass the checkLevel
checks) levels that are (in order) at least 3 by 3 with 1 goal, 6 by 6 with 2 goals and 9 by 9 with
3 goals. Since the arrays stored in LEVELS can be ragged, the minimum number of columns
means that at least one row should contain that number of columns. At the minimum, the 9 by 9
should be a ragged array.
4. Download Sokoban.java and TestSokoban.java and save them in your project src folder.
5. Best practice: Start by writing the tests.
a. Add at least 2 more tests to the testCheckLevel method. (Ideally, you would test every
possible return value.)
b. OPTIONAL: This is not required for the BP1 assignment, but ideally you would also create test
methods for promptInt, promptString,and promptChar. These methods require a
Scanner object. To do the automated testing, you can create a Scanner object from a String.
6. In this milestone, you will implement the methods: checkLevel, promptString, promptChar,
and promptInt. The suggested approach is as follows:
a. First implement checkLevel.
i. Use the test bench to check your method.
ii. Once it passes your test bench, submit to zyBooks to see if you pass zyBooks test 1.
b. Then, implement promptString, promptChar, and promptInt.
7. With the supporting methods written, you can write the basic main method with a play again loop. For
Milestone 1, an algorithm for the main method is:
Print out “Welcome to Sokoban!”
Begin the play again loop
● Call promptInt for the “Choose a level between 0 and maxLvl: ”, where maxLvl
is the maximum index in Config.LEVELS. The minimum value should be 0 and the maximum
value should be maxLvl.
● Check the level selected by the user using your checkLevel method.
● If the level is valid, print out “Sokoban Level lvl”, where lvl is the level selected by the
user.
● Prompt the user with “Play again? (y/n) “, using the promptChar method.
Exit the loop if the value of promptChar is not a ‘y’
Print out “Thanks for playing!”
8. Submit your Sokoban.java, TestSokoban.java and MyLevels.java files to zyBooks for feedback and
grading. We recommend you complete commenting and styling your code for each milestone as
described in the Program Grading section of this document. Your highest scoring results prior to
Project designed by Marc Renault.
Last update: 2018-10-08 2 of 7
6:00pm or (11:59pm with a 10% deduction) Thursday, October 25th will be recorded as your grade for
this weekly milestone.
Note: We may use different values in the Config.java for testing.
Milestone 1 Sample run: Milestone1.txt (interleaved input and output) [Milestone1In.txt, Milestone1Out.txt]
Project designed by Marc Renault.
Last update: 2018-10-08 3 of 7
Milestone 2: Printing and Using the Levels
1. Best practice: Start by writing the tests.
a. Add at least 1 more tests to the testInitBoard method.
b. Using the testCheckLevel and testInitBoard methods as templates, update the test
method stubs testCheckWin, testCalcDelta, and testCheckDelta by adding at least
1 test to each test method.
2. In this milestone, you will implement the methods: initBoard, checkWin, calcDelta,
checkDelta and printBoard. The suggested approach is as follows:
a. First, implement printBoard.
b. Then, implement initBoard.
i. Use the test bench to check your method.
ii. Once it passes your test bench, submit to zyBooks to see if you pass zyBooks test 1.
c. Then, implement checkWin, use the test bench to check your method, and submit to zyBooks
to see if you pass zyBooks test 2.
d. Then, implement calcDelta, and checkDelta, use the test bench to check your methods,
and submit to zyBooks to see if you pass zyBooks tests 3 and 4.
3. For Milestone 2, an algorithm for the main method is:
Print out “Welcome to Sokoban!”
Begin the play again loop
● Call promptInt for the “Choose a level between 0 and maxLvl: ”, where maxLvl
is the maximum index in Config.LEVELS. The minimum value should be 0 and the maximum
value should be maxLvl.
● Check the level selected by the user using your checkLevel method.
● If the level is valid:
○ Initialize the board and worker position by calling initBoard.
○ print out “Sokoban Level lvl”, where lvl is the level selected by the user.
○ Begin the game loop:
■ Print the board using your printBoard method.
■ Prompt the user with “: ”, using the promptString method.
■ If the user inputs no value, then loop again.
■ If the user inputs Config.QUIT_CHAR, then exit the loop.
■ Otherwise, call calcDelta using the value entered by the user and exit the loop.
● Prompt the user with “Play again? (y/n) “, using the promptChar method.
Exit the loop if the value of promptChar is not a ‘y’
Print out “Thanks for playing!”
4. Submit your Sokoban.java and TestSokoban.java files to zyBooks for feedback and grading. We
recommend you complete commenting and styling your code for each milestone as described in the
Program Grading section of this document. Your highest scoring results prior to 6:00pm or (11:59pm
with a 10% deduction) Thursday, November 1st will be recorded as your grade for this weekly
milestone.
Note: We may use different values in the Config.java for testing.
Milestone 2 Sample run: Milestone2.txt (interleaved input and output) [Milestone2In.txt, Milestone2Out.txt]
Project designed by Marc Renault.
Last update: 2018-10-08 4 of 7
Milestone 3: Playing the Game
1. Best practice: Start by writing the tests.
a. Using the testCheckLevel and testInitBoard methods as templates, update the test
method stubs testTogglePos, testShiftBox, testDoMove, and testProcessMove by adding
at least 1 test to each test method.
2. In this milestone, you will implement the methods: togglePos, shiftBox, doMove, and
processMove. The suggested approach is as follows:
a. First, implement togglePos, test, then submit to zyBooks to see if you pass zyBooks test 1.
b. Then, implement shiftBox, test, then submit to zyBooks to see if you pass zyBooks test 2.
c. Then, implement doMove, test, then submit to zyBooks to see if you pass zyBooks test 3.
d. Then, implement processMove, test, then submit to zyBooks to see if you pass zyBooks test
4.
3. With the supporting methods written, you can update the main method to play the game. For Milestone
3, an algorithm for the main method is:
Print out “Welcome to Sokoban!”
Begin the play again loop
● Call promptInt for the “Choose a level between 0 and maxLvl: ”, where maxLvl
is the maximum index in Config.LEVELS. The minimum value should be -1 and the maximum
value should be maxLvl.
● If the user enters in -1, choose a level from Config.LEVELS uniformly at random.
● Check the level selected using your checkLevel method.
● If the level is invalid, print “Error loading level!” followed by a newline, followed by the
error message that corresponds to value returned by checkLevel:
Let lvl be the level selected:
Value Error Message
0 Level lvl must be 0 or greater!
-1 Error with Config.LEVELS
-2 Error with Config.GOALS
-3 Level lvl does not contain any boxes.
-4 Level lvl does not have the same number of boxes as
goals.
-5 Level lvl has a goal location that is a wall.
-6 Level lvl has 0 or more than 1 worker(s).
-7 Level lvl contains duplicate goals.
Any other
value
Unknown Error
Project designed by Marc Renault.
Last update: 2018-10-08 5 of 7
● If the level is valid:
○ Initialize the board and worker position by calling initBoard.
○ print out “Sokoban Level lvl”, where lvl is the level selected.
○ Begin the game loop and loop until checkWin is true:
■ Print the board using your printBoard method.
■ Prompt the user with “: ”, using the promptString method.
■ If the user inputs no value, then loop again.
■ If the user inputs Config.QUIT_CHAR, then exit the loop.
■ Otherwise:
● call calcDelta using the value entered by the user.
● If the calculated delta is valid:
○ Call processMove with that delta
○ Add the number of moves in the calculated delta to a counter
subpanelvariable.
○ If the user won the game, print “Congratulations! You won in xNum
moves!”, where xNum is the number of moves counted during the game loop,
followed by the board (using your printBoard method).
● Prompt the user with “Play again? (y/n) “, using the promptChar method.
Exit the loop if the value of promptChar is not a ‘y’
Print out “Thanks for playing!”
4. Submit your Sokoban.java and TestSokoban.java files to zyBooks for feedback and grading. We
recommend you complete commenting and styling your code for each milestone as described in the
Program Grading section of this document. Your highest scoring results prior to 6:00pm or (11:59pm
with a 10% deduction) Thursday, November 8th will be recorded as your grade for this weekly
milestone and used for the human grading.
Note: We may use different values in the Config.java for testing.
Milestone 3 Sample run: SampleFinal.txt (interleaved input and output) [SampleFinalIn.txt, SampleFinalOut.txt]
Project designed by Marc Renault.
Last update: 2018-10-08 6 of 7
Appendix
Debugging Tips
● Write your tests first!
● Compile, run tests and run the program often! Think about doing this with each code change and each
completed method.
● Do your tests cover a breadth (ideally all) of possible scenarios?
● Do your tests check the boundary or edge cases?
● Do your tests cover valid, but unexpected, inputs?
● Make use of print statements!
● Have you gone through the tips on the CS Website: https://cs200-www.cs.wisc.edu/wp/help/#Tips
Extensions
The are many ways your might consider improving this Sokoban program. If you are interested in pursuing
these extensions or others that you might think of, please submit your fully completed Milestone 3 before
attempting any extensions. The instructional staff would be happy to review your extensions with you or
answer questions regarding extensions, but do not submit your extensions.
Change Log
● Initial version: 2018-10-08
Project designed by Marc Renault.
Last update: 2018-10-08 7 of 7