Assignment 4: A multi-player word game Solution



We have provided starter code for the Makefile. Completing it is your first task and the starter code will not compile until you complete these tasks.

To avoid port conflicts when testing your programs on teach.cs, you will use PORT (see below) to specify a port number. Select that number using the same algorithm we used for lab 10: take the last four digits of your student number, and add a 5 in front. For example, if your student number is 1008123456, your port would be 53456. Using this base port, you may add 1 to it as necessary in order to use new ports (for example, the fictitious student here could also use 53457, 53458, 53459, 53460). Sometimes, when you shutdown your server (e.g. to compile and run it again), the OS will not release the old port immediately, so you may have to cycle through ports a bit.

lu1890tybba0 tmp 4ba5a8aa2d63c0dc

lu1890tybba0 tmp a96e7346e154fb74 In wordsrv.c , replace x with the port number on which the server will expect connections (this is the port based on your student number):

lu1890tybba0 tmp 109c1ee4879b8e6e lu1890tybba0 tmp 886b005b0bdc5634 lu1890tybba0 tmp 672a879309881755

#ifndef PORT

#define PORT x


lu1890tybba0 tmp a96e7346e154fb74 Then, in Makefile , replace y with your student number port plus 1:

lu1890tybba0 tmp 1b178fdafee11f10

PORT= y;

Now, if you type make PORT=53456 the program will be compiled with PORT defined as 53456 . If you type just make , PORT will be set to y as defined in the makefile. Finally, if you use gcc directly and do not use ‐D to supply a port number, it will still have the x value from your source code file. This method of setting a port value will make it possible for us to test your code by compiling with our desired port number. (Read the Makefile. It’s also useful for you to know how to use ‐D to define macros at command line.)

lu1890tybba0 tmp 95a6e8d1c33f8c1d lu1890tybba0 tmp dd17fecc4c46873e

For assignment four, you will write a word guessing game server. The game is similar to the game you wrote in assignment two, but with some key differences. In particular, the server chooses the word before the players start guessing and doesn’t change the word during a round. The game is played by one or more players who take turns guessing letters.

Players will connect using nc . When a new player connects, the server will send them “Welcome to our word game. What is your name?”. After they input an acceptable name that is not equal to any existing player’s name and is not the empty string, they are added to the game, and all active players (if any) are alerted to the addition (e.g., “Karen has just joined.”) If they input an unacceptable name, they should be notified and asked again to enter their name.

lu1890tybba0 tmp a9b5d119e502aa39

With your server, players can join or leave the game at any time. A player leaves the game by exiting/killing

nc .

lu1890tybba0 tmp daa3553967037ccd

1页 共5 2019/3/23 14:05

game_state struct


Assignment 4: A multi-player word game

New players who have not yet entered their names are stored in a linked list, and each new player is added to the front of the list (see add_player ). Players in this list do not get turns, and do not receive any messages about the status of the game.

lu1890tybba0 tmp d5c8c4acd81a2b1a

When a player has entered their name, they are moved from the new players list to the head of the list of

active players that is stored in the lu1890tybba0 tmp 4dae72af8765699e .

Adding a player to the active list in the game_state struct must not change whose turn it is, unless this is the first player to join the game. When someone leaves, if it is their turn, the turn has to pass to the next player in the list, not to the top of the list. When the last player leaves, the variable that stores the pointer to the player with the next turn is set to NULL .

lu1890tybba0 tmp cf796955dd07f02f lu1890tybba0 tmp 2a3b7a0f3667b82f

For each turn, or to newcomers moved to the active list, you display the game state in a simple text format.

The output should look something like this:

lu1890tybba0 tmp 36f58ab94c327cee


Word to guess: ‐‐u‐‐s

Guesses remaining: 3

Letters guessed:

u s z


Then, prompt the player whose turn it is with the query “Your guess?”, and tell everyone else (for example) “It’s Jen’s turn.”

The player is expected to type a single lowercase letter, followed by the enter (or return) key. Note that because we are running nc with the ‐c or ‐C option it will send the network newline ( ‘\r\n’ ). If the user enters anything else, such as multiple characters or a character that is not a lowercase letter between ‘a’ and ‘z’ , the guess is invalid. You should tell the player this (the exact format of this message is up to you) and ask them again for their guess. An invalid guess does not decrement the number of guesses.

lu1890tybba0 tmp e828b701f60018fc lu1890tybba0 tmp e05dcf80df5517d4 lu1890tybba0 tmp 8f8b026f6b77577e lu1890tybba0 tmp 9136fc9b002bafbd lu1890tybba0 tmp 5eb94e4cd4ce0dcb lu1890tybba0 tmp 91db92934455c867

