Consuming the TicTacToe Web Service with C#Builder by Bob Swart

By: Bob Swart

Abstract: In this article, Bob Swart shows you how to use C#Builder to import a web service, and use it to build a WinForms application that can be used as a TicTacToe game client.

In this article, I'll show you how to use C#Builder to import a web service, and turn it into a TicTacToe game client. Source code (which can also be compiled using the C# command-line compiler from the .NET SDK) is already available in the BDS\1.0\Examples\C#\Web Services\Tic Tac Toe directory, as well as CodeCentral, but feel free to start C#Builder and type along to see how I've created and build this project.

C#Builder Project
The project of today consists of two parts: the user interface (a WinForm) and the engine, which is based on an imported web service. The web service itself was implemented in Delphi 6 a few years ago, and is available on the web as http://www.eBob42.com/cgi-bin/TicTacToe.exe/wsdl/ITicTacToe (hosted by TDMWeb).
Start C#Builder and do File | New - C# Application to start a new project. In the dialog, we can enter the name of the project (like TTT) which results in the project being created in the C:\Documents and Settings\Administrator\My Documents\Borland Studio Projects\TTT directory (in the current user directory, that is - I'm just playing as administrator).

After you click on OK, a new project will be created for you with an empty WinForm. As first thing, I want to add a main menu to the WinForm. Using the menu designer, I create a menu structure Game | New Game with the submenu options Computer Starts and Human Starts. The latter two are the only one that will get an event handler, the others have only a cosmetic purpose (and make it a bit harder to start a new game by accident).

Next, drop nine buttons (from top-left to bottom-right) but call them btn8, btn3, btn4, btn1, btn5, btn9, btn6, btn7, btn2, set their Tag property (which is an Object in .NET, not an Integer) to the number of the button (so upper-left gets Tag 8, upper-middle gets Tag 3, etc.). This will ensure that the user interface also uses the magic square algorithm implemented by the TicTacToe web service.
Select all buttons and set their font to Comic Sans MS, Bold, 24 point and clear their Text property.

Add Web Reference
Now, before we write some event handlers (for the two menu items and the nine buttons), we should first import the web service to work with. Do Project | Add Web Reference and enter the URL for the TicTacToe web service in the search box. The URL is http://www.eBob42.com/cgi-bin/TicTacToe.exe/wsdl/ITicTacToe as you can see in the following screenshot.

The Add Reference button will be enabled only when the UDDI Browser (the Add Web Reference dialog) shows an actual WSDL definition. In all other cases you can use this dialog as simple web browser, but nothing more.
With the button enabled, click on Add Reference which will import the external web service and create a web reference and add it to our project. The Project Manager will illustrate how the Web Reference as well as the Reference.cs file are now embedded in our project:

The Reference.cs file contains the imported web service .

Writing C# Code
Finally, we've come to the point where we can delay it no longer: we have to write some C# code. Before we can implement the event handlers, I first need to add some special variables (like the TTT variable that points to an instance of the TicTacToe web service, a Game handle and an indicator to know that the computer or human has won the game). The best place to add these is right after the implementation of the Main() method in the source file of the WinForm:

    private ITicTacToeservice TTT = null;
    private int Game = 0;
    private int TTTIsWinnerGame = 0;

