Puzzle Input and Output (IO)
CS 162 - Spring 2008

Specifications
The puzzle input to your program comes from a file. The file contains the puzzle size and contents. In your program, store the puzzle in an array that has border characters to facilitate searching. Print the puzzle array contents with a blank space after each character. For this assignment only, print the border characters as well. For later assignments, the border characters will be there but won't be printed.

The first inputs are the size of the puzzle. This will be the number of rows (numRows) followed by the number of columns (numCols). The next numRows strings will each contain the numCols characters for that row of the puzzle.

  Input
 5 8
 hptnrocr
 aeehkcra
 moaiauag
 itmupcni
 rauioibn
 
     Output
= = = = = = = = = =
= h p t n r o c r =
= a e e h k c r a =
= m o a i a u a g =
= i t m u p c n i =
= r a u i o i b n =
= = = = = = = = = =
Your program should terminate gracefully if numRows or numCols is greater than 20 or less than 1. After you know the sizes are good, allocate a puzzle array (a two-dimensional array of char) to hold a puzzle with an extra two characters in each dimension for the border. Before reading the puzzle contents, fill the entire array with the border (non-data) character, '=', which should be declared as a global constant (static final). Then fill the used portion with the data from the puzzle file.

The main function should do command line processing, get the file name if it wasn't provided, open the file, and close it. It controls the overall processing but doesn't do any word search action itself. Much of that capability is provided in the starting code we provide.

You must use functions and parameters extensively in this assignment. Do not use any global or class variables other than the console Scanner. You may define class constants.

Steps to Solving the Word Search Problem
In the sections below, the summaries in italics state what should be done while the paragraphs suggest how to do it. There are more details here than we'll usually give you.

Examine and execute the starting program. Copy the starting program directory from ~katz162/link162/wordsearch and create a new Java project in Eclipse. Look at what the starting program does to read a filename, open the file, and read from the file. It reads and prints the number of rows. The name of the input file can be read from the command line or from the user. If a file name is not provided from either place or the file cannot be opened, the program prints a message stops. Note the exception handling.

To execute from the command line, change directory to your program directory and type:
   java WordSearch thanks.txt

Modify to read columns and test. Modify the program to read and print the number of columns as well as the number of rows. Add a check that those values are in the correct range and throw an IllegalStateException with a descriptive error message including the problem value (bad rows or bad columns). Even though that exception is thrown in readPuzzle, it will be printed when it is caught in main. Create a bad.txt file and check that you get messages for the four error conditions (numRows and numCols each too big and too small). An example error message is:
   Rows must be between 1 and 20 but is 21

Declare and allocate the puzzle. The puzzle array is a two-dimensional array of characters. The readPuzzle function will read the puzzle file and return the puzzle array as its return value. Declare the puzzle in main with:
   char[ ][ ] puzzle = readPuzzle(puzzleFile);

Adjust readPuzzle's return type to be char[ ][ ]

In readPuzzle, after you know the sizes are good (but still inside the try-catch block), allocate the space for the puzzle. It must be two characters bigger in each dimension to be able to hold the border characters:
   char[ ][ ] puzzle = new char[numRows+2][numCols+2];
   return puzzle;

Check that the puzzle is being returned to main correctly by printing the row and column values in main rather than in readPuzzle. The puzzle array's dimensions are available using the length variable (not function): puzzle.length and puzzle[0].length

Write print and initialize functions. Both the print and initialize functions take in a puzzle and iterate through the elements doing some action. Use two nested for loops in each function. Use the length variable to determine how many times to execute the loop. In the innermost loop, refer to the row,col element of the puzzle array p as  p[row][col]
For the print function, print a space after each character to make it more readable. Finish each line after the inner loop. Print an extra blank line after printing the puzzle. Call this function from main after reading the puzzle.

For initializing, before main declare a final static class constant char called BORDER and set it to '='. Assign its value to all elements in the puzzle array. Call this function from readPuzzle.

Fill puzzle with data. Modify readPuzzle to use two nested for loops to fill the puzzle from the puzzle file. Scanner will not read characters, but if you read a string, you can walk through that string placing each character in the puzzle. The first data character goes at 1,1. But the first character in the string will be at index 0. So your assignment statement will look like:
   puzzle[row][col] = s.charAt(col-1);

Be very careful with your loop bounds. You are placing these characters in the space within the borders of the array.

If there aren't enough rows(strings), the scanner throws a NoSuchElementException. That exception is already caught in readPuzzle, and the long error message is sufficient and will stop the program gracefully. If there aren't enough characters in a row, you need to catch the StringIndexOutOfBoundsException. You can handle it the same way the NoSuchElementException is handled in readPuzzle. Duplicate the catch clause and change the name of the caught exception.

Test this with several data sets that exercise the code and push the boundaries but have legal data.

Check your work. Have you tested your program with large and small data sets? Have you included your name in the comments and expanded the comments to include a description of the problem? Did you use functions? Does each function have a short comment describing what it does? Does the program's indenting match its control structure? Do the for loops have appropriate bounds?

If so, submit this as the IO assignment to the appropriate grader account.