Once the player makes a valid guess, tell everyone what guess that player made. (The exact format of this message is up to you.)

If the player guesses a letter that has not already been guessed and that letter is in the word, the player gets to guess again. Prompt the player whose turn it is with the query “Your guess?”, and once again tell everyone else (for example) “It’s Jen’s turn.”

The game ends in two situations. First, it ends when a player guesses the last hidden letter. Announce to the player, for example, “Game over! You win!” and tell everyone else, for example, “Game over! Karen won!” Second, the game ends when the players have zero guesses remaining. In that case, tell everyone “No guesses left. Game over.”

Once the game has ended (for either reason), it should restart with a new word to guess. The player who was supposed to guess next, gets the first turn.

Be prepared for the possibility that the player drops the connection (disconnects) when it is their turn to guess. Furthermore, you must notice user input or dropped connections even when it isn’t that player’s turn. If the player types something other than a blank line when it is not their turn, tell them “It is not your turn to guess.” For a blank line, you can say “It is not your turn to guess” or you can ignore it, whichever you prefer.

How does the server tell when a client has dropped a connection? When a client terminates, the socket is closed. This means that when the server tries to write to the socket, the return value of write will indicate that there was an error, and the socket is closed. Similarly, if the server tries to read from a closed socket, the

lu1890tybba0 tmp 2f9012572e3e9a04

return value from the read call will indicate if the client end is closed.

lu1890tybba0 tmp 2867460b37872f3a

As players connect, disconnect, enter their names, and make moves, the server should send to stdout a brief statement of each activity. (Again the format of these activity statements is up to you.) Remember to use the network newline in your network communication throughout, but not in messages printed on stdout .

lu1890tybba0 tmp 1fbb3af36d62cbd5 lu1890tybba0 tmp 9136fc9b002bafbd

You are allowed to assume that the user does not “type ahead” — if you receive multiple lines in a single read() , for this assignment you do not need to do what is usually required in working with sockets of storing the excess data for a future input.

lu1890tybba0 tmp da6e40e233a1c3c5

However, you can’t assume that you get the entire player name or guess in a single read() . For the input of the player name or guess, if the data you read does not include a network newline, you must loop to get the rest of the input.

lu1890tybba0 tmp d3f99492a71bba2d

To help you better understand the game play, we provide three sets of sample interactions. The messages displayed may vary, but behaviour of your program should be consistent with these interactions.

Please note that these interactions do not cover all possible scenarios and your program must take other situations into account. For example, the number of players can vary, and players can connect and disconnect at any time, including when it is a player’s turn.

In these interactions, our server logs show that we always read the word from index 0, since the dictionary used contained only one word for demonstration purposes. With a larger dictionary, we’d expect that index number to vary.

lu1890tybba0 tmp 23ae5eb91c4055b2 Interaction 1: game1_client_jen.txt lu1890tybba0 tmp 4cfd357d1add8f81 , game1_client_karen.txt lu1890tybba0 tmp e1af3357bad0eb74 , game1_server.txt lu1890tybba0 tmp 8635608a0c7d0938

lu1890tybba0 tmp 483fa0112f2e3b7c player Jen connects, then enters name

lu1890tybba0 tmp 483fa0112f2e3b7c player Karen connects, then enters name

lu1890tybba0 tmp 84b6179681eec9ed players make guesses (some correct, some incorrect, one out of turn) until player Karen wins

lu1890tybba0 tmp e26291c6940a5603 a new game starts

lu1890tybba0 tmp 55ebb896df435d9b player Jen disconnects

lu1890tybba0 tmp 8e264cf363fbfc20 player Karen disconnects

lu1890tybba0 tmp c3cff2ca4e22f12 server terminated

lu1890tybba0 tmp 85ecb48b59ef0528 Interaction 2: game2_client_jared.txt lu1890tybba0 tmp 744a58b820b0c1a8 , game2_client_mark.txt lu1890tybba0 tmp a5bbd2d589d7dab3 , game2_client_anisha.txt lu1890tybba0 tmp aef68276f88f0484 , game2_client_stathis.txt lu1890tybba0 tmp e209bea24a74a4b , game2_server.txt lu1890tybba0 tmp 48527279645bb02d

lu1890tybba0 tmp fe05986f355bc82 player Jared connects, enters name and guesses

lu1890tybba0 tmp 483fa0112f2e3b7c during Jared’s turn, player Mark connects and enters name

