I am excited to see Windows 7 phone coming to live slowly. And as always I wanted to play with this new toy and make something to get my feet wet. After watching the introductory videos, I figured out that I will make a simple game. Well Tic Tac Toe was my choice. I tried to stay away from complex logic and class seperation at this point. This is a Introductory project and just want it to work. So without any delay I will walk you through the process.
First of all, if you haven’t downloaded the Developer tools you can go here and download it. You will also find useful documentations. If you just want to watch few videos, go to Windows Phone 7 in 7 Minutes! (Beta) site.
- Fire up your Visual Studio 2010.
- Select Visual C# node (I used C#)
- Select Windows Phone Application
- I named my project TicTacToe ( you can name it whatever you want). (Don’t get confused if you see TicTacToe2 on the pictures. It is just for the pics).
Now you are on the Mainpage.xaml. You can items on your xaml and graphically as you want.
- Click on Page Name.
- On the right hand side (properties window), find Text and change it to Tic Tac Toe.
- You can Change the Application Name from My Application to whatever you want.
- On your left click on ToolBox and Drag 9 textboxes on the canvas. I named them TopLeft1, TopMiddle1, TopRight1, MiddleLeft1, MiddleMiddle1, MiddleRight1, BottomLeft1, BottomMiddle1, BottomRight1. You can do this right on the xaml or properties.
- Size them into squares.
- Click on each button to generate the click events.
- Add a TextBox on the bottom and change text to “Game On!!!â€Â
- One you are done your xaml’s <Grid> segment should look like below.
<Grid x:Name="ContentGrid" Grid.Row="1"> <Button Content=" " Height="82" HorizontalAlignment="Left" Margin="107,150,0,0" Name="TopLeft1" VerticalAlignment="Top" Width="89" Click="TopLeft1_Click" Background="#00EF0303" /> <Button Content=" " Height="82" HorizontalAlignment="Left" Margin="299,150,0,0" Name="TopRight1" VerticalAlignment="Top" Width="89" Click="TopRight1_Click" /> <Button Content=" " Height="82" HorizontalAlignment="Right" Margin="0,150,190,0" Name="TopMiddle" VerticalAlignment="Top" Width="89" Click="TopMiddle_Click" /> <Button Content=" " Height="82" HorizontalAlignment="Left" Margin="299,326,0,0" Name="BottomRight1" VerticalAlignment="Top" Width="89" Click="BottomRight1_Click" /> <Button Content=" " Height="82" HorizontalAlignment="Left" Margin="201,326,0,0" Name="BottomMiddle1" VerticalAlignment="Top" Width="89" Click="BottomMiddle1_Click" /> <Button Content=" " Height="82" HorizontalAlignment="Left" Margin="106,326,0,0" Name="BottomLeft1" VerticalAlignment="Top" Width="89" Click="BottomLeft1_Click" /> <Button Content=" " Height="82" HorizontalAlignment="Left" Margin="299,238,0,0" Name="buMiddleRight1" VerticalAlignment="Top" Width="89" Click="buMiddleRight1_Click" /> <Button Content="" Height="82" HorizontalAlignment="Left" Margin="201,238,0,0" Name="MiddleMiddle1" VerticalAlignment="Top" Width="89" Click="MiddleMiddle1_Click" /> <Button Content="" Height="82" HorizontalAlignment="Left" Margin="106,238,0,0" Name="MiddleLeft1" VerticalAlignment="Top" Width="89" Click="MiddleLeft1_Click" /> <TextBox Height="72" HorizontalAlignment="Left" Margin="36,479,0,0" Name="textBox1" Text="Game On !!!!" VerticalAlignment="Top" Width="383" /> </Grid>
Now your UI is all set.
We will define a value for each button on the canvas.
1 2 3
4 5 6
7 8 9
There are few winning combinations
Horizontally
123, 321
456, 654
789, 987
Vertically
147 , 741
258 , 852
369 , 963
Diagonally
159 , 951
357 , 753
Well, if we just can sort and go one way we can eliminate the reverse order so our logic segment will have to only work half as hard. You can call me lazy if you want.
Now what other logic can I find in there. hmmm.
Well when all the lines match except for the top (lowest value number) and bottom (most valued numbers) it all equals to 15.
The top if matches equal to 6 and bottom equals to 24.
Also left vertical will equals to 12 and right vertical equals to 18.
We will have special cases for these two since 12 and 18 can be in few different ways
12 = (3, 4, 5 ) (2,3,7) (1,3,8) (1,4,7)
18 = (3,6,9) ( 1,8,9) (2,7,9) (4,5,9)
(I have left this logic out for now for simplicity and will implement the login on Part 3)
Wait, there are more. To have this logic actually work for us, we have to make sure that there are 3 numbers that comes together for that sum of values.
So here is the logic for the core
-
If there are 3 numbers
-
That equals to 15
-
Or 24
-
or 6
Then we have a winner. Simple isn’t it? Feel free to improve it if you want or point out the flaws in this logic.
Now we also need to keep track of players and boxes that are checked
-
Since they will alternate after each move. That’s easy to do, just have identifier to identify the whose move is next.
-
and create a list<int> where you can store all the values that are selected so far.
-
I also have Hard coded player name as â€ÂPlayer 1†and “Player 2â€Â. You can use input box to create dynamic names if you want.
-
Also to keep track of each players moves I have created 2 List<int> where I keep track of each player moves.
Ok Back to Programming.
- private const string _player1 = "Player 1";
-         private const string _player2 = "Player 2";
-         private List<int> player1Moves;
-         private List<int> player2Moves;
-         private int _nextMoveFor;
-         private List<int> _notAvailablePositions;
You need to instantiate the list at the startup and identify the first players move. Do this on the constructor
- // Constructor
-         public MainPage()
-         {
-             InitializeComponent();
-             player1Moves = new List<int>();
-             player2Moves = new List<int>();
-            ÂÂ
-             _notAvailablePositions = new List<int>();
-             _nextMoveFor = (int)Players.Player1;
-            ÂÂ
-         }
You will have to create a method that will handle your Button Selection. You need to pass the button that was selected and number for that button.
I called this HandleBoxSelection
- /// <summary>
-         /// Handles the box selection.
-         /// </summary>
-         /// <param name="buttonId">The button id.</param>
-         private void HandleBoxSelection(int buttonId, object sender)
-         {
-             if (IsPositionAvailable(buttonId) == true)
-             {
-                 if (_nextMoveFor == (int)Players.Player1)
-                 {
-                     ChangeForSelected(Players.Player1, buttonId,sender);
-                 }
-                 else
-                 {
-                     ChangeForSelected(Players.Player2, buttonId, sender);
-                 }
-                 _notAvailablePositions.Add(buttonId);
-             }
-         }
This is a very simple method. It Checks If the position is available for that button. If it is then checks who is changing the move and changes for the person. You got introduced to 3 new things here. 2 Methods IsPositionAvailable and ChangeForSelected and a enum called Players. They are below.
- public enum  Players
- {
-     Player1 = 1, Player2 = 2
- }
Is PositionAvailable is very simple. Just goes through the list of already selected values and if there are no match it means the position is still available.
- /// <summary>
-         /// Determines whether [is position available] [the specified position].
-         /// </summary>
-         /// <param name="position">The position.</param>
-         /// <returns>
-         ///     <c>true</c> if [is position available] [the specified position]; otherwise, <c>false</c>.
-         /// </returns>
-         private bool IsPositionAvailable(int position)
-         {
-             bool retVal = true;
-             if (_notAvailablePositions.Count > 0)
-             {
-                 foreach (int item in _notAvailablePositions)
-                 {
-                     if (position == item)
-                     {
-                         retVal = false;
-                     }
-                 }
-             }
-             return retVal;
-         }
Change for Selected has few things.
- Adding the move to appropriate player.
- Setting the flag for move to the next player.
- Changing the Button que to “X†or “Oâ€Â.
- Checking the GameLogic to see if we have a winning number.
-     /// <summary>
-     /// Changes for selected.
-     /// </summary>
-     /// <param name="player">The player.</param>
-     /// <param name="buttonId">The button id.</param>
-     private void ChangeForSelected(Players player, int buttonId, object sender)
-     {
-         bool isWinner = false;
-         string winner = string.Empty;
-         if (player == Players.Player1)
-         {
-             player1Moves.Add(buttonId);
-             _nextMoveFor = (int) Players.Player2;
-             ((ContentControl) (sender)).Content = "X";
-             isWinner = GameLogic.IsWinningNumbers(player1Moves);
-             winner = _player1;
-         }
-         else
-         {
-             player2Moves.Add(buttonId);
-             _nextMoveFor = (int) Players.Player1;
-             ((ContentControl) (sender)).Content = "O";
-             isWinner = GameLogic.IsWinningNumbers(player2Moves);
-             winner = _player2;
-         }
-         if (isWinner)
-         {
-             textBox1.Text = winner + " wins the game";
-         }
- }
GameLogic is where we are implementing all the predefined GameLogic.
- public static class GameLogic
-     {
-         //Possible Win
-         //123, 456,789,
-         //369,258,147,
-         //159,753
-         /// <summary>
-         /// Determines whether [is winning numbers] [the specified numbers list].
-         /// </summary>
-         /// <param name="numbersList">The numbers list.</param>
-         /// <returns>
-         ///     <c>true</c> if [is winning numbers] [the specified numbers list]; otherwise, <c>false</c>.
-         /// </returns>
-         public static bool IsWinningNumbers(List<int> numbersList)
-         {
-             bool retVal = false;
-             if (numbersList != null)
-             {
-                 numbersList.Sort();
-                 retVal = IsWinningCombination(numbersList);
-        ÂÂ
-             }
-             return retVal;
-         }
-         /// <summary>
-         /// Gets the winner with3 numbers.
-         /// </summary>
-         /// <param name="numbersList">The numbers list.</param>
-         /// <returns></returns>
-         private static bool GetWinnerWith3Numbers(List<int> numbersList)
-         {
-             bool retVal = false;
-             var total = numbersList[0] + numbersList[1] + numbersList[2];
-             if (total == 15 || total == 24 || total == 6) // we have a winner
-             {
-                 retVal = true;
-             }
-             return retVal;
-         }
-         /// <summary>
-         /// Determines whether [is winning combination] [the specified my list].
-         /// </summary>
-         /// <param name="myList">My list.</param>
-         /// <returns>
-         ///     <c>true</c> if [is winning combination] [the specified my list]; otherwise, <c>false</c>.
-         /// </returns>
-         private static bool IsWinningCombination(List<int> myList)
-         {
-             List<int> v1 = new List<int>();
-             List<int> v2 = new List<int>();
-             List<int> v3 = new List<int>();
-             //horizontal items
-             List<int> h1 = new List<int>();
-             List<int> h2 = new List<int>();
-             List<int> h3 = new List<int>();
-             //Diagonal
-             List<int> d1 = new List<int>();
-             List<int> d2 = new List<int>();
-             bool Retval = false;
-             if (myList != null)
-             {
-                 myList.Sort();
-                 foreach (int item in myList)
-                 {
-                     switch (item)
-                     {
-                         case 1:
-                             v1.Add(1);
-                             h1.Add(1);
-                             d1.Add(1);
-                             break;
-                         case 2:
-                             v1.Add(2);
-                             h2.Add(2);
-                             break;
-                         case 3:
-                             v1.Add(3);
-                             h3.Add(3);
-                             d2.Add(3);
-                             break;
-                         case 4:
-                             v2.Add(4);
-                             h1.Add(4);
-                             break;
-                         case 5:
-                             v2.Add(5);
-                             h2.Add(5);
-                             d1.Add(5);
-                             d2.Add(5);
-                             break;
-                         case 6:
-                             v2.Add(6);
-                             h3.Add(6);
-                             break;
-                         case 7:
-                             v3.Add(7);
-                             h1.Add(7);
-                             d2.Add(7);
-                             break;
-                         case 8:
-                             v3.Add(8);
-                             h2.Add(8);
-                             break;
-                         case 9:
-                             v3.Add(9);
-                             h3.Add(9);
-                             d1.Add(9);
-                             break;
-                     }
-                 }
-                ÂÂ
-                 //add these to a list
-                 var allItems = new List<List<int>>();
-                 //check each items
-                 allItems.Add(v1);
-                 allItems.Add(v2);
-                 allItems.Add(v3);
-                 allItems.Add(h1);
-                 allItems.Add(h2);
-                 allItems.Add(h3);
-                 allItems.Add(d1);
-                 allItems.Add(d2);
-                 foreach (var item in allItems)
-                 {
-                     if (item.Count == 3)
-                     {
-                         if (GetWinnerWith3Numbers(item))
-                         {
-                             Retval = true;
-                             break;
-                         }
-                     }
-                 }
-             }
-             return Retval;
-         }
-     }
As you can see the method IsWinningNumber is the only call you make and that will do all the work for you.
- It calls IsWinningCombination and sends it the list of sorted numbers.
- Winning Combination creates 8 List<int> and keeps 8 possible winning list. Each list will have 3 numbers (well at least one of them will have 3 number in case of a win).
- We take the list of the lists and call GetWinnerWith3Numbers ( this is where the “Sum†of number are checked.
You will see the game will show “Player 1 wins the game†or “Player 2 wins the game†in the textbox once someone wins. Thats it folks.
Here is the source codes Download Source