Description

Our project was to sucessfully write and implement a client/server Scrabble game. The Scrabble game is based on the Milton Bradley game by the same name where the object is to form interlocking words in a crossword fashion on the Scrabble board using letter tiles of different values. Each players is competing for the highest score by taking advantage of the letter values, as well as the premium squares on the board. The players will all log on with a unique identity and maintain that login for the duration of the game. There must be at least two people and at most four people playing the game. The user will place a word on the board by clicking the mouse on the desired position on the Scrabble board. A window will pop up where the user can type in the desired word and also specify which direction he/she wants the letters to flow in (either in the top down direction or in the left right direction, the only two direction flows a word can be placed in). The project was broken down into three different parts, a client side, a server side, and a side that takes care of all the logic involved with handling the words and deciding whether they are valid or not. The server will be written in C on the Sun Sparc platform being OS independent. The client side will be written in Java. The logic portion of the project will be written in C.

GUI

On the client end, we had a total of 4 different GUI's designed. We designed a login GUI, a Scrabble Board GUI, a word layout GUI, and then finally an error messages GUI. The login GUI is there simply to define a name for the user to be known throughout the game. It's not necessary for the user to have either a username or password on the system. The second GUI is the Scrabble Board GUI. It is the most complex out of all the GUI's and contains the playing board as well as the chat screen and the player's score. The third GUI is the word layout GUI, which is a user interface for the player to type in the word that he wants to submit. Our Scrabble board will require the user to click a button on the square he/she wants to place the BEGINING of the word. This will then pop up a screen on which the user will type in the word itself, and also specify which direction the word will flow in (i.e. from up to down or from left to right, the only directions that a word can be placed on our board). From there, the word and it's direction will be sent to the server to check it's validity and also to determine if there has been a collision with any other words. The last GUI we are implementing is a simple error message GUI where error messages will display if the user makes a mistake. All of the client code has been packaged together under the package name "Client".

We first started out by designing the Scrabble board and how we would want it to look. The board has 15*15 squares with special scores on certain strategic spots. We decided that the easiest way to display the scrabble board would be to draw the entire scrabble board out and paint it the colors that we would want. Then, to figure out where on the Scrabble board the users was clicking on (to place tiles), we used a series of MouseDown actions that determine the x and y locations of the mouse, and then decide where on the board that x and y location is. Once we got down with the Scrabble side of the board, we turned our focus to the Chat Window. We wanted a little window so that the user could chat back and forth with other players on the team. At this point, we discovered the need to thread the replies that the client was receiving from the server because otherwise, the client would freeze up while waiting for the server to send a reply. The chat box to display other players' message was a TextArea with scroll bars, while the chat box to send out messages from the player was a TextField. A score board was then added as well as some buttons on the bottom of the screen. In order to find an appropriate layout for the frame, I decided to use a series of panels. Each little sub-section would lie within their own panel, while would be within another panel, and then so on until they were incorporated into the final main panel. I used Border Layout, Grid Layout, and Flow Layout in some of the different sections in order to achieve a certain effect. The other GUI's were simple GUI's written to display certain information using mainly Text Fields, Labels, and Buttons.

Networking

The project uses a client-server method to handle the networkind issues. The server was written in C. The first thing the server does is set up a socket to listen to. Once the socket is set up, it listens for new connections. Once connections have been made, the server will use a polling method to listen to the various connections for incoming messages, or the socket for incoming connections. It uses the select() system call to do this. The select() function will put the CPU to sleep, and once incoming messages or connections have been made, it wakes up the CPU and sets a bit in an integer array to signify which file descriptor received new information. The server then searches through all the current file descriptors and finds any descriptors that have new information. If the file descriptor belongs to a player, it knows that it is a message passed to the server from a client, or the player associated with the descriptor has logged off. The incoming message is then parsed. All messages have the format:

opcode:arguments

The server then takes the apropriate actions based on the opcode. Here are the meanings of a few different opcodes:

1: Set name
2: Set play now flag for player
3: Chat message
4: Place a word
5: Challenge recent word
6: Trade tiles


Once enough connections have been made to play a game, the server will create a child process which is an exact copy of itself using the fork() system call. The child process will handle all client-server interactions for that game. The parent process will then listen for new connections for a new game.

The only time the server will send out messages is after it has read something in. The client does not have this synchronized messaging method available to it. Specifically, the client may receive information from the server whether or not it has written a message to the server. One clear example of this is the chat window. Many messages can come in for the player to read without the player having sent out a single message. In order to accomidate this asynchronous behaviour, a special networking class had to be created.

