On this page:
Instructions
Problem 1: Knitted fabric
Problem 2: Sokoban, Part 3
8.14

Assignment 8: Iterators and Sameness, and Finishing Games🔗

Goals: Further practice with ArrayLists; mutable worlds.

Instructions🔗

The submissions will be organized as follows:

Due Date: Thursday, March 20th at 9:00pm

Problem 1: Knitted fabric🔗

In this problem you are going to design two distinct but related data definitions: one to describe knitted fabric, and another to describe the instructions needed to actually make a fabric. Read the entire problem carefully before starting; you might otherwise jump to conclusions that are not warranted.

A knitted fabric is made up of two basic kinds of stitches: knits and purls. On the front side of the fabric, a knit stitch looks like a V, while on the back side it looks like a -. Purl stitches are the opposite: on the front side of the fabric they look like a -, while on the back side they look like a V. A knitted fabric is made up of rows of these stitches, typically starting from the bottom and working upward (e.g. from the waistband of a sweater up to the neck), and combining different stitches in different pattern on different rows naturally produces different textures of results.

Design a class KnittedFabric (and any helper classes) to represent a knitted fabric. (Hint: your design should not need any fields of type String.) Your KnittedFabric class must include a constructor with zero arguments, to create an empty fabric.

Design a method KnittedFabric addRow(Iterator<IStitch> rowIter) that takes in an iterator of stitches, from left to right on the front side of the fabric, and adds that row of stitches to the current fabric — and then returns the current fabric, so that you can add another row to it easily.

Design a method String renderFabric that draws your fabric as a string of text. You can see some examples of rendered fabrics below.

Design a method sameFabric that checks if two knitted fabrics look the same. Keep in mind, you might be looking at the front side of one fabric and the back side of the other, but they might be the same fabric if you turn them both to face forward — the following two fabrics are the same:

VVV----V    and     -VVVV---
---VVVV-            V----VVV

Knitting instructions are a bit trickier. They follow a few rules:
  • Instructions are written for right-handed knitters, so the first instruction in a row is on the right edge of the fabric, and the last instruction in a row is on the left edge of the fabric.

  • A simple instruction for a row of fabric might say something like “Knit 3, purl 3, knit 1, purl 3.” This will produce the fabric ---V---VVV.

  • A fancier set of instructions might include grouping: “Knit 4, (purl 2, knit 2) 3 times, purl 4” would produce the fabric ----VV--VV--VV--VVVV. We can actually think of this grouping as extending to individual stitches: the simple instruction “Knit 3, purl 3” could be written as “(knit) 3 times, (purl) 3 times” instead. So there are really three kinds of instructions: knit, purl and repeat.

  • Knitting is typically worked from the bottom up, so the first row of instructions is the bottom of the fabric.

  • At the end of every row, knitters turn the fabric around, so that they’re now looking at the other side of the fabric. This swaps the left and right edges of the fabric, so that the first instruction of the next row produces a stitch that sits above the last stitch of the previous row. So for example, the instructions “row 1: knit 1, purl 5; row 2: knit 2, purl 4” will produce the fabric (looking at the front of the fabric):

    --VVVV
    -----V

    The first row is on the bottom, and is worked from right to left; the second row is above it, is worked from left to right, and the stitches are all backwards in appearance.

Design the class KnitFabricInstructions (and any helper classes needed) to represent knitting instructions for a full fabric. You should at minimum have classes that represent the three kinds of instructions, single rows of instructions, and an entire fabric’s worth of instructions. Your KnitFabricInstructions class must have a zero-argument constructor that creates an empty set of instructions.

Design a method KnitFabricInstructions addRow(Iterator<IInstruction> instructions) that adds a row of instructions to the growing fabric. Note that the instructions should be interpreted based on whichever side of the fabric is next: either right-to-left instructions for a front-side row, or left-to-right instructions for a back-side row. Like the other addRow method, this one will return the current set of instructions, so that you can continue add more rows of instructions.

Design the method KnittedFabric makeFabric() that follows the instructions and generates the knitted fabric result. (Hint: you will likely want an accumulator parameter in a helper method somewhere; that accumulator likely will be a boolean; you may need other accumulators or other helpers as well.)

Design the method boolean sameInstructions(KnitFabricInstructions other) that decides whether this set of instructions and that set of instructions will produce the same final fabric. As a tiny example, “knit 3, purl 3, knit 3, purl 3” will produce the same fabric as “((knit) 3 times, (purl) 3 times) 2 times.”

Problem 2: Sokoban, Part 3🔗

In the previous part of Sokoban, you implemented player and item movement rules, added pit-traps, and extended the game-over check to account for losing the player down a pit. In this week’s exciting conclusion, you’ll add a new floor tile, and add a way to fix mistakes.

Ice patches:

Exercise

We add a new kind of tile: ice:

image

Ice tiles have no traction: if a player steps onto one, they will slide in that direction until they collide with an immovable item, or until they land on a non-ice tile. If, while colliding, they crash into a movable item, then the movable item starts sliding too. Here’s a tiny demo level to get you started, and the results of the player moving right twice:

image

image

image

And here’s a more fun introductory level to try

image

We are deliberately not specifying every possible behavior here, or every possible interaction of items, ice, player motion, and immovable things. Here are a few scenarios worth considering, and worth making a deliberate design choice for (there are several others worth considering as well!):

  • In the first sample level, what if the trophy started on the ice? Would it matter which ice it started on?

  • Two adjacent movable objects on the ground are considered too heavy to move. But what if one or both of them are already on ice?

  • As a comic possibility: suppose you had a “slip-n-slide” of an ice runway followed immediately by a pit trap. Consider various combinations of items already on the ice, and decide their behavior.

Come up with small tutorial levels (i.e., test cases) to demonstrate the behaviors you decide upon. Be thorough. Leave comments in your code, near where you define the data for each level, that explain what scenario you want to test and why it’s interesting.

Keeping score:

Exercise

Add a step counter to keep track of the number of steps a player has made. Show the score somewhere on-screen. Lower scores are better!

Fixing mistakes:

Exercise

It’s far too easy to mistype and cause the player to take one too many steps, such that the game is no longer playable. Add an undo feature, that lets the player type "U" in order to rewind the game by one step. (Note that this should increase the player’s score! Undoing a bad move should not also rewind their score to something better.) Make sure that the game does not crash if the player tries to undo when there are not currently any moves to undo.

Have fun!

You might find some levels at https://www.sokobanonline.com/play/lessons/ to be fun — they do not necessarily have exactly the same rules of movement as we do in this assignment (especially for ice), so it might be interesting to try some of their levels, try coding them up as examples in your own game, and playing them to see if you can solve them in your game as well.

Submission instructions:

As with prior parts, you should submit an updated UserGuide.txt and Design.txt that describe how a user should play your game, and how a developer should read and understand your code. Make sure you submit all the necessary source and image files that your graders need in order for them to run your games.

There will likely be a self-eval questionnaire the day after this assignment is due. Much like the peer evaluations asked you to review each other’s code, this self-evaluation will ask you to justify your design choices against your Design.txt explanations, and to guide your graders to understand where to find particular test cases, examples, or other implementation choices.