On this page:
Instructions
Problem 1: Visitors
Problem 2: Sokoban, Part 1
Sokoban
Submission notes
8.14

Assignment 5: Building a game; Visitors🔗

Goals: To build a non-trivial Big-bang game from scratch, and practice with visitors

Instructions🔗

Be very, very careful with naming! Again, the solution files expect your submissions to be named a certain way, so that they can define their own Examples class with which to test your code. Therefore, whenever the assignment specifies:
  • the names of classes,

  • the names and types of the fields within classes,

  • the names, types and order of the arguments to the constructor,

  • the names, types and order of arguments to methods, or

  • filenames,

...be sure that your submission uses exactly those names.

Make sure you follow the style guidelines that Handins enforces. For now the most important ones are: using spaces instead of tabs, indenting by 2 characters, following the naming conventions (data type names start with a capital letter, names of fields and methods start with a lower case letter), and having spaces before curly braces.

You will submit this assignment by the deadline using the Handins submission system. You may submit as many times as you wish. Be aware of the fact that close to the deadline the Handins system may slow down to handle many submissions - so try to finish early.

There will be a separate submission for each problem - it makes it easier to grade each problem, and to provide you with the feedback for each problem you work on.

The submissions will be organized as follows:

Due Dates:
  • Problem 1, arithmetic visitors: Friday, Feb 14th, at 9:00pm

  • Problem 2, Sokoban implementation: Friday, Feb 14th, at 9:00pm

  • Problem 2 peer review: Saturday, Feb 15th, at 9:00pm

Problem 1: Visitors🔗

In a new file Visitors.java, implement the following class diagram:
      +-------------------+
      | IArith            |
      +-------------------+
      +-------------------+
          /_\       /_\
           |         |------------------------------------------------------
           |         |                                                     |
+-------------+   +------------------------------+   +-----------------------------------------+
| Const       |   | UnaryFormula                 |   |              BinaryFormula              |
+-------------+   +------------------------------+   +-----------------------------------------+
| double num  |   | Function<Double,Double> func |   | BiFunction<Double, Double, Double> func |
+-------------+   | String name                  |   | String name                             |
                  | IArith child                 |   | IArith left                             |
                  +------------------------------+   | IArith right                            |
                                                     +-----------------------------------------+

Specifically, the above represents an arithmetic expression. The Function and BiFunction in UnaryFormula and BinaryFormula respectively denote the arithmetic operation to be applied to their respective operands (child and left,right). In class, we defined these interfaces as IFunc and IFunc2, but they’re actually predefined for you in Java. To use them, you will need to write import java.util.function.*; at the top of your file among the other import statements. As in class, these interfaces require that you implement a method named apply, whose parameters are (in this problem) all Doubles.

You must support 4 binary formulas (named "plus", "minus", "mul" and "div" representing addition, subtraction, multiplication and division respectively), and 2 unary formulas (named "neg" and "sqr" representing negation and squaring respectively).

Problem 2: Sokoban, Part 1🔗

Sokoban🔗

We’re going to build Sokoban, a logic/puzzle game created in 1981, over the next few weeks. There are many variations on this game in existence, so we’ll be adding features as we go. Adding features may mean that you have to redesign earlier parts of your code, so the cleaner your initial design is, the easier it will be to modify later. Spending time early on careful, clean design will pay off!

A Sokoban level is played on a rectangular grid of square cells. For now we’ll only consider a few kinds of cells; we’ll add more later. Several things could be in a cell: nothing at all, the player, a brick wall, a crate, a trophy, or a target. (We’ll add more possible things in later assignments.) Here is an example board:

image

The goal of the game is to get all the colored trophies onto their similarly colored targets: as in the example above, your game should support four colors; our implementation uses red, green, blue and yellow. Some things in the game can move: crates, trophies, and the player. Others are fixed: the targets, and brick walls. You can play the original, classic version of the game at https://www.mathsisfun.com/games/sokoban.html, but be aware that this version only has movable crates, which behave like the trophies in our version of the game (i.e. the crates need to be placed on the targets).

Exercise

Design data definitions sufficient to describe the board state. The board above can indeed be thought of as rectangular: there are just a lot of blank cells and the brick walls just happen to enclose a smaller region of the board. You will need several helper data definitions. Note that different boards could easily be of different sizes, so your definitions should not limit themselves to a specific size of board. Be sure to follow the design recipe for all of them, and create sufficient examples. Your data definitions should accommodate new features in the future, so be careful not to make your designs too inflexible.

It will be convenient to have an easy way to write down board levels as text. Let’s distinguish things-on-the-ground from things-in-a-cell:

Then we could write the example level above as
String exampleLevelGround =
"________\n" +
"___R____\n" +
"________\n" +
"_B____Y_\n" +
"________\n" +
"___G____\n" +
"________";
String exampleLevelContents =
"__WWW___\n" +
"__W_WW__\n" +
"WWWr_WWW\n" +
"W_b>yB_W\n" +
"WW_gWWWW\n" +
"_WW_W___\n" +
"__WWW___";

Exercise

You should design a class to represent a Sokoban level. One of the constructors for your class should take in level-description strings like these, and use them to configure the level — it will likely be easier than trying to write out the IList of contents by hand.

Exercise

Design a method on your class to render it as an image. You do not need to use precisely the same images as we have here, but if you’d like to, you may copy these images and use them:

imageimageimageimageimageimageimage

Save them to your project’s directory, and use the FromFileImage class to create WorldImages from them.

Exercise

Design a method levelWon that detects if the player has won the level: it should check that every target has a trophy on top of it, whose color matches the target’s color. Note: you can design Sokoban levels where there are more trophies than targets, so you do not need to check if every trophy is on a target. (The converse, where there are more targets than trophies, is simply an unwinnable board.)

Exercise

Design a class that subclasses javalib.funworld.World, that contains a starting Sokoban level and that lets the player move in any direction. For now, ignore the full rules of the game: a player can move to any adjacent empty cell.

Hint: Describing a rectangular grid is best done using a list of lists. Creating large lists of lists may be quite tedious. Abstract out the convenience method above that takes in the string of ground-content and the string of cell-content and produces the requisite list of lists; test that method with several small but plausible examples; and then use that helper to build larger test cases.

Hint: it likely makes sense to have two separate classes, one that subclasses World and handles keypresses and such, and one that represents your game logic. Combining these into a single class risks making that class bloated and hard to read.

Submission notes🔗

Don’t make the game overly elaborate; we are more interested in your program’s design than your graphic design! Include two additional files in your submission:

Be sure to include all your source files and all your image files in your submission, or else we won’t be able to run your game. You should submit the files as a single .zip file. Zip up your source directory and your images – don’t include the out/ or target/ directory where Eclipse puts your compiled code.