Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Word Building Network Game With Intelligence

0.00/5 (No votes)
6 Feb 2005 1  
Word building game using C#.

gamemenu

Introduction

The word building game is a well known game all over the world. It is also called as scrabble. In this network-supported game, four players can play the game together sharing the same matrix board. Players can join their corresponding opponents directly by searching. I have used UDP sockets for searching the hosted game and TCP sockets for game processing. This game can be played within the subnet.

This network-supported game is intelligent. A player cannot fool the game by submitting non-English words. This game uses an English word list of around 55903 words. HashTable of C# is used for this implementation. This data structure is used to store the words. The game performs lookup operation when a player submits the word. New words can be added in wordlist.txt file present in the bin folder. The network infrastructure developed in this game is general purpose. Any game can use this underlying network infrastructure. I have added Howtoplay.pdf file for the instructions to play the game.

Game

In general, this game is a two-player game. Like all other games, these two players will have turns to put a single English alphabet in the given matrix of boxes so that they can form an English word in vertical direction or horizontal direction. Each player will get points equal to the length of the English word they form. Finally, the player with more points will win the game.

Game roles

After hosting or joining the game, the game instance can run one of the following roles:

  • Server Role
  • Client Role
  • Client Inactive Role

Server Role

The game will enter this role once it hosts the game. In this role, the client will act as a server where it will perform three tasks. First, it will listen for clients searching for an active host and reply to them with an acknowledgement message informing them of its presence. Second, it will wait for clients to request for joining the game. Once it receives the join request, it will process this request and it will reply to the sender with an acceptance message that has some needed information. Third, it will initialize and start the game by sending every client a special message notifying them about the game start event along with some other information to initialize the game state. The game will exit this role once it starts the game.

serverrole

The following code snippet is a thread that will handle this role.

private static void TcpServerRole()
{
    // start a TCP listener

    ServerListener = new TcpListener(GamePort);
    ServerListener.Start();

    //declare some variables

    Socket ss ; //server socket

    NetworkStream ns ;
    StreamReader sr;
    StreamWriter sw;
    string IncomingMessage ;

    while (true)
    {
        // wait for incoming messages

        ss = ServerListener.AcceptSocket(); 

        // create network, reader and writer streams

        ns = new NetworkStream(ss);
        sr = new StreamReader(ns);
        sw = new StreamWriter (ns);

        IPAddress ip; 
        // read the incoming message

        IncomingMessage = sr.ReadLine();

        // ((Type 1))

        // request for total number of connected players

        if (IncomingMessage=="NumberOfPlayers?") 
        {    
            // reply with the number of players

            sw.WriteLine(Game.ConnectedPlayers.Count.ToString());
            sw.Flush(); 
        }

        // ((Type 2))

        // request for all connected players

        if (IncomingMessage=="Players?") 
        {    
            // loop over all connectd players

            for ( int i=0 ; i < Game.ConnectedPlayers.Count ; i++)
            {    
                // send the player object

                sw.WriteLine(Game.ConnectedPlayers[i].ToString());
                sw.Flush();
                // send the player IP Address

                sw.WriteLine(ClientsAddresses[i].ToString());
                sw.Flush();
            }
        }

        // ((Type 3))

        // request to join the game

        if (IncomingMessage.StartsWith("Join"))
        {
            // get the player string by removing un-needed part

            string PlayerStr = IncomingMessage.Remove(0,4);
            // get the client (new player) IP Address

            ip = ((IPEndPoint)ss.RemoteEndPoint).Address;
            // send back the client, the Turn Index

            sw.WriteLine(Game.ConnectedPlayers.Count);
            sw.Flush();

            // add the new player IP Address

            ClientsAddresses.Add(ip);

            // Add the new player to connected players

            Game.ConnectedPlayers.Add(Game.ConvertStringToPlayer(PlayerStr));

            // update all other clients of the new player

            NewClientUpdateOthers(PlayerStr,ip);
        }

        // close the socket, end of request

        ss.Close(); 

    } //end while

}

