代写ECE 209 Program 2: wordle Fall 2025代做R编程
- 首页 >> C/C++编程ECE 209
Program 2: wordle
Fall 2025
Due Monday, Nov 17 @ 11:59pm
In this program, you will implement a significant part ofa program that implements the Wordle game.
Your main jobs will be to load a dictionary of words from a file, choose a random secret word, and then compare the user’s guess to the secret and give feedback.
The learning objectives ofthe program are:
• Write one component of a multi-file program.
• Read strings from a file.
• Process string data.
• Implement logic to check for exact and misplaced matches between two strings.
Background
Wordle is a web-based game that was created in 2021, and joined the NY Times lineup of games in 2022. According to Wikipedia, “In the game, players have six attempts to guess a five-letter word, receiving feedback through colored tiles that indicate correct letters and their placement.” Instead of the colored tiles, you will create an output string for each guess that shows the exact and misplaced matches.
The user interface, which plays the game, is already written and given to you. Your job is to implement the word processing logic.
The Program
When your program is fully implemented, this is what it will do:
1. Ask the user to provide the name of a dictionary file. This is the file that contains all of the secret words that will be used during the playing of the game.
2. Ask the user to enter a number between 1000 and 9999. This number will be used to initiate the generation of random numbers, which determines which secret word will be picked. If you want to repeat a game using the same secret, simply use the same number.
3. The program will now prompt the user for a guess, and it will show the matching result for that guess.
• The result has a * in every position where the guess letter is exactly the same as the secret.
• The result has a | in every position where the guess letter matches a letter in the secret, but is in the wrong position.
• The result has a - in every position where the guess letter does not appear at all in the secret.
4. If the guess is not a word in the dictionary, it is not allowed to be used as a guess. This prevents the user from guessing “aaaaa” to see if there are any a’s in the secret.
5. If the guess is correct, the program will print a congratulations message and ask if the user wants to play again.
6. If six guesses are used without success, the game is over. The secret is printed and the user is asked if they want to play again.
7. This continues until the user answers ‘N’ or ‘n’ when asked to play again.
NOTE: When the game repeats, the random number generator continues. If you find a bug and want to test with that word, you won’t know what number to use as the seed. Therefore, for debugging purposes, I recommend that you either (a) always play just one word at a time, so that you know what number is associated with that word, or (b) write your own unit tests instead of relying on the main program to test your code.
The dictionary file contains all of the words that might be chosen as the secret. The file is guaranteed to have no more than 10,000 entries. Every word is exactly 5 characters and contains only lower-case letters (no digits, punctuation, etc.).
The following dictionary files are provided for development and testing:
scrabble5.txt This file was created by extracting all of the five-letter words from an official Scrabble word list. You will probably hate this dictionary, because it contains words that you’ve never heard of, which are very hard to guess!
small.txt This file has only a small number of words. It is good for development because you can easily check whether you are loading all of the words correctly and in the correct order. Small dictionaries are not easy to play with, because most of your guesses will not be in the dictionary.
ece.txt This file has a small collection of ECE-related five-letter words.
Multiple Files
The program is built from the following files:
main .c
wordle.h
wordle.c
random.h
random.c
You will only be implementing wordle.c. Remaining files should be treated as read-only with respect to the submission; you will not be uploading these files to ZyBook. You may change these files locally while you develop and debug your program on CLion, but if your code depends on any of those changes, then it will not work when you submit.
Hint: If you always want to run your program using the same dictionary file, you can change the main function to use that file name and skip the part where the user is asked for the name.
In order to create an executable program, we have to compile all of the source code (.c) files to create object (.o) files. These will be linked together to create an executable that you can run on your computer. You won’t see the .o files in your CLion project directory, because the actual compiling and linking is done elsewhere.
In CLion, we use CMakeLists.txt to specify how to build the executables in our project. (There are other things we can do, but that’s beyond the scope of this course.) For each executable, we need a line that looks like this:
add_executable(program src1.c src2.c src3.c … )
The name of the program (the desired executable) comes first, followed by the source code files that must be compiled and linked. The compilation system is smart, because it checks to whether any of the source code files have changes since the last build and only compiles those files who have changed.
Then all of the object files are linked to create the executable. (This is why you see different outputs when you click the build icon: sometimes there are lots of things to build and sometimes there’s nothing to do because nothing has changed.)
The ZyBooks environment does not use CMakeLists.txt and you don’t have to worry about the details of building. You only need to upload the file you are changing (wordle.c) and the compilation will happen when you press Run or Submit. Please don’t try to do anything other than that, and don’t upload additional files; you might mess up the environment.
But wait … If we are only specifying the .c files, why do we need the .h files?
Header (.h) files are used to simplify the coding and compiling of the individual source code (.c) files.
A header file contains function declarations (not definitions) and struct definitions that may be needed by multiple files in the overall program. We put them in a header file so that we don’t need to copy the declarations into every source code file. Then we use #include to bring them into the source code files as needed.
In this program, here are the roles for each of the files.
|
File name |
Purpose |
Calls functions defined in … |
Includes … |
|
main.c |
User interface for wordle game. |
wordle.c, random.c |
wordle.h, random.h |
|
wordle.h |
Function declarations for the wordle game. |
|
|
|
wordle.c |
Function definitions and global data variables needed to implement wordle. |
random.c |
wordle.h, random.h |
|
random.h |
Function declarations for generating pseudorandom numbers. |
|
|
|
random.c |
Function definitions and global variables needed to generate pseudorandom numbers. |
|
random.h |
Getting Started
To set up your CLion environment:
1. Create a new project. Specify a C Executable, and use the C17 standard. Name the project whatever you like, but I recommend something meaningful like “prog2” or “wordle”. This will create a directory in the place where your CLion projects are kept.
2. Go to ZyBook 15.2 (Program 2) and download all of the files into the top level of your project directory. This includes all of the .c, .h, and .txt files. This will overwrite the main.c file that was automatically created with the project; that’s fine -- it’s what you want.
3. Set the Working Directory for the executable. This is important!!! If you don’t do this, then the program will not be able to find the file to open it. In the dropdown menu of executables, select Edit Configuration. Select an executable and click on the folder icon next to the Working Directory box. Select your top-level project directory.
To test whether you have things setup, build and execute the program using the scrabble5.txt dictionary file, and choose any number between 1000 and 9999. If successful, this will tell you that there are -1 words in the dictionary, and that the secret word could not be retrieved from the dictionary.
Random Number Functions
Typically, when we need to use random numbers in C, we use the rand and srand functions provided by the C standard library. However, libraries vary across platforms, and we need our code to work the same in our local CLion development environment and on the ZyBooks testing platform. Therefore, we provide our own implementation of a pseudorandom number generator for this assignment.
We use a linear feedback shift register (LFSR) to generate our pseudorandom sequence of integer values. It’s called pseudorandom because the sequence is generated algorithmically and is not really random: it just looks random. We need a starting value, known as a seed; a specific seed will generate the same sequence of values every time. This is good for debugging purposes, since it means that we can exactly reproduce the same execution multiple times.
The random.c file contains the function definitions and the random.h file gives the declaration of those functions:
void seedRandom(unsigned int seed);
Initializes the LFSR to seed. This is typically done once, at the beginning of your program, just to initialize the random number generator.
unsigned int getRandom(unsigned int limit);
Returns a random integer between 0 and limit-1.
Wordle Functions and Data Structures
Open the wordle.c file and take a look. There are two comments that tell you to create global variables. (What? Yes, we will use these and only these global variables in this assignment.)
The first is a data structure that holds all of the words in the dictionary file. This will be some sort of array. You do not need a linked list, because you know the maximum number of allowable words.
However, you need to know how many words were read, which leads us to the second global variable …
After the array, you must declare (and initialize!) a global variable that counts the number of words read from the dictionary file.
Pro tip: If you add static at the beginning of your declaration, it restricts the scope of this global variable to this file only. (See the variables in random.c as an example.) That prevents accidental name collisions, which multiple files decide to declare a global variable with the same name. However, don’t do static if you really do want to the global variable to be used throughout the entire program.
After the variable declaration, I have provided stubbed-out function definitions for the functions that are declared in wordle.h. Notice that I also included wordle.h in this file; it’s a good practice to include the header associated with the source code file, to make sure that your function definitions agree with the declarations seen by the other files in the project. Also, header files may contain struct definitions, typedefs, and stuff that is needed by your source code.
Here are the functions that you must implement, followed by some explanation. Please read the description carefully. Do exactly what is required -- no more, no less.
int loadDictionary(const char *fname);
The parameter is a string that corresponds to the name of a file. Open the file for reading. If the file cannot be opened, return 0. Otherwise, read all of the words and store in the data structure that you declared. Assume there are no errors in the file; all words are exactly five characters long. Close the stream when you have finished reading the file. Return the number of words read.
NOTE: Even though the main program only loads the dictionary once, the tests may call this function multiple times. Each load will overwrite the previous data. Make sure your code does not assume that the data structure is “empty” when this function runs.
const char * getWordByIndex(unsigned int index);
Retrieve a word from the dictionary using its position in the data structure (its index). Return a pointer to the string. (Don’t create a copy of the string. Just point to where it is stored in your data structure.) The ordering must be exactly the same as the dictionary file. This function is not called by the main function. It will only be used to test that you loaded the file correctly.
const char * getRandomWord();
Call this function to retrieve a random word from the dictionary. You must use the provided getRandom function, and you must call it in a way that selects from the entire dictionary; in other words, all words in the dictionary have a chance of being selected. Return a pointer to the word.
(Don’t make a copy of it. Just point to where it is stored in your data structure.)
NOTE: Do not seed the random number generator. This will be done before your function is called. Use the getRandom function to generate a random index into your dictionary.
bool findGuess(const char *guess);
Look up a string in the dictionary. Return true if the string matches one of the words in the dictionary, and false otherwise. Do not make any assumptions about the string provided by the caller (for example, it may contain non-letters or it may not be five characters long).
int checkGuess(const char *guess, const char *soln, char *outcome);
This function matches the character in the player’s guess against the secret word. Those two strings are the first two parameters. The third parameter is an array that you must use to create a string showing the matching results: * for every exact match, | for a match in the wrong position, and - for a letter that does not appear in the secret. Return the number of exact matches.
Here are the rules for a misplaced match, i.e., a letter that appears in the solution but in a different position.
• Exact matches take precedence. Ifa letter is in the right position, it should always be marked as an exact match, even if that same letter appears multiple times in the solution. For example, if the solution is madam and the guess is party, the outcome is -*---, even though the ‘a’ in party matches both a’s in madam.
• First misplaced match takes precedence. If there are multiple letters in the guess that match a letter in the wrong place, only the first matching letter should be marked. For example, if the solution is acrid and the guess is madam, the outcome is - ||--. The second ‘a’ in madam matches the first ‘a’ in acrid, but the second ‘a’ in madam does not have a corresponding match, so it is marked as -. Likewise, the ‘d’ in madam matches the last letter of acrid.
Hints and Suggestions
• Don’t overcomplicate the program. This program is focused on arrays, strings, and characters. There is no need for structs or linked lists.
• Work incrementally. Get one part of the code working, and then move to the next. Try to write your code such that the program compiles and runs when some parts are missing. However, only unit tests will be used in zyBook, so it doesn’t matter for submission whether your main program runs or not.
• Don’t assume that the unit tests will call your functions in the same way as the program in main.
• When a test fails, you should have enough information in the test description to know why it fails. Figure out how to reproduce that same behavior. and use the debugger to step through your code. Sometimes, it’s hard to reproduce the behavior. using the main program -- that’s really just there as a starting point and to give you something to compile and run. Try writing your own unit test code: a separate executable that calls one function with various inputs to see ifit behaves correctly. (See Programming Tutorial 3 for a description of how to create multiple executables in a single CLion project.)
• For compiler errors, look at the source code statement mentioned in the error. Try to figure out what the error is telling you. Try to fix the first error first, and then recompile. Sometimes, fixing the first error will make all the other errors go away. (Because the compiler got confused after the first error.)
• Use a source-level debugger to step through the program if the program behavior is not correct. If you are using CLion on your own computer, the debugger is integrated with the editor and compiler, so there’s no excuse for not using it.
• For general questions or clarifications, use Discord, so that other students can see your question and the answer.
• For code-specific questions, create a private thread in the #getting-help channel and attach your code (just wordle.c) as a file. Do not copy and paste! Do not post a screenshot of code! We do not debug by staring at your code. (And neither should you.) We need to compile and execute your code. Describe the problem and what you have tried so far. Give precise information that allows us to recreate the problem you see. (For example, what input values were entered?)
• Ifa test fails or seems to behave “weird,” 99% of the time the problem is with your code, not the test. If you are convinced that the test is wrong, post a message and I’ll look into it. Sometimes I do make a mistake.
Administrative Info
Updates or clarifications on Discord:
Any corrections or clarifications to this program spec will be posted on Discord. It is important that you read these postings, so that your program will match the updated specification.
What to turn in:
• Upload your wordle.c file to the zyLab assignment in 15.2 Program 2: wordle, and then submit for grading.
Grading criteria:
40 points: loadDictionary
15 points: getWordByIndex
20 points: getRandomWord
10 points: findGuess
15 points: checkGuess
Possible deductions:
Up to 10 points: Poor coding style. See the Programming Assignments section on Moodle for style. guidelines. Do not use global variables or goto. Use proper indentation, and include useful comments. We are mostly looking for code that is readable and has sufficient comments for someone else to understand the code.
NOTE: Points may be deducted for errors, even if all of the zyBook tests pass. This will be rare, but it may happen if it is obvious to the grader that the program is written specifically to pass only these tests and would not pass other similar tests, or if you have violated the specifications (e.g., by assuming a limit to the number of characters to be read).
Do not make assumptions. Write your code to pass any test consistent with this specification. We reserve the right to run your code on tests that were not provided in the zyLab.
