The goal of this project is to create a word search game. I hope that it will allow you to apply and extend your knowledge of arrays and strings and also practice top-down design. The inspiration is the Wonderword puzzles by David Ouellet that regularly appear in many local newspapers including the High Point Enterprise; they can also be found at www.wonderword.com. The puzzle consists of a grid of characters and a list of words to find. In the paper version the user circles each word as they find them (in any order). Words may appear horizontally, vertically, or diagonally either forwards or backwards. Words cannot wrap around from one side of the grid to another. The game is complete when the user has found all of the words in the list.
There are many, many different word search puzzles on the Web. Feel free to use/experiment with any of them for testing before trying to scale up to a larger 15X15 or 20X20 version in the sample file I posted.
1. Prompt the user in main or some helper function for the name of the file to read the puzzle data from. Attempt to open the file. If unsuccessful print some sort of error message and keep re-prompting the user for a file name and attempting to open that file for reading until they supply the name of file that can be opened. Note that file names may contain spaces and you should not assume any special suffix for the name.
To simplify your testing and save yourself typing this test file name every time you run the program, make a default file name string variable and set it equal to the test file. If the user presses return without entering a file name when prompted attempt to load the default file. If the default file cant be opened proceed as above re-prompting until a valid file name is supplied.
See File Format and Data Structures below for more about the file contents.
2. Create a separate function to load the data from the user-specified file. Before working on the user interface for solving the puzzle I would get a version of your display puzzle function working to verify you loaded the data correctly.
3. After loading the data from the file start the puzzle solving process. Begin by displaying the letter grid and list of words to find. Use a hypothetical example word to explain to the user how they should specify what/which word in the list theyve found and where they found it in the grid. Two common conventions are:
a. Have the user give the word number or word itself along with its start and end grid coordinates, i.e., start row, start column, end row, and end column.
b. Have the user give the word number or word itself along with the row and column of the first letter in the word and which of the possible 8 directions/orientations from the start position where the rest of the words letters appear. Alternatively, if you dont want to make the user enter the found word/word number you will need to have them enter the found words length in addition to its direction and then search the word list for a match to the word you find in the grid.
Choose whichever of these you like or feel free to come up with your own. However try to minimize the amount of information the user has to enter for each word they find. When displaying the grid, label rows (left and right) and columns (top and bottom) with numbers and/or letters to make it easier for the user to identify a words start location.
4. Each time the user correctly finds a word, redisplay the grid with the most recently found word and all previously found words circled. Also redisplay the list of words remaining to be found with all already found words removed or otherwise crossed off the word list. You dont actually need to remove the found words from the list if you keep an array of which words have/havent been found and only print those not yet found. If the word the user circles doesnt match a word in the list of those to find, display an error message and wait for their next attempt. You dont need to redisplay the grid and word list if they make an invalid entry. Note that you can clear the terminal window on Max OSX and various Linux OSs using the command: system(clear); (there is another way to do it using an obscure ASCII character code sequence; if you find it let me know what it is).
There are a number of options for differentiating circled from un-circled letters in the grid: uppercase and lowercase, the presence or absence an underscore/dash under (on the next line) below the letter, a box around them, or even using different colors in the terminal for letters in found words versus those unused (several people did this last semester). Start with a simple scheme, and if you have time and the inclination feel free to pursue a more visually appealing method.
If any part of the word the user attempts to circle falls outside of the grid display a different error message indicating their circling is taking them off the grid. Similarly, if you ask the user to enter the number of the word they are finding the program should verify the number is in the valid range word numbers and is for an as yet unfound word. If not, show them an appropriate error message, ignore that selection/input, and ask them for their next selection. You can attempt to validate/error check each piece of information about the circled word as the user enters it or wait until after reading in all the information they specify and then validate their input.
5. Stop the program once the user finds all the words in the list or at any point if the user indicates they wish to quit before finding all the words. Rather than prompting the user each time whether they want to continue, try to come up with a special signal they can provide when they want to quit instead of their usual found word information.
1. All the information about the puzzle will be read in from whatever file the user specifies. Ive provided a sample file with a grid of characters and list of words to find. I encourage you to find or create a smaller puzzle to test on. Do not make any assumptions about the size of the character grid (you may assume its square) or number of words to find. See below for details about the file format. When grading the project with your help I will use a different file than the sample Im providing you with.
2. Define a struct to store the various pieces of the puzzle in a single entity. Pass references/pointers to a struct variable to your load puzzle and other functions (use const for those that dont need write access). That way you wont have to pass five or six separate parameters to your various functions.
3. The default/user specified file your program will read the puzzle data from contains the grids height and width in that order separated by one or more whitespace characters on the first line. Following the grid dimensions is the character grid with each row of letters on a separate line. The letters in each row are separated by one or more spaces or tabs. Following the character grid on its own line is the number of words to find in the grid. Finally, each word to find appears on a separate line. Its probably safe to assume that none of the words in that list will have spaces.
You may not make any modifications to the file format. If theres some other format or information you think the file needs please consult with me. You may do whatever you like in terms of case, capitalization, etc. as you read the data into your program.
4. In our previous project the number of words in a jumble was fixed and know in advance. In contrast, for this project the dimensions of the character grid and the number of words in the word list wont be discovered until the file is read. You should have a separate function to read in the data and in that function dynamically allocate the space need for the array of words and the grid of characters. This will require using pointers and dynamic memory allocation. See pp.792-806 in your book for a discussion on dynamic variables, pointers, and dynamic array in particular. Ill spend some time in class discussing and post some examples of to accomplish this on Blackboard. Initially, to get started you may wish to set fixed sizes for these structures corresponding to whatever puzzle you are using for your testing. However, I will test using a different file, and so your final version should be able to dynamically handle different size character grids and word lists without allocating overly large arrays.
NOTE: You may store the grid letters either in a 2-D array of characters or a 1-D array of strings (all the same length) but you may not use the Vector or other standard library container classes that dynamically resize themselves since part of this project is learning how to do that yourself.
5. You will obviously need to do a significant amount of testing to verify the correctness of your work. Whatever puzzle you use for testing make sure it has at least one word in each orientation. Also be sure to test what happens when a later solved word overlaps with one or more letters of a previously solved word.
Whatever format you decide on for specifying the word/positions to circle, I strongly recommend making a partial or complete answer key for your puzzle that has all the information the user would need to enter for all the words in the list to completely solve the puzzle (find and record the information about a different word each time you test). That way you can quickly copy and paste the information to test various words instead of rekeying it in each time. When youre fairly certain things are working pretty well, use input redirection to feed your program the solution file or part of it to quickly test a large number of cases/words. Ill demonstrate and example of this in class.