Client Role

The game will enter this role by two ways: either by starting the game where it will switch from server role, or by receiving the turn message (the turn message notifies the client that it is his/her turn to play). In this role, the client can do two tasks. The first task is to receive the played action from the game and then send it to all other clients to update their internal game state. The second task is to pass the turn to the next player once the current player finishes his/her turn.

serverrole

Inactive Client Role

This role is the entry role for clients joining the game. The game will also enter this role once it is finished playing and has passed the turn to the next player. In this role, the client will wait for update messages that can be one of the following:

  • New player joined the game
  • Game has started, initialize your state
  • New action
  • It is your turn

Once clients join the game, they will wait to receive a new player update message. This message will contain both the new player object along with the IP address, thus enabling the clients to update their player list. Also, clients will need to initialize their game state according to the "Start Game" update message. Once the player list is complete and the game state is initialized, the clients are ready to receive new actions played by the current player in order to update their game states as needed. The client will switch to Client role once it receives "Your Turn" message which indicates the current player has finished playing and it is now your turn to play.

serverrole

Following code snippet will handle this role:

private static void UnactiveClient()
{
    // set the port that I will listen to

    int port = GamePort + Game.MyTurnIndex ;

    // create a TCP Listener 

    TcpListener Client = new TcpListener(port);
    Client.Start(); // start listening


    // define variables

    TcpClient cs ;
    NetworkStream ns ;
    StreamReader sr;
    string update;

    bool MyTurnFlag = true; 

    // loop until you receive your turn

    while (MyTurnFlag)
    {
        // wait for updates

        cs = Client.AcceptTcpClient();  

        // create network & reader streams

        ns = cs.GetStream();
        sr = new StreamReader(ns);

        // read the update

        update = sr.ReadLine();
                
        // string array to deal with the update

        string[] updateMsg; 

        // is it a NEW PLAYER Update Message

        if (update.StartsWith("New Player -->"))
        {
            // remove first part (Length of NewPlayer --> is 14)

            update = update.Remove(0,14); 

            // add the new player object 

            Game.ConnectedPlayers.Add(Game.ConvertStringToPlayer(update));

            // reads the new player IP Address

            update = sr.ReadLine();

            // add the new player IP Address to Address List

            ClientsAddresses.Add(update);

            // close the socket

            cs.Close();

        } 

        // is it a Game Start Update Message

        else if(update.StartsWith("Start Game-->"))
        {
            // A received message can be "Start Game-->5#2

            // Upto 5#2 everything is removed

            // 5 is the number of columns

            // 2 is the number of rows

            //remove unneeded info.

            update = update.Remove(0,13); 

            string[] rowcol = update.Split(new char[] {'#'});
            int row = Convert.ToInt32(rowcol[0]);
            int col = Convert.ToInt32(rowcol[1]);

            // These values will be used by MatrixDisplay function

            form.row = row;
            form.col = col;

            Game.IsGameStarted = true; // game state is started

            // close the client

            cs.Close();
            // display matrix on the user form

            form.Invoke(new displayMethod(form.MatrixDisplay),null);
        }
        else if ( update.StartsWith("alphabet"))
        {
            // Example alphabet-10-10-a#colour#


            string x1s;
            string y1s;
            int index;

            index = update.IndexOf("-");
            update = update.Remove(0,index+1);
            index = update.IndexOf("-");

            x1s = update.Substring(0,index);
            update = update.Remove(0,index+1);
            index = update.IndexOf("-");
            y1s = update.Substring(0,index);

            string update1 = update.Remove(0,index+1);
            update1 = update1.Substring(0,1);
            index = update.IndexOf("#");

            string colour = update.Remove(0,index+1);
            colour = colour.TrimEnd('#');

            // pass the parameters to DisplayAlphaBet method

            // This function displays the alphabet

            form.DisplayAlphaBet(Convert.ToInt32(x1s), 
                      Convert.ToInt32(y1s), update1,colour);
            cs.Close();
        }
        else if(update.StartsWith("Game Over"))
        {
            string[] ln = update.Split(new char[] {'#'});
            ln[0] =  ln[0].Remove(0,9);

            MessageBox.Show(ln[0] + " Won the game " + "Score:" + ln[1]);
            cs.Close();
        }
        else if (update.StartsWith("word"))
        {
            int index;
            string Stringtemp1;
            string Stringtemp2;
            Stringtemp1 = update;
            Stringtemp2 = update;

            // index extraction

            index = Stringtemp1.IndexOf("#");
            Stringtemp1 = Stringtemp1.Remove(0,index+1);

            index = Stringtemp1.IndexOf("@");
            Stringtemp1 = Stringtemp1.Substring(0,index);

            int LabelIndex = Convert.ToInt32(Stringtemp1);
            index = Stringtemp2.IndexOf("@");
            Stringtemp2 = Stringtemp2.Remove(0,index+1);

            int LabelScore = Convert.ToInt32(Stringtemp2);
            index = 0;

            index = update.IndexOf("#");
            update = update.Substring(0,index);
            index = 0;

            ArrayList xs = new ArrayList();
            ArrayList ys = new ArrayList();

            index = update.IndexOf("-");
            update = update.Remove(0,index+1);
            index = update.IndexOf("W");
            string coordinates = update.Substring(0,index);
            update = update.Remove(0,index+1);
            index = update.IndexOf("-");
            update = update.Remove(0,index+1);

            string[] ln = coordinates.Split(new char[] {'-'});
            for (int i=0;i < ln.Length;i+=2) 
                xs.Add(ln[i]);

            for (int i=1;i < ln.Length;i+=2)
                ys.Add(ln[i]);

            form.DisplayColour(xs,ys,update,LabelIndex,LabelScore);
            cs.Close();
        }

        // is it a Your Turn Message

        else if (update.StartsWith("TURN")) 
        {
            Game.MyTurn = true; // Set my turn

            MyTurnFlag = false; // exit from this state

            cs.Close(); // close the socket

            Client.Stop(); // stop client mode; do not listen for updates


            // Current player is the local Player

            Game.CurrentPlayerObj = Game.LocalPlayer;
        }
        else //ignore other messages

            cs.Close(); 
    } // End of while(true) statement

}