lu1890tybba0 tmp 3be2b69152aee494 during Jared’s turn, player Anisha connects and enters name

lu1890tybba0 tmp d3ffa0253286a88b when Jared’s turn ends, player Anisha guesses; players Mark and Jared disconnect during Anisha’s turn

lu1890tybba0 tmp 939adb621d979df3 the game ends with no winner

lu1890tybba0 tmp c6a213c9f181583 a new game starts

lu1890tybba0 tmp 8191f37f758895ec player Anisha guesses once

lu1890tybba0 tmp 6e393157e6bd180b player Anisha disconnects

lu1890tybba0 tmp 4abb772b5aab0fe0 player Stathis connects and enters name

lu1890tybba0 tmp dddb26712c3dff3d server terminated

lu1890tybba0 tmp b45df248ed118b6 Interaction 3: game3_client_jingyi.txt lu1890tybba0 tmp ceeb38fd0d81119c , game3_client_tudor.txt lu1890tybba0 tmp 34ef3dbe814149da , game3_server.txt lu1890tybba0 tmp dbd3cea0fa8437e0

lu1890tybba0 tmp 11ba1c94f072110f player Jing Yi connects, but does not enter name yet

player Tudor connects, enters name

lu1890tybba0 tmp 32bfdfd18eb76f63 player Tudor guesses incorrectly; player Tudor’s turn again

lu1890tybba0 tmp 6d3779168e3e1802 during player Tudor’s turn, player Jing Yi enters name

lu1890tybba0 tmp 12791fa1e96a6130 when player Tudor’s turn ends, it becomes player Jing Yi’s turn lu1890tybba0 tmp fe3a0bd5ad285af7 server terminated

lu1890tybba0 tmp def0173d35bbedab

To use nc , type nc ‐C hostname yyyyy (use lowercase -c on Mac), where hostname is the full name of the machine on which your server is running, and yyyyy is the port on which your server is listening. If you aren’t sure which machine your server is running on, you can run hostname ‐f to find out. If you are sure that the server and client are both on the same server, you can use localhost in place of the fully specified host name.

lu1890tybba0 tmp ec77fe72be9f2770

To test if your partial reads work correctly, you can send a partial line (without the network newline) from nc by typing Ctrl-D.

lu1890tybba0 tmp c1f9d1df50950fc5 lu1890tybba0 tmp 59f861a86a8b69e3

The TAs will be reading the output of your program (rather than using a script to match it against expected output). This means that your message do not need to exactly match the ones in this handout. However, your messages will be read by a person, so you want to make your output meaningful and readable.

Your code may be evaluated on:

lu1890tybba0 tmp 336255e9725bb7a5 Code style and design: At this point in your programming career you should be able to make good choices about code structure, use of helper functions, variable names, comments, formatting, etc.

lu1890tybba0 tmp f0b5a146020bf027 Memory management: your programs should not exhibit any memory leaks. Use valgrind to check your code.

lu1890tybba0 tmp f703957b8beaa0f7

lu1890tybba0 tmp 528fb30bb65aec0d Error-checking: library and system call functions (even malloc !) can fail. Be sure to check the return values of such functions, and terminate your program if anything bad happens.

lu1890tybba0 tmp e4e23b7f4d74a075

lu1890tybba0 tmp 2cbad13f1f8bab10 Warnings: your programs should not cause any warnings to be generated by gcc ‐Wall .

lu1890tybba0 tmp 700e961502f73a6a lu1890tybba0 tmp 583153e8297722fa

Your program must compile on teach.cs using gcc with the ‐Wall option and should not produce any error messages. Programs that do not compile, will get 0. You can still get part marks by submitting something that doesn’t completely work but does some of the job — but it must at least compile to get any marks at all. Also check that your output messages are exactly as specified in this handout.

lu1890tybba0 tmp 896829cfa3f0f687 lu1890tybba0 tmp cc45bbde03bc0c5 lu1890tybba0 tmp 526c39635013beaa lu1890tybba0 tmp 2272544f6af5a9fb

We will be looking for the following files in the a4 directory of your repository:

lu1890tybba0 tmp c3a7444f1e20ca08 Makefile

lu1890tybba0 tmp d946803c36408c63 wordsrv.c

lu1890tybba0 tmp 9c7ef465ec9de683 socket.c

lu1890tybba0 tmp d80fdce6812d3f87 socket.h


lu1890tybba0 tmp a96e7346e154fb74 gameplay.h

No other files will be accepted. Do not commit .o files or executables to your repository.

lu1890tybba0 tmp a9b5d119e502aa39

5页 共5 2019/3/23 14:05