$29
PROGRAMMING II
This assignment involves developing a textual Fish Tank Simulation in which fish <((' are
swimming to the right. Fish food * is float down and to the left. And a fish hook is being pulled
straight up from the bottom of the tank. The code that is developed for this assignment will also be
used as the basis for future programming assignments, so be sure to keep your code clean, clear, and
well commented. Here’s what one frame of this animation will look like when you are done.
Objectives and Grading Criteria
The goal of this assignment is to review writing code in a procedure-oriented style. This code
utilizes basic control structures (conditions and loops), primitive data types, Strings, and multidimension arrays. It also requires defining and calling custom methods.
Grade Breakdown:
50
points
10x zyBooks Tests: automated grading test results are visible upon submission, and
allow multiple opportunities to correct the organization and functionality of your code.
P01: SWIM SIM (TEXT)
1
2
3
4
5
6
7
8
~~~~~~~~~~~~~~~~~~~~~~~~*~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~J
~~~<(('~~~~~~~~~~~~~~~*~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~<(('~*~~~~~~~~~*~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~<(('~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
LECTURE NOTES
Your highest scoring submission prior to the deadline will be recorded.
GETTING STARTED
0. If you haven’t already, either Install Eclipse with Java 8 on your computer, or find a computer
that they are already installed on.
1. Then create a new Java8 project within Eclipse. You can name this project whatever you like, but
P1SwimSim is a descriptive choice. Then create a new class named Main with a public static void
main(String[] args) method stub. This process is described near the end of the Eclipse
installation instructions here.
2. The code that you write for this and future assignments will rely on some provided resources.
Download the file SwimSim.jar and copy it into your project folder. Then right-click on this file
in the “Package Explorer” within Eclipse, and choose “Build Path” and then “Add to Build Path”
from the menu.
3. To test that everything is working and you are ready to proceed, try running your program with
the following the print statement to your main method.
If everything is working correctly, you should see a (potentially different) random number
between 1 and 6 print out every time the program is run. Please consult piazza or one of the
consultants, if you have any problems with this before proceeding. After it is working, you can
remove the suggested test statement from your code.
CREATING THE TANK
4. We will be storing the contents of our fish tank in a two-dimensional array of characters that
you’ll instantiate from inside the main method. This array will hold 8 rows of characters, with 32
characters in each row.
5. After creating this array, we’re going to define and call two methods: one method to fill this array
with tilde (~) water characters, and another to draw the contents of this array out to the console.
Here are the signatures and javadoc comments for these two methods:
1 System.out.println( Utility.randomInt(6) + 1 );
1
2
3
4
5
6
7
8
9
10
11
12
/**
* Copies the water character into every position in the tank array. The two-dimensional ta
* array can have dimensions of any size(s).
*
* @param tank will contain all water characters after this method is called.
* @param water is the character copied into the tank.
*/
public static void fillTank(char[][] tank, char water)
{
}
After defining and calling these methods, you should see a 32×8 rectangle of tilde (~) characters
print out after running your program.
Note that we could have drawn a rectangle of tildes without needing this array.
However this random access array will begin to pay off as we start adding and
moving fish around this tank.
ADDING FISH
6. Next we’ll create a two dimensional array to store the positions of our fish in. In addition to our
randomly positioned fish, we’ll be adding randomly positions fish food and fish hooks in the
future. So lets create a method to generate an array of as many random positions as we’d like.
Here’s the signature for this new method:
The first parameter “number” represents the number of different random positions that this
method should generate. The width and height are the bounds for how large the x and y
coordinates of these random positions may be (they must be smaller than these bounds, and nonnegative integers). Use the Utility.randomInt() method that we tested earlier to generate these
random position coordinates. The positions generated by this method are then returned as the
rows of a two-dimensional array, where each row contains an x position (0 referencing the
leftmost column of the tank, widht-1 referencing the rightmost column) followed by the y position
(0 referencing the top row of the tank, height-1 referencing the bottom row). Here’s an example
of how these values might be laid out in the array:
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/**
* Prints the contents of the tank into the console in row major order, so that the
* smallest row indexes are on top and the smallest column indexes are on the left. For
* example:
* tank[0][0] tank[0][1] tank[0][2] ...
* tank[1][0] tank[1][1] tank[1][2] ...
* ...
* Each row is on its own line, and this method should work for two-dimensional tanks with
* dimensions of any size.
*
* @param tank contains the characters that will be printed to the console.
*/
public static void renderTank(char[][] tank)
{
}
1
2
3
4
public static int[][] generateRandomPositions(int number, int width, int height)
{
}
1
2
3
int[][] posA = generateRandomPositions(3,4,100);
// a call like this could generate a result like the following:
int[][] posB = new int[][] {
After implementing this method, it can be called from the main method to instantiate and
initialize an array of fish positions. We want 4 fish positions that are all within the bounds of the
tank. Be sure to reference the tank array’s dimensions in this code, rather than hard-coding the
dimensions 32×8.
7. Now we need a method to draw the fish at these positions within our tank array. This will happen
after generating the positions and before drawing the tank’s contents to the console. The method
that we will create to do this will be called placeFishInTank and it will take three parameters in
the following order: the tank 2d array of characters that the fish should be drawn into, the int xposition or column that the head of this fish should be drawn to, and the int y-position or row
that the head of this fish should be drawn to. The fish’s head will be drawn as a greater-than
symbol (), to the left of this will be an apostrophe (') for an eye, and to the left of that the rest of
the fishes body. The complete fish should look as follows <((' If part of the fishes body
extends off the left edge of the tank, you can either skip drawing that part of the fishes body or if
you’d like a bit more of a challenge you can draw that part of the fishes body on the opposite side
of the screen to produce the appearance of wraparound. Ensure that you can see the four fish
drawn to the tank when running this program, and remember that it’s possible for the fish to
occasionally overlap since their positions are being randomly generated. For additional
challenge, you are welcome to extend your generateRandomPositions() method to avoid placing
any two fish at the same position.
8. With our fish in the tank, it’s time to get them swimming. We’ll implement a new method called
moveAllFish() to help us with this. This method will take the following parameters (in order): the
2d array of fish positions, the width of the tank the fish are swimming in, and then the height of
that tank (note that we won’t use this height until a future step). The computation that this
method will perform is that it will move every fish position one character to the right of where it
used to be. But whenever a fish moves off the right edge of the screen (from column width-1 to
column width), they should instead be moved to column 0 to produce a wraparound effect. This
will allow us to moveAllFish repeatedly and ensure that they are still always visible in our
simulation, as if they were swimming laps in around the edges of an aquarium. After
implementing this method, we need to revisit the main method to setup the main-loop of our
simulation. Here’s the pseudocode for that main-loop:
4
5
6
7
8
{ 3,21 },
{ 1,97 },
{ 1,45 }
};
// three positions with xs from [0,4) and ys from [0,100)
1
2
3
4
5
6
// create the tank
// generate fish positions
// repeat forever:
// update the simulation by:
// moving all fish one position to the right
The provided Utility.pause(200) method helps add an extra 0.2 second delay between iterations
of this simulation, which makes it easier to see what is changing. There are also a few newlines
being printed out after each of these pauses, to help make it clear where one frame ends and the
next begins. The resulting animation is produced in a similar fashion to flip books.
ADDING FOOD AND A HOOK
9. Now that we have the fish moving, we’d like to add some fish food (so they don’t starve) and a fish
hook (so their lives aren’t too boring). Think about how you would organize these additions
within the existing code base before following these instructions to implement the new features.
a. The generateRandomPositions() method that you already implemented can be re-used to
generate the positions of any kinds of objects within the tank. Use this method to generate
random positions for six fish food and one fish hook. Even though you only need one hook
at this time, keep it’s position in a two-dimensional array like the fishes and foods. This will
make things easier for us through the next two steps.
b. In order to see these objects, we could create methods similar to our existing
placeFishInTank() for the food and hook. Or instead of creating separate new methods, we
could generalize the method we have to work with different kinds of objects by having it
draw different sequences of characters into the tank. Let’s change the name of this method
from placeFishInTank() to placeObjectInTank(), and then add one extra parameter to the
beginning of this method’s parameter list. This extra parameter will be a string
representation of the sequence of characters that should be drawn into the tank. And this
string will be justified (or aligned) so that the right most (or last) character in the string
ends up at the position specified by the later parameters. The signature for this method
should now match the following:
After updating the implementation of this method to make use of the new parameter, you
should be able to draw fish, fish food asterisks (*), and a fish hook capital letter J into each
frame of your simulation. But those other objects are all stationary, which we’ll fix in the
next step.
c. As a final step we’d like to get all of these new objects moving. The fish food should move
down one row and to the left one column each update, and the hook should move up one
7
8
9
10
11
12
13
14
// render (draw) the simulation by:
// clear the tank by filling it with water (~)
// place each fish into the tank
// draw the contents of this tank to the screen
// pause briefly to slow down the simulation a bit
Utility.pause(200);
System.out.println("\n\n\n");
1 public static void placeObjectInTank(String object, char[][] tank, int column, int row)
row each update. As in the previous step, we’ll accomplish this by generalizing an existing
method rather than adding new methods to our code. First change the name of the method
moveAllFish() to moveAllObjects(). Then add parameters to specify how far the objects
should be moved left-right (dx), and how far they should be moved up-down (dy) each
update. Make sure that your method’s signature exactly matches the following:
Then call this method from main to get the fish, fish food, and fish hook all moving as
previously specified. If any of these objects moves beyond the bounds of the tank (outside
of 0 to width-1 or 0 to height-1), their position should be wrapped to end up along the
opposite edge. Test this out and make sure that it is working for all of your objects.
10. Congratulations on finishing your first CS300 assignment! After verifying that your work is
correct, and written clearly in a style that is consistent with the course style guide, you should
submit your work through zybooks Section 2.11. Make sure that the methods’ names and
parameter lists exactly match what is described in this write-up, since differences may prevent
our automated tests from finding your solutions. If the automated tests detect defects in your
code, you may fix those and re-submit for full credit, although you will need to wait an hour
between submissions. The most recent of your highest scoring submission prior to the deadline
of 17:00 on Thursday, September 14th will be used as your score for this first assignment.
1 public static void moveAllObjects(int[][] positions, int dx, int dy, int width, int hei