The new networking class needed to run on its own thread. It basically consists of a loop where the thread reads off new incoming messages from the socket. Once a new incoming message has been read, the thread will pass the message back to the Scrabble class for parsing and where the apropriate actions are taken. It then goes back and listens for more incoming messages. Incoming message have the same format as mention above, and the opcodes were designed to take on the same type of meaning. A typical chat message would be handled by the network class in the following manner:

1) Read new incoming message from the socket (3:Hello World)
2) Pass message to Scrabble class where it is parsed.
3) The message has been identified as a chat message, therefore print the string sent with the message in the chat window
4) Wait for new message


The main resource used to create the server code was UNIX Network Programming by W. Richard Stevens. The resources for the client networking were the required and recommended textbooks for the class.

server.c
game.c

Logic


The basic rules of the Milton/Bradley game of Scrabble (r):
The majority of the logic is manipulation of arrays, both one and two dimensional. The following are functions that showed the manipulation of arrays. The random letter generator was handled with the use of the time.h library. The commands srand and rand were used along with the mod function, to statistically choose tiles correctly to give to each of the players.

Part of the random tile generator code:

 
int Random_Tile(int *letter_is, int j)
{
  int rn = 0; /*RANDOM NUMBER*/
  int found = 0; /*ARRAY PLACE TRACKER*/
  
  rn = rand();
  rn = rn%MAX_TILES;

  while(counter[found] != 0){ /*GETS RANDOM NUMBER*/
    {
      if (rn>=0 && rn<9){
	*letter_is = A_LETTER;
	found = rn;
      }
..................................................

	EDITED OUT TO CONSERVE SPACE
.................................................
     if (rn>=98 && rn<100){
	*letter_is = BLANK_LETTER;
	found = rn;
      }
    }
    
    if (counter[found] == 0) /*CHECKS TO SEE IF RN WAS CHOSEN ALREADY*/
      Random_Tile (letter_is,j);
    counter[found] = 0; /*NEW RN FOUND!!! REPLACES 1 WITH A 0 IN ARY*/
    T_board[j] = found; 
  }/*END OF while(counter[found]!=0)*/
  Players_Sideboard[j] = *letter_is + 96;
  found = MAX_TILES+1; /*SO WE CAN RUN THE LOOP AGAIN =)*/

}/*END OF Random_Tile()*/

The placement of tiles on the Scrabble board is also a manipulation of arrays. Most of the logic's complications arrose at this stage. The main problem was not keeping track of all the letters, but making sure that letters were placed in a valid spot. The main reason there might not be a valid spot is due to the fact that the player before you has placed a word down on the Scrabble board. To make sure that the letters were placed in correct places was handled by arrays. Always making sure that before you place a letter on the board, the square is empty. If there is a letter in the sqaure already, then making sure that the letter is what the player wanted originally. Also, there is a need for a check to make sure that there are no letters surrounding the letters that the player places unless the player intended on doing so to create additional words.

Part of the tile placement code:


void Tile_Placement(int Down_or_Right, char *Players_Sideboard, int x, int y, char *word)
{
  count = strlen(word);
  
  for(l = 0; l < count; l++){
    for(p = 0; p < 7; p++)
      if (word[l] == Players_Sideboard[p]){
	Tile_Num = p;
	break;
      }
    if(Tile_Num < 7)
      {
	if (m==0)
	  U_board[l] = Players_Sideboard[Tile_Num];
	else
	  U_board[l+m] = Players_Sideboard[Tile_Num];
	
	if(Scrabble_board_CHAR[x][y] == '_')
	  {
	    if(m==0)
	      {
		Scrabble_board_CHAR[x][y] = U_board[l];
		if(Down_or_Right == 0)
		  x++;
		else
		  y++;
	      }
..................................................

	EDITED OUT TO CONSERVE SPACE
.................................................
    else{
      printf("YOUR WORD IS NOT VALID!!\n");
      break;
    }
    j = Tile_Num;
    Random_Tile (letter_is,j); 
  }
  count = 0;
  m = 0;
  
}/*END OF void Tile_Placement(int Down_or_Right, char *Players_Sideboard, int x, int y, char *word)*/

The game ends when the tiles are all given out. The player's score is tally during the course of the game, making sure to keep track of the bonus point squares. The player with the highest score is declared the winner.