Lab 4: C Programming Project
Overview
This C programming project focuses on dynamic memory allocation, pointers, file I/O, and string manipulation.
Program Description
In this lab, you will write a program to play a beginners-level crossword puzzle game. The goal of the game is to guess each word. Words are placed either horizontally (left to right) or vertically (top to bottom). This program is "beginners-level" because it verifies each word you enter, making it impossible to commit a wrong entry to the board.
An example game, including user input, is shown below. While your program does not have to match this example program letter-by-letter, it should provide similar functionality.
unix> ./crossword CROSSWORD PUZZLE GAME Enter game filename to load: crossword_puzzle.txt Loading game file crossword_puzzle.txt Game is 5 rows x 5 cols with 6 words Current Puzzle: 1 2 3 4 5 ----------- 1 | _ _ _ # # 2 | _ # _ # # 3 | _ _ _ _ _ 4 | # # _ # _ 5 | # # _ _ _ Unsolved Clues: ------------------------ # Direction Row/Col Clue 1: Horizontal 1 / 1 Sheep sound 2: Horizontal 3 / 1 Neither liquid nor gas 3: Horizontal 5 / 3 Humor 4: Vertical 1 / 1 Road passenger transport 5: Vertical 1 / 3 To permit 6: Vertical 3 / 5 Point Enter clue to solve, or -1 to exit: 1 Enter your solution: baa Current Puzzle: 1 2 3 4 5 ----------- 1 | B A A # # 2 | _ # _ # # 3 | _ _ _ _ _ 4 | # # _ # _ 5 | # # _ _ _ Unsolved Clues: ------------------------ # Direction Row/Col Clue 2: Horizontal 3 / 1 Neither liquid nor gas 3: Horizontal 5 / 3 Humor 4: Vertical 1 / 1 Road passenger transport 5: Vertical 1 / 3 To permit 6: Vertical 3 / 5 Point Enter clue to solve, or -1 to exit: 4 Enter your solution: bus Current Puzzle: 1 2 3 4 5 ----------- 1 | B A A # # 2 | U # _ # # 3 | S _ _ _ _ 4 | # # _ # _ 5 | # # _ _ _ Unsolved Clues: ------------------------ # Direction Row/Col Clue 2: Horizontal 3 / 1 Neither liquid nor gas 3: Horizontal 5 / 3 Humor 5: Vertical 1 / 3 To permit 6: Vertical 3 / 5 Point Enter clue to solve, or -1 to exit: 5 Enter your solution: allow Current Puzzle: 1 2 3 4 5 ----------- 1 | B A A # # 2 | U # L # # 3 | S _ L _ _ 4 | # # O # _ 5 | # # W _ _ Unsolved Clues: ------------------------ # Direction Row/Col Clue 2: Horizontal 3 / 1 Neither liquid nor gas 3: Horizontal 5 / 3 Humor 6: Vertical 3 / 5 Point Enter clue to solve, or -1 to exit: 2 Enter your solution: solid Current Puzzle: 1 2 3 4 5 ----------- 1 | B A A # # 2 | U # L # # 3 | S O L I D 4 | # # O # _ 5 | # # W _ _ Unsolved Clues: ------------------------ # Direction Row/Col Clue 3: Horizontal 5 / 3 Humor 6: Vertical 3 / 5 Point Enter clue to solve, or -1 to exit: 3 Enter your solution: pun Wrong answer Current Puzzle: 1 2 3 4 5 ----------- 1 | B A A # # 2 | U # L # # 3 | S O L I D 4 | # # O # _ 5 | # # W _ _ Unsolved Clues: ------------------------ # Direction Row/Col Clue 3: Horizontal 5 / 3 Humor 6: Vertical 3 / 5 Point Enter clue to solve, or -1 to exit: 3 Enter your solution: wit Current Puzzle: 1 2 3 4 5 ----------- 1 | B A A # # 2 | U # L # # 3 | S O L I D 4 | # # O # _ 5 | # # W I T Unsolved Clues: ------------------------ # Direction Row/Col Clue 6: Vertical 3 / 5 Point Enter clue to solve, or -1 to exit: 6 Enter your solution: dot Game over, you win! Current Puzzle: 1 2 3 4 5 ----------- 1 | B A A # # 2 | U # L # # 3 | S O L I D 4 | # # O # O 5 | # # W I T
This program will read a puzzle from a text file saved to disk. This file has a specific format that must be followed, to ensure compatibility across all programs.
- The first line of the file should contain the dimensions of the puzzle and the number of clues in the format:
- # of rows (integer)
- # of columns (integer)
- # of clues (integer)
- Subsequent lines in the file should contain the word clues in the format:
- Orientation (H for horizontal or V for vertical)
- Row # (starting from 1)
- Column # (starting from 1)
- Solution word (spaces are not allowed as part of the solution word)
- The clue (which may contain multiple words, ending with a newline character)
Here is the input file for the demo game shown previously:
5 5 6
H 1 1 BAA Sheep sound
H 3 1 SOLID Neither liquid nor gas
H 5 3 WIT Humor
V 1 1 BUS Road passenger transport
V 1 3 ALLOW To permit
V 3 5 DOT Point
Requirements: Makefile
You must create a Makefile for your program (with the name Makefile). I should be able to enter the directory containing your code and type "make" to trigger compilation. If the Makefile is broken, or if I need to type anything else (or dig into the source code to figure out how to compile your program), zero points will be awarded!
Use the following GCC options in your Makefile to set the compiler to a very picky mode:
- -std=c99 (Use the more modern C99 standard for the C language)
- -Wall and -Wextra (Turn on all warnings and extra warnings. By viewing and fixing issues that generate warnings, you will produce better, safer, C code)
- Warning: Don't delete the existing -c flag flag in the Makefile example from the previous lab! (It is essential to Makefile operation)
Configure your Makefile so that the name of your program binary is crossword
Makefile grading nodes:
- If your program produces any warning during compilation (with these options), 5 points will be deducted.
- If your program doesn't compile on my virtual machine (and the error is such that your code wouldn't compile on any of your classmate's machines either!), zero points will be awarded.
Requirements: Memory Structures
Use a two-dimensional array of characters to store the current state of the puzzle. In this array, store the '#' character to denote non-game squares, the underscore '_' character for blank spaces, and A-Z characters for solved words. As the game is played, update this array based on user input.
Because the size of the puzzle is variable, you must use dynamic memory allocation to store this array. Remember to release dynamic memory before exiting! How can this be accomplished? In C, a two-dimensional array is simply an array of arrays, and you can allocated a single-dimensional array using malloc() or calloc(). This method is documented at the C FAQ site.
Tip: A demo program that uses dynamic memory allocation is provided for your reference. Note that it stores an array of integers, while you will want an array of characters. It can be compiled and run with the command:
unix> gcc dynamic_2d_array.c -std=c99 -o dynamic_2d_array
Requirements: Other
- I will compile and test your program in a Linux virtual machine that meets the installation process followed at the beginning of the semester. Don't relay on anything that wouldn't be in this default installation!
- You must implement the program in C
- You cannot use global variables.
- You must use both header files (.h) and source files (.c) where appropriate
- You must create a C structure for a datatype called clue that is saved in a header file. The following information (at a minimum) should be contained in this structure
- The word (i.e. answer)
- The clue that describes the word
- Starting row where this word can be found
- Starting column where this word can be found
- Whether the word is horizontal ('H') or vertical ('V')
- Whether this word has been found (1) or not found (0)
- You must use functions with clue parameters. The actual division of the program into functions is up to you.
- You can assume that the maximum length of a word clue is 256 characters, allowing that array to be a fixed length instead of dynamically allocated.
- Your game logic should be case insensitive when comparing the user entry to the correct word. The strcasecmp() function may be helpful here.
- All source files must be commented, including your name and email address.
- Feel free to use fancier text editors or IDEs that auto-indent your code and provide other convenience features. Just note, however, that you still must have a Makefile that allows your project to be compiled by typing make at the command line! (i.e. I will not install any IDEs on my computer, and still should be able to compile your project).
- Geany (fancy code text editor) - install via sudo apt-get install geany
- CodeBlocks (cross-platform IDE) - install via sudo apt-get install codeblocks
Requirements: Test Case
As part of this lab, you must submit a test case that demonstrates your program operation, including both valid and invalid human input. This test case has two components:
- A sample crossword puzzle file with dimensions of at least 15x15 and 10 words to solve.
- A sample human input file that contains test values that a human would enter on the keyboard.
Here is an example of what a test case should look like. The sample crossword puzzle file used in the demo above could be stored in the file crossword_puzzle.txt:
5 5 6
H 1 1 BAA Sheep sound
H 3 1 SOLID Neither liquid nor gas
H 5 3 WIT Humor
V 1 1 BUS Road passenger transport
V 1 3 ALLOW To permit
V 3 5 DOT Point
Then, the sample human input file could be stored in the file human_input.txt. Note that this file is exactly what a person would type at the keyboard while running the program!
crossword_puzzle.txt
1
BAA
2
SOLID
3
WRONG
3
WIT
4
BUS
5
ALLOW
6
DOT
The human input file can be run using Unix input redirection. Via this mechanism, your program can automatically read from this file instead of standard input (i.e. the keyboard) with no code changes required! The command to accomplish this is simple:
unix> ./crossword < human_input.txt
Be sure to test that your test case functions in this manner.
Note: When you use input redirection, the input will not be echoed on the screen in the same way that keyboard input is echoed. It is OK if your program output looks a little strange in this mode. You don't need to adjust your program code to accomodate this.
Resources
- Need C programming resources? Visit the class Resources page
- The Instant Online Crossword Puzzle Maker may help you construct creative new sample puzzles for your program.
Getting Started
First, go to the directory that will hold your project.
unix> cd ~/bitbucket/2015_spring_ecpe170/lab04
Second, write your program in this directory!
Here is one way to approach this lab in a step-by-step manner:
- Create a .c file for source code and .h file for header information. Put in a few lines of code - just enough to compile and produce some output.
- Create the Makefile - you'll need this to compile your program! Base this off of the advanced "Makefile-4" from the previous lab, but call it "Makefile" here.
- Test the Makefile
- Create a crossword puzzle file (or copy the example above for a fast start)
- Add these files to your version control repository, and commit a new changeset. Be careful - don't include any of the temporary files your text editor creates! Those end in a tilde (~).
- Write file I/O code - Read in the crossword puzzle file and echo the output on the screen (for debugging)
- Test file I/O code
- Commit a new changeset to version control
- Write dynamic memory code - Save the crossword puzzle into dynamic array(s) created based on the demo program code. You might want multiple arrays, one for the puzzle itself, and another for all of the clues.
- Test dynamic memory code
- Commit a new changeset to version control
- Write the game play logic, prompting the user for input and comparing against the correct answer.
- Test game play logic
- Commit a new changeset to version control
- ... and so on ...
Submission
(1) Check all of your code (including Makefile and test cases) into version control, and push to BItBucket.
Want to test your submission to ensure you don't lose points due to version control errors? You could do a checkout of your repository into a different directory. Then, verify that all files are present and that you can still compile this copy of your project in its new location.
- Warning: Don't be sloppy and add too many files to version control! 5 points will be deducted if intermediary files (i.e. .o object files) end up in your repository.
- Warning: Don't be sloppy and add too few files to version control! Zero points will be awarded if missing source code or Makefiles prevent your program from compiling and running!
- Warning: Make sure your Makefile has the exact name "Makefile", so that I can compile your program simply by typing "Make" in the directory.