These declarations need to be followed by the implementation of four methods: Init_TTT, and Clear_Board. The former is used to delay load the instance of the TicTacToe web service - we should call Init_TTT before using the TTT variable, and this will make sure a server instance is only created when we actually need it (so if you start the game executable but exit it right away, you won't need a connection to the server, and none will be made). The Clear_Board method is used to clear the captions of the nine buttons again, and reset the TTTIsWinnerGame variable. To be called right before a new game starts.

    private void Init_TTT()
    {
      if (TTT == null)
      try
      {
        TTT = new ITicTacToeservice();
      }
      catch (Exception ex)
      {
        MessageBox.Show(ex.Message, "Error");
      }
    }

    private void Clear_Board()
    {
      btn1.Text = "";
      btn2.Text = "";
      btn3.Text = "";
      btn4.Text = "";
      btn5.Text = "";
      btn6.Text = "";
      btn7.Text = "";
      btn8.Text = "";
      btn9.Text = "";
      TTTIsWinnerGame = 0;
    }

There are two more methods we need to implement before we can step up to the event handlers: ComputerMove and HumanMove. Obviously, we need to know the difference between Human (1) and Computer (2), and I've hardcoded the fact that the computer plays with the character "42" and the human with crosses. Feel free to add your own stuff here - even images if you feel inspired.

    const int Human = 1;
    const int Computer = 2;

    private void ComputerMove()
    {
      int Move = TTT.NextMove(Game, Computer);
      TTT.MakeMove(Game, Computer, Move);
      switch (Move)
      {
        case 1: btn1.Text = "42"; break;
        case 2: btn2.Text = "42"; break;
        case 3: btn3.Text = "42"; break;
        case 4: btn4.Text = "42"; break;
        case 5: btn5.Text = "42"; break;
        case 6: btn6.Text = "42"; break;
        case 7: btn7.Text = "42"; break;
        case 8: btn8.Text = "42"; break;
        case 9: btn9.Text = "42"; break;
      }
      TTTIsWinnerGame = TTT.IsWinner(Game);
      if (TTTIsWinnerGame == Computer)
        MessageBox.Show("I have won this game!");
    }

    private void HumanMove(object NewMove)
    {
      int Move = Convert.ToInt32(NewMove);
      TTT.MakeMove(Game, Human, Move);
      TTTIsWinnerGame = TTT.IsWinner(Game);
      if (TTTIsWinnerGame == Human)
        MessageBox.Show("Congratulations: you have won!");
      else
        if (TTT.NextMove(Game, Computer) > 0)
          ComputerMove();
    }

At this time, we can implement the two menu choice event handlers. The first one (menuItem3_Click is fired when the "Computer Starts" is selected, and the second one (menuItem4_Click) is fired when the human (enduser) starts. Both call Init_TTT and Clear_Board as explained before, and call NewGame to get a unique new game handle. As debugging help, the application puts the Game handle of the new game in the caption of the dialog. The TicTacToe game server can play many games at the same time, and doesn't store the game state in memory (but in a local .ini file - one for each game). It's up to the client to maintain it's own state on the game board.

    private void menuItem3_Click(object sender, System.EventArgs e)
    {
      // Computer Starts
      Init_TTT();
      Clear_Board();
      Game = TTT.NewGame();
      Text = "Game: " + Convert.ToString(Game);
      ComputerMove();
    }

    private void menuItem4_Click(object sender, System.EventArgs e)
    {
      // Human Starts
      Init_TTT();
      Clear_Board();
      Game = TTT.NewGame();
      Text = "Game: " + Convert.ToString(Game);
    }

Finally, we can implement the Click event handler of the nine buttons. They should all point to the same event handler (so implement it once for the button on the upper-left corner - btn8 - and point all others to the same btn8_Click event handler). Since each button has a different value of their Tag property, it's easy to use that to identify the value of the position on the game board.

    private void btn8_Click(object sender, System.EventArgs e)
    {
      if (Game == 0) menuItem4_Click(sender, e);
      switch (TTTIsWinnerGame)
      {
        case Computer:
          MessageBox.Show("Computer has already won!"); break;
        case Human:
          MessageBox.Show("You have already won!"); break;
        default:
          if ((sender as Button).Text == "")
          {
            (sender as Button).Text = "X";
            Update();
            HumanMove((sender as Button).Tag);
          }; break;
      }
    }

If you want, you can add some more cosmetic stuff, like an icon to the form (like the eBob42.ico from me), you can set MaximizeBox to False, and to avoid resizing, set the MaximumSize and MinimumSize to the values of the Size property (this may result in an ugly application when using large fonts - I haven't tried yet).

Compile and Run
Now, save your work, compile and run it for the first time. Note that you need an internet connection in order to reach the TicTacToe server - otherwise the client will complain with an exception.

In order to deploy the application, set Project Options to Release and compile for the last time. Note that C#Builder created .NET executables that require version 1.1 of the .NET Framework, so the executables won't run on .NET Framework 1.0.

Summary
In this article I have shown how we can create a new C#Builder application, import web services (by adding a web reference) and compile, run and deploy the application. In future articles we'll explore other capabilities of C#Builder in more details, so stay tuned.
Feel free to send me feedback, comments or any questions about this article. You can either e-mail me directly, or use the borland.public.csharpbuilder.* newsgroups.


Bob Swart (aka. "Dr.Bob" - http://www.drbob42.com) is author, trainer, consultant, developer, and webmaster for his own company Bob Swart Training & Consultancy (eBob42) in Helmond, The Netherlands. Bob is overseas member and webmaster for the UK-BUG Borland User Group as well as the Dotnet Developers Group (DDG). Bob is a technical author for The Delphi Magazine, Borland .NET Developer's Journal, C++Builder Developer's Journal, Hardcore Delphi, Der Entwickler, SDGN Magazine, UK-BUG Developer's Magazine, writes the IBM DB2 and Borland web portals, and has spoken at (Borland) conferences all over the world since 1994.
Bob is married to Yvonne and they have two internet-aware children: Erik Mark Pascal (9 years) and Natasha Louise Delphine (6.5 years).


Server Response from: ETNASC03