Noughts and Crosses

Noughts and Crosses or Tic-Tac-Toe is a very simple game to play and also to create with this Tutorial using Silverlight on Windows Phone 7.

www.cespage.com/silverlight/wp7tut9.html

Step 1

Start Microsoft Visual Studio 2010 Express for Windows Phone, then Select File then New Project... Select "Visual C#" then "Silverlight for Windows Phone" and then "Windows Phone Application" from Templates, select a Location if you wish, then enter a name for the Project and then click OK, see below:

New Project

Step 2

A Windows Phone application Page named MainPage.xaml should then appear, see below:

MainPage.xaml

Step 3

In the XAML Pane for MainPage.xaml between the <Grid x:Name="ContentGrid" Grid.Row="1"> and </Grid> lines, enter the following XAML:

<Grid x:Name="ContentMain">
  <Grid.RowDefinitions>
    <RowDefinition Height="*"/>
    <RowDefinition Height="Auto"/>
  </Grid.RowDefinitions>
  <Button Grid.Row="1" Width="160" Content="new" Click="New_Click"/>
</Grid>

XAML:

MainPage XAML View

Design:

MainPage Design View

Step 4

Then from the Windows Phone Controls section in the Toolbox select the Grid control:

Grid Control

Step 5

Draw a Grid on the Page by dragging a Grid from the Toolbox onto the middle part of the Grid on the Page, then in the XAML Pane change the "grid1" line to the following:

<Grid Height="400" Width="400" Name="Display"/>

See below:

MainPage with Grid

Step 6

Right Click on the Page or the entry for "MainPage.xaml" in Solution Explorer and choose the "View Code" option. In the Code View above "public MainPage()" type the following declarations:

bool _hasWon = false;
string _piece = "";
string _nought = "O";
string _cross = "X";
string[,] _board = new string[3,3];

See Below:

MainPage Declarations

Step 7

While still the Code View for MainPage.xaml.cs above "public MainPage()" type the following Methods:

private bool Winner()
{
  return
  (_board[0, 0] == _piece && _board[0, 1] == _piece && _board[0, 2] == _piece) ||
  (_board[1, 0] == _piece && _board[1, 1] == _piece && _board[1, 2] == _piece) ||
  (_board[2, 0] == _piece && _board[2, 1] == _piece && _board[2, 2] == _piece) ||
  (_board[0, 0] == _piece && _board[1, 0] == _piece && _board[2, 0] == _piece) ||
  (_board[0, 1] == _piece && _board[1, 1] == _piece && _board[2, 1] == _piece) ||
  (_board[0, 2] == _piece && _board[1, 2] == _piece && _board[2, 2] == _piece) ||
  (_board[0, 0] == _piece && _board[1, 1] == _piece && _board[2, 2] == _piece) ||
  (_board[0, 2] == _piece && _board[1, 1] == _piece && _board[2, 0] == _piece);
}

private bool Drawn()
{
  return 
  _board[0, 0] != "" && _board[0, 1] != "" && _board[0, 2] != "" &&
  _board[1, 0] != "" && _board[1, 1] != "" && _board[1, 2] != "" &&
  _board[2, 0] != "" && _board[2, 1] != "" && _board[2, 2] != "";
}

See Below:

MainPage Numbers Method

Step 8

While still the Code View for MainPage.xaml.cs, below the "}" of the "private bool Drawn()" method type the following Method:

private Path GetPiece()
{
  if ((_piece == _cross)) // Draw X
  {
    Path _lines = new Path();
    LineGeometry _line1 = new LineGeometry();
    LineGeometry _line2 = new LineGeometry();
    GeometryGroup _linegroup = new GeometryGroup();
    _line1.StartPoint = new Point(0, 0);
    _line1.EndPoint = new Point(64, 64);
    _line2.StartPoint = new Point(64, 0);
    _line2.EndPoint = new Point(0, 64);
    _linegroup.Children.Add(_line1);
    _linegroup.Children.Add(_line2);
    _lines.Data = _linegroup;
    _lines.Stroke = new SolidColorBrush(Colors.Red);
    _lines.StrokeThickness = 6;
    _lines.Margin = new Thickness(5);
    return _lines;
  }
  else // Draw O
  { 
    EllipseGeometry _ellipse = new EllipseGeometry();
    Path _circle = new Path();
    _ellipse.Center = new Point(32, 32);
    _ellipse.RadiusX = 32;
    _ellipse.RadiusY = 32;
    _circle.Data = _ellipse;
    _circle.Stroke = new SolidColorBrush(Colors.Blue);
    _circle.StrokeThickness = 6;
    _circle.Margin = new Thickness(5);
    return _circle;
  }
}

