Computer Science 15-100 (Sections S-V), Fall 2008
Homework 7
Due: Thu 16-Oct-2008 at 11:59pm (email copy) and at Friday's
class/recitation
(identical physical copy)
(no late submissions accepted).
Read these instructions first!
- Be sure to include your name, your Andrew ID, and your section clearly on the top of each file in your assignment.
- Also on the top of each file, include a timesheet logging all
the time you spent on that part of the assignment.
You will not be graded on your number of hours, but this information
will be helpful to the course staff.
- For non-programming problems (there are none)
- Place all your solutions to the non-programming
problems in a single file named Hw7 (with whatever extension is appropriate
for the format you choose, such as Hw7.txt or Hw7.html, etc). You must
use a one of these file formats: plain text (txt), or RTF, or HTML, or
Word (doc, not docx), or PDF. No other file formats will be accepted.
- Show your work. Correct
answers without supporting calculations will not receive full credit.
- For programming problems:
- Place each solution in its own file named exactly as given below, and
with a class name that exactly matches the file name. So if the file
name is Hw7Foo.java, the main class in that file must be Hw7Foo.
- Use well-named variables, proper indenting, reasonable commenting,
etc.
- What to submit
- Either one zip file, Hw7.zip, containing all your files (this is
preferred), or all the files as attachments to a single email (do not send
one email per file!). It is recommended
that you "cc" yourself in that email, too, just to confirm that you properly
sent the email.
- More Array Practice
- isAlmostMagicSquare
- isSudokuRectangle
- isSudokoBoard
- Snake
-
Bonus/Optional: Better
Snake
- More Array Practice
In a file named Hw7MoreArrayPractice.java, write each of the following methods
along with their corresponding well-designed and aptly-named test methods.
- isAlmostMagicSquare
We will say that a square of numbers is "almost" a magic square if it
can be made into a magic square by exactly one swap of two numbers.
For example:
This square is not magic because (among other reasons) the first
row sums to 15, but the first column sums to 8. However, if we swap
the 1 and the 8 we obtain this magic square:
So the first square above, while not a magic square, is an "almost" magic square.
Write the following method:
public
static boolean isAlmostMagicSquare(int[][] a)
This method takes a 2d-array of int's and returns true if it represents an
almost-magic square, and false otherwise. Note that non-square
matrices and null matrices are not magic squares, so your method should
return false in these cases.
Note: In solving this problem, you will almost surely want to
make use of your isMagicSquare method from the previous assignment.
Also note: magic squares do not have to be 3x3. They can be as
small as 1x1 or arbitrarily larger.
- isSudokuRectangle
In the very popular game of Sudoku, players are presented with an N2-by-N2
square board in which they must fill all the cells with the numbers from
1 to N2 such that each row, each column, and each N-by-N
"box" contains all the numbers from 1 to N2. For
example, if N=3, players get a 9-by-9 board like so:
For this board (again, where N=3), players must fill each 1-by-9 row,
each 9-by-1 column, and each 3-by-3 highlighted "box" with the numbers
from 1 to 9. Here is a solution for this particular Sudoku:
For more information, read the Wikipedia page on Sudoku:
http://en.wikipedia.org/wiki/Sudoku
Write the following method:
public
static boolean isSudokuRectangle(int[][] board,
int row0, int col0,
int row1, int col1)
This method takes a 2d-array of int's
(the "board"), and a rectangle on the board defined by its top-left row
and column (row0, col0), and its bottom right row and column (row1,
col1), and returns true if this rectangular region of the board can be
part of a legal Sudoku solution and false otherwise.
Note that this method is only expected to work over rectangular regions
defining a single row (so col0 equals col1), a single column (so row0
equals row1), or a single "box" -- so the method returns false if any
other rectangle is specified. The method also returns false if the
board is null, is not square, or is not N2-by-N2
for some positive integer N.
Also note: if the board is not full, as in the first example
above, then the empty spaces will be signified by a 0 in that cell of
the board. Thus, this method amounts to checking that all the
values in the given rectangle are in the range [0,N2],
inclusive, and that none of the values besides 0 occurs more than once.
For your benefit, here are the two Sudoku boards from the examples
above:
private static int[][] board1 = {
{ 5, 3, 0, 0, 7, 0, 0, 0, 0 },
{ 6, 0, 0, 1, 9, 5, 0, 0, 0 },
{ 0, 9, 8, 0, 0, 0, 0, 6, 0 },
{ 8, 0, 0, 0, 6, 0, 0, 0, 3 },
{ 4, 0, 0, 8, 0, 3, 0, 0, 1 },
{ 7, 0, 0, 0, 2, 0, 0, 0, 6 },
{ 0, 6, 0, 0, 0, 0, 2, 8, 0 },
{ 0, 0, 0, 4, 1, 9, 0, 0, 5 },
{ 0, 0, 0, 0, 8, 0, 0, 7, 9 }
};
private static int[][] board2 = {
{ 5, 3, 4, 6, 7, 8, 9, 1, 2 },
{ 6, 7, 2, 1, 9, 5, 3, 4, 8 },
{ 1, 9, 8, 3, 4, 2, 5, 6, 7 },
{ 8, 5, 9, 7, 6, 1, 4, 2, 3 },
{ 4, 2, 6, 8, 5, 3, 7, 9, 1 },
{ 7, 1, 3, 9, 2, 4, 8, 5, 6 },
{ 9, 6, 1, 5, 3, 7, 2, 8, 4 },
{ 2, 8, 7, 4, 1, 9, 6, 3, 5 },
{ 3, 4, 5, 2, 8, 6, 1, 7, 9 }
};
Hint: Remember that Sudoku boards can be 1-by-1, 4-by-4,
9-by-9, 25-by-25, and so on.
- isSudokoBoard
Write the following method:
public
static boolean isSudokuBoard(int[][] board)
This method takes a 2d-array of int's (the "board"), as
defined in the previous problem, and returns true if the board is a
partial or complete solution to a Sudoku, and false otherwise.
Note that the previous method does all the "heavy lifting". This
method simply calls the previous helper method once for each row, each
column, and each "box". As with the previous method, this method
returns false if the board is null, is not square, or is not N2-by-N2
for some positive integer N.
- Snake
In a file named Hw7Snake.java, write
a simple version of the game of Snake:
snake.html (applet) or
snake.jar (app)
To play the game: The player controls the snake using the up, down, left,
and right arrows. The snake also moves one space ahead on each timer
click (where "ahead" is whatever direction it last moved). When the
snake eats (randomly-placed) food, it grows by one cell. If the snake
goes off the board or crawls into itself, it dies. In this simple
game, there is no score, no timer, no advanced effects, and when the snake
dies the game simply starts over. For more details, here is the
Wikipedia page on Snake:
http://en.wikipedia.org/wiki/Snake_(video_game)
Note: Of the many ways to represent a snake, we will use one that
is not very efficient but which greatly simplifies our coding effort.
Despite its inefficiency, it will run perfectly fine for any Snake game any
human player is realistically going to play. In any case, you are
required to use this approach:
- Represent your board as a 2d array of integers.
- Most of the board will contain 0's, meaning that the cell is empty
(no snake is present and no food is present). You may want a
constant like this:
public final static
int EMPTY = 0;
- Cells containing food will contain -1. You may
want a constant like this:
public final static
int FOOD = -1;
- Cells containing the snake will contain integers greater than 0.
- If the snake is, say, 3 cells long, then it will be represented by
the numbers 1, 2, and 3 stored in the board, where 1 is the snake's tail
and 3 is its head.
- In general, if the snake is N cells long, it will be represented by
the numbers 1, 2, ..., N, where 1 is the snake's tail and N is the
snake's head.
- To start the game (either in your start() method or after a game
ends), clear the board and randomly place the snake somewhere (but no
closer than 2 squares from any edge) and randomly place food somewhere
else (when you place food, make sure it is not where the snake is!).
- In response to timer fired events, move the snake one step in its
current direction. How you do this depends on what is one step
ahead of the snake. Here are the different cases:
- off-board: If the move is off-board, the player loses, so
start the game over.
- the snake: If the snake crashes into itself, the player
loses, so start the game over.
- food: If the snake eats food, it gets one longer, so
(assuming the snake is of length N before eating the food), just
replace the value in the food cell with the value (N+1). Now
the snake is (N+1) long, and the cell where the food was is the
snake's new head. Also, randomly place a new food cell, again
being sure not to place it on the ever-growing snake.
- empty board: One way to approach this case is to first
handle it like the food case, and place an (N+1) in the empty cell.
Only now we have to "shrink" the snake by 1, so it slithers one
square forward. To do this, we subtract one from every
positive number on the board (leaving the non-positives alone!).
Think about why this works!
- In response to key pressed events: for non-arrow keys, just
beep (by calling beep(), which is a method provided by
JComponentWithEvents). For arrow keys, change the direction the snake will move on
the next timer fired event. Note that this is an interesting
design decision. A different, but equally valid, design would be
to actually move the snake in response to an arrow key. This would
allow you to quickly move the snake by repeated arrow presses. Try
out this alternative! But then switch it back, since your
submission should not move in response to arrow keys, but just adjust
the direction for the next timer fired event.
Note: To get a clearer picture of how we are representing
the board, you can run this version of Snake, where the board values are
displayed:
snakeWithBoardValues.html (applet) or
snakeWithBoardValues.jar (app)
This version is only to help you understand how this design works.
Your submitted version should not display the board values, and should work
like the first version from above.
-
Bonus/Optional: Better
Snake
The Snake game you just wrote is fairly simple. In a file named
Hw7BonusBetterSnake.java, make a better Snake game. Here are some
features you might consider:
- A score.
- A timer.
- Multiple snake lives.
- A high score file.
- Better graphics.
- A splash screen (at the start of the program) and a game over
screen.
- A help screen.
- Levels with increasing challenges.
- Impediments (walls, traps, etc).
- Eagles (they eat snakes).
- Portals (as the snake enters a portal, it magically teletransports
to emerge from a different portal, so for a while there are two partial
snakes on the board)
- Two players (one gets arrows, the other gets AWSZ or some such).
- Other ideas. Be creative!!!. Have fun!!!
To be sure that you get credit for all your great efforts, be sure to
provide a detailed comment at the head of your Java file listing ALL the
extra features you added, along with a timesheet of all the time spent on
your bonus Snake project (not including, of course, the time spent on the
assigned Snake project).
Carpe diem!