Diagrammatic view

When a user clicks the Host button, three threads will be started. Under Form1.cs class, a thread called as UpdateThread is started. This thread takes the information from ICommon interface and updates the information to the user interface form. UdpServerRole thread listens for UDP broadcast messages and acknowledges with the IP address of the machine where the game is hosted.

TcpServerRole deals with network messaging. It receives the messages from the network and responds to them and also updates to the interface ICommon. When a user clicks the Start Game button, TcpServerRole and UdpServerRole threads will be stopped and the main user will do some action. The following figures show a nice multi-threading environment.

serverrole

When a user clicks the Join button, UpdateThread and ClientThread start executing. ClientThread is a general purpose thread. When a user joins the game or loses his turn, this thread will run. It accepts New player, Start Game, Alphabet, Game Over, Word, and Turn messages from the network and updates to the interface ICommon.

serverrole

Limitations

  • Only four players can play.
  • Cannot play if behind a firewall or a NAT.
  • Players must agree before playing in order for them to know their IPs.
  • Since it is implemented in C#, it will not run on machines without .NET runtime environment.

Conclusion

In this article, a general-purpose network infrastructure is presented. Any game that is similar to the implemented word building game can be plugged into this infrastructure. The article serves as a re-usable component in other developments.

Acknowledgment

This game implementation is a course project for course ICS-571 (Information and Computer Science) namely Client/Server programming, taught by Assistant Professor Nasir Al-Darwish at King Fahad University of Petroleum and Minerals, Kingdom of Saudi Arabia, Dhahran. His email address is darwish@kfupm.edu.sa. From this course, many new concepts have been learned and implemented.

References

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here