See Below:

MainPage GetPiece Method

Step 9

While still the Code View for MainPage.xaml.cs, below the "}" of the "private Path GetPiece()" method type the following Button Event Handler:

private void Button_Click(object sender, System.Windows.RoutedEventArgs e)
{
  if (!_hasWon)
  {
    Button _btn = new Button();
    _btn = ((Button)(sender));
    if ((_btn.Content == null))
    {
      _btn.Content = GetPiece();
      _board[(int)_btn.GetValue(Grid.RowProperty),
      (int)_btn.GetValue(Grid.ColumnProperty)] = _piece;
    }
    if (Winner())
    {
      _hasWon = true;
      MessageBox.Show((_piece + " wins!"), "Noughts and Crosses", MessageBoxButton.OK);
    }
    else if (Drawn())
    {
      MessageBox.Show("Draw!", "Noughts and Crosses", MessageBoxButton.OK);
    }
    else
    {
      _piece = ((_piece == _cross) ? _nought : _cross); // Swap Players
    }
  }
  else
  {
    MessageBox.Show("Game Over!", "Noughts and Crosses", MessageBoxButton.OK);
  }
}

See Below:

MainPage Button Click Method

Step 10

While still the Code View for MainPage.xaml.cs, below the "}" of the "private void Button_Click(...)" method type the following Methods:

private void Add(ref Grid Grid, int Row, int Column)
{
  Button _btn = new Button();
  _btn.Click += Button_Click;
  _btn.Content = null;
  _btn.Margin = new Thickness(2);
  _btn.SetValue(Grid.ColumnProperty, Column);
  _btn.SetValue(Grid.RowProperty, Row);
  Grid.Children.Add(_btn);
}

private void Layout(ref Grid Grid)
{
  Grid.Children.Clear();
  Grid.ColumnDefinitions.Clear();
  Grid.RowDefinitions.Clear();
  // Setup 3x3 Grid
  for (int Index = 0; (Index <= 2); Index++)
  {
    Grid.RowDefinitions.Add(new RowDefinition());
    Grid.ColumnDefinitions.Add(new ColumnDefinition());
  }
  Add(ref Grid, 0, 0); // Top Left
  Add(ref Grid, 0, 1); // Top Middle
  Add(ref Grid, 0, 2); // Top Right
  Add(ref Grid, 1, 0); // Middle Left
  Add(ref Grid, 1, 1); // Centre
  Add(ref Grid, 1, 2); // Middle Right
  Add(ref Grid, 2, 0); // Bottom Left
  Add(ref Grid, 2, 1); // Bottom Middle
  Add(ref Grid, 2, 2); // Bottom Right
}

See Below:

MainPage Add and Layout Methods

Step 11

While still the Code View for MainPage.xaml.cs, below the "}" of the "public MainPage()" method type the following Event Handler:

private void New_Click(object sender, RoutedEventArgs e)
{
  Layout(ref Display);
  _board[0, 0] = "";
  _board[0, 1] = "";
  _board[0, 2] = "";
  _board[1, 0] = "";
  _board[1, 1] = "";
  _board[1, 2] = "";
  _board[2, 0] = "";
  _board[2, 1] = "";
  _board[2, 2] = "";
  _hasWon = false;
  if ((MessageBox.Show((_cross + " to go first?"), "Noughts and Crosses", 
  MessageBoxButton.OKCancel) == MessageBoxResult.OK))
  {
    _piece = _cross;
  }
  else
  {
    _piece = _nought;
  }
}

See Below:

MainPage Event Handler

Step 12

Save the Project as you have now finished the Windows Phone Silverlight application. Select the Windows Phone Emulator option then Select Debug then Start Debugging or click on Start Debugging:

Start Debugging

After you do, the following will appear in the Windows Phone Emulator after it has been loaded:

Application Running

Step 13

Tap the "new" Button, it will ask "X to go first?", choose OK for "X" or Cancel for "O", then the following will appear:

Noughts and Crosses

Step 14

You can then Stop the application by selecting the Visual Studio 2010 application window and clicking on the Stop Debugging button:

Stop Debugging

This is a very simple game, try adding more advanced features such as a Computer-based Player 2 using Random Numbers, or just try changing the colours used - make it your own!