I am relitively new to C#.
On thursday I started out writing a Tic-tac-toe game. Just a basic gridbuilder, ask the user where they want to go, alternate the users, as player2 where he wabts to go (checking if the move is 'legal'). I've just kept adding to it... This leads to a set of well labelled functions, but not always in the most logically arranged order.

Today i attempted to write AI that was impossible to beat, using the MiniMax alogorithm. This new code can be found in the methods:
MiniMax
ValueCell
GridSpace
RotateGo
CheckCurrentWin
I have placed these at the very bottom of the code for ease.

There is a bug somewhere in this program that makes the AI play out not just it's move, but the entire game (after you have taken your starting go).

MiniMax is called by the SinglePlayerUpdate Method (Ln650).

Note: When asked for a grid location to go in,
a,b,c respond to the 3 vertical columns respectively.
1,2,3 respond to the 3 horizontal rows respectively.
E.g. entering "c3" would place your marker in the bottom right of the grid.

Thankyou in advance for any help!

/*
 * Tic-Tac-Toe
 * J Keegan
 * 10/12/09
 */
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace OXO
{
    class Program
    {
        static int width = 3;
        static int height = 3;
        static char[] OX = new char[width * height];
        static string spacer = " | ";
        static char go;
        static char computerPlayer = 'O';
        static int games;
        static int gameNumber;
        static int scoreX;
        static int scoreO;
        static char lastWinner;

        static void Main(string[] args)
        {
            bool playing = true;
            while (playing)
            {
                Initialise();
                //Would you like to play single player or multiplayer?
                int userChoice = MenuLevel0();

                Console.Clear();
                    //Multi-Player
                    if (userChoice == 1)
                    {
                        while (gameNumber <= games)
                        {
                            Initialise();
                            //If we are into the second round or higher of a tournament, set the starting user to the player who loast last time:
                            if (gameNumber > 1)
                            {
                                go = lastWinner;
                            }                            
                            string grid = GridBuilder();
                            Console.Write(grid);

                            bool inPlay = true;
                            while (inPlay)
                            {
                                Update();
                                inPlay = !GameOver(userChoice);
                            }
                            gameNumber++;
                            Wait();
                        }
                        //If it was a tounament, declare the victor!
                        TourniVictor();
                    }

                    //Single-Player
                    else if (userChoice == 2)
                    {
                        while (gameNumber <= games)
                        {
                            Initialise();
                            //If we are into the second round or higher of a tournament, set the starting user to the player who loast last time:
                            if (gameNumber > 1)
                            {
                                go = lastWinner;
                            }
                            string grid = GridBuilder();
                            Console.Write(grid);

                            bool inPlay = true;
                            while (inPlay)
                            {
                                SinglePlayerUpdate();
                                inPlay = !GameOver(userChoice);
                            }
                            gameNumber++;
                            Wait();
                        }
                        //If it was a tounament, declare the victor!
                        TourniVictor();
                    }
                    else if (userChoice == -1)
                    {
                        Console.WriteLine("Thankyou for playing!\nGoodbye!");
                        playing = false;
                    }
                }
        }
        static int MenuLevel0()
        {
            string userChoice;
            //Console.Clear();
            Console.WriteLine("Welcome to Tic-Tac-Toe!");
            Console.WriteLine("1. Play Multi-Player \n2. Play Single-Player\nQ. Quit Playing");
            do
            {                
                Console.Write("Please enter your choice: ");
                userChoice = Console.ReadLine();
            }
            while (!(userChoice == "1" || userChoice == "2" || userChoice.ToLower() == "q"));
            //convert to integer value
            int selection;
            if (int.TryParse(userChoice, out selection))
            {
            }
                //For values that are actually letters, assign an equivelent integer value, for simplicity
                //KEY:
                //QUIT      q       -1
            else
            {
                selection = -1;
            }

            //if the user wants to play:
            if (selection > 0)
            {
                MenuLevel1();
            }

            return selection;
        }
        static void MenuLevel1()
        {
            int userInput;
            Console.Clear();
            Console.WriteLine("How many games would you like to play?");
            Console.WriteLine("1. Just the one game thanks!");
            Console.WriteLine("2. A mini-tournament please!");
            do
            {
                Console.Write("Enter your selection: ");
            }
            while (!(int.TryParse(Console.ReadLine(), out userInput)) && !(userInput<=2 && userInput>=1));

            if (userInput == 2)
            {
                do
                {
                    Console.Clear();
                    Console.Write("Enter How Many Games You'd Like To Play: ");
                }
                while (!int.TryParse(Console.ReadLine(), out userInput));
                //Set up the tourni values
                InitialiseTournament(userInput);
            }
            
        }
        static void TourniVictor()
        {
            //If we just finished a tournament, declare the victor:
            if (games > 1)
            {
                Console.Clear();
                char winner;
                //if X won
                if (scoreX > scoreO)
                {
                    winner = 'X';
                }
                //If O won
                else if (scoreO > scoreX)
                {
                    winner = 'O';
                }
                //If it was a draw
                else
                {
                    winner = 'd';
                }

                //If it was a draw:
                if (winner == 'd')
                {
                    Console.WriteLine("Alas, a draw!");
                }
                //Else declave the victor:
                else
                {
                    Console.WriteLine("Congratulations {0}! You won the Tournament :)", winner);
                }
                //reset the values
                InitialiseTournament(1);
                Wait();
            }
        }
        static void InitialiseTournament(int numberOfGames)
        {
            games = numberOfGames;
            gameNumber = 1;
            scoreO = 0;
            scoreX = 0;
        }
        static void Wait()
        {
            Console.WriteLine("\nPress any key to continue . . .");
            Console.ReadKey();
            Console.Clear();
        }
        static int AI()
        {
            AlternateUsers(); char enemy = go; AlternateUsers();
            int[] winPossibilityPriority = new int[8];
            int k = 0;
            
            //Horizontal Wins:
            for (int i = 0; i < OX.Length; i+=width, k++)
            {
                //construct a string which contains the char array
                string contents = "";
                for (int j = 0; j < width; j++)
                {
                    contents += OX[i + j];
                }
                //search for an empty cell. If it has one continue checking. Else move on.
                if (contents.Contains(" "))
                {
                    if (contents.Contains(enemy))
                    {
                        int numberOfEnemyPositions = 0;
                        int numberOfFriendlyPositions = 0;
                        //count how many enemies && friendlies are in the 3 cells.
                        for (int j = 0; j < width; j++)
                        {
                            if (contents[j] == enemy)
                            {
                                numberOfEnemyPositions++;
                            }
                            if (contents[j] == go)
                            {
                                numberOfFriendlyPositions++;
                            }
                        }
                        //Prioritise this 3 cell group (win possibility)
                        winPossibilityPriority[k] = numberOfEnemyPositions - numberOfFriendlyPositions;
                    }
                }
                else
                {
                    //we cannot go here.
                    winPossibilityPriority[k] = 0;
                }
            }

            //Vertical Wins:
            for (int i = 0; i < width; i++, k++)
            {
                //construct a string which contains the char array
                string contents = "";
                for (int j = 0; j < width; j++)
                {
                    contents += OX[i + (j*width)];
                }
                //search for an empty cell. If it has one continue checking. Else move on.
                if (contents.Contains(" "))
                {
                    if (contents.Contains(enemy))
                    {
                        int numberOfEnemyPositions = 0;
                        int numberOfFriendlyPositions = 0;
                        //count how many enemies && friendlies are in the 3 cells.
                        for (int j = 0; j < width; j++)
                        {
                            if (contents[j] == enemy)
                            {
                                numberOfEnemyPositions++;
                            }
                            if (contents[j] == go)
                            {
                                numberOfFriendlyPositions++;
                            }
                        }
                        //Prioritise this 3 cell group (win possibility)
                        winPossibilityPriority[k] = numberOfEnemyPositions - numberOfFriendlyPositions;
                    }
                }
                else
                {
                    //we cannot go here.
                    winPossibilityPriority[k] = 0;
                }
            }

            //Diagonal Wins:
            //Top Left to Bottom Right:
            //construct a string which contains the char array
            for (int i = 0; i < 1; i++, k++)//C# won't let me use contents string unless it's inside a child here... C# is great...
            {
                string contents = "";
                for (int j = 0; j < width; j++)
                {
                    contents += OX[j * 4];
                }
                //search for an empty cell. If it has one continue checking. Else move on.
                if (contents.Contains(" "))
                {
                    if (contents.Contains(enemy))
                    {
                        int numberOfEnemyPositions = 0;
                        int numberOfFriendlyPositions = 0;
                        //count how many enemies && friendlies are in the 3 cells.
                        for (int j = 0; j < width; j++)
                        {
                            if (contents[j] == enemy)
                            {
                                numberOfEnemyPositions++;
                            }
                            if (contents[j] == go)
                            {
                                numberOfFriendlyPositions++;
                            }
                        }
                        //Prioritise this 3 cell group (win possibility)
                        winPossibilityPriority[k] = numberOfEnemyPositions - numberOfFriendlyPositions;
                    }
                }
                else
                {
                    //we cannot go here.
                    winPossibilityPriority[k] = 0;
                }
            }

            //Top Right to Bottom Left:
            //construct a string which contains the char array
            for (int i = 0; i < 1; i++, k++)//C# won't let me use contents string unless it's inside a child here... C# is great...
            {
                string contents = "";
                for (int j = 2; j <= 6 ; j+=2)
                {
                    contents += OX[j];
                }
                //search for an empty cell. If it has one continue checking. Else move on.
                if (contents.Contains(" "))
                {
                    if (contents.Contains(enemy))
                    {
                        int numberOfEnemyPositions = 0;
                        int numberOfFriendlyPositions = 0;
                        //count how many enemies && friendlies are in the 3 cells.
                        for (int j = 0; j < width; j++)
                        {
                            if (contents[j] == enemy)
                            {
                                numberOfEnemyPositions++;
                            }
                            if (contents[j] == go)
                            {
                                numberOfFriendlyPositions++;
                            }
                        }
                        //Prioritise this 3 cell group (win possibility)
                        winPossibilityPriority[k] = numberOfEnemyPositions - numberOfFriendlyPositions;
                    }
                }
                else
                {
                    //we cannot go here.
                    winPossibilityPriority[k] = 0;
                }
            }

            //NOW ALL POSSIBLE WAYS TO WIN HAVE BEEN EVALUATED ONCE.
            //Everything has been giver a value of 2, 1, 0, -1 or 2

            //WIN OR LOSE EVENTS:
            //-2 means there are 2 allies in this sector. Any sector with this value means that one move will win the game!
            //2 means there are 2 enemies in this sector and so is High Priority! One move will stop the enemy winning via this sector.

            //NORMAL GAMEPLAY:
            //-1 means there is one ally in this sector. Going here will make this -2 for the enemy, during standard gameplay this is the highest value sector.
            //1 means there is an enemy in this sector. Low priority event.
            //0 means there is no value to playing in this sector. Either there is one enemy & one ally, or there is neither an ally nor an enemy.

            //Rearrange these into more readable priorities:
            for (int i = 0; i < winPossibilityPriority.Length; i++)
            {
                if (winPossibilityPriority[i] == -1)
                {
                    winPossibilityPriority[i] = 2;
                }
                else if (winPossibilityPriority[i] == 2)
                {
                    winPossibilityPriority[i] = 3;
                }
                else if (winPossibilityPriority[i] == -2)
                {
                    winPossibilityPriority[i] = 4;
                }
            }
            //NEW VALUES:

            //WIN OR LOSE EVENTS:
            //4 means there are 2 allies in this sector. Any sector with this value means that one move will win the game!
            //3 means there are 2 enemies in this sector and so is High Priority! One move will stop the enemy winning via this sector.

            //NORMAL GAMEPLAY:
            //2 means there is one ally in this sector. Going here will make this -2 for the enemy, during standard gameplay this is the highest value sector.
            //1 means there is an enemy in this sector. Low priority event.
            //0 means there is no value to playing in this sector. Either there is one enemy & one ally, or there is neither an ally nor an enemy.

            //FIND THE HIGHEST PRIORITY SECTOR:
            int highPriorityValue = 0;
            int highPrioritySector = 0;
            for (int i = 0; i < winPossibilityPriority.Length; i++)
            {
                if (highPriorityValue < winPossibilityPriority[i])
                {
                    highPriorityValue = winPossibilityPriority[i];
                    highPrioritySector = i;
                }
            }

            //The highest priority sector is now listed as a location in the array winPosibilityPriority

            //FIND THE ACTUAL GRID LOCATIONS:
            //(relative to the OX array)
            int[] gridLocations = new int[3];

            //If it's horizontal
            if (highPrioritySector < 3)
            {
                gridLocations[0] = highPrioritySector * 3;
                for (int i = 1; i < 3; i++)
                {
                    gridLocations[i] = gridLocations[0] + i;
                }
            }

            //If it's vertical
            else if (highPrioritySector < 6)
            {
                gridLocations[0] = highPrioritySector - 3;
                for (int i = 1; i < 3; i++)
                {
                    gridLocations[i] = gridLocations[0] + (i * width);
                }
            }

            //If it's diagonal
            else if (highPrioritySector == 6)
            {
                gridLocations[0] = 0;
                gridLocations[1] = 4;
                gridLocations[2] = 8;
            }
            else if (highPrioritySector == 7)
            {
                gridLocations[0] = 2;
                gridLocations[1] = 4;
                gridLocations[2] = 6;
            }

            //NOW GO THROUGH THE INDIVIDUAL VALUES OF THE HIGH PRIORITY SECTOR AND TAKE YOUR GO
            for (int i = 0; i < 3; i++)
            {
                if (OX[gridLocations[i]] == ' ')
                {
                    return gridLocations[i];
                }
            }
            //IF YOU GET THIS FAR, IT'S FUBAR
            //Give an *Important* error warning
            Console.Beep();
            //Return a value to prevent application hanging
            return 4;
        }
        static void KeepScore()
        {
            if (go == 'X')
            {
                scoreX++;
            }
            else
            {
                scoreO++;
            }
        }
        static bool GameOver(int gameType)
        {
            if (gameType == 1)
            {
                if (CheckWinCriteria() == true)
                {
                    //Write Out the new GridBuilder, as CheckWinCriteria will have placed hitmarkers on the winning cells
                    Console.Clear();
                    Console.Write(GridBuilder());
                    Console.WriteLine("Well done {0}, you win!", go);
                    KeepScore();
                    TournamentUpdate(false);
                    //Determine the player who starts next time (if its a tourni)
                    lastWinner = go;
                    return true;
                }
            }
            else if (gameType == 2)
            {
                if (CheckWinCriteria() == true)
                {
                    if (go == computerPlayer)
                    {
                        //Write Out the new GridBuilder, as CheckWinCriteria will have placed hitmarkers on the winning cells
                        Console.Clear();
                        Console.Write(GridBuilder());
                        Console.WriteLine("The computer won. Bad Luck!");
                    }
                    else
                    {
                        //Write Out the new GridBuilder, as CheckWinCriteria will have placed hitmarkers on the winning cells
                        Console.Clear();
                        Console.Write(GridBuilder());
                        Console.WriteLine("Well done, you win!");
                    }
                    KeepScore();
                    TournamentUpdate(true);
                    //Determine the player who starts next time (if its a tourni)
                    lastWinner = go;
                    return true;
                }
            }
            if (CheckDrawCriteria() == true)
            {
                Console.WriteLine("Stand down, it's a draw...");
                return true;
            }
            return false;

        }
        static bool CheckDrawCriteria()
        {
            for (int i = 0; i < OX.Length; i++)
            {
                if (OX[i] == ' ')
                {
                    return false;
                }
            }
            return true;
        }
        static bool CheckWinCriteria()
        {
            char winMarker = '*';
            //Check left column, and then along the rows horizontally
            for (int j = 0; j < OX.Length; j += 3)
            {
                //If all cell's on the horizontal row hits. Game over.
                if (OX[j] == go && OX[j + 1] == go && OX[j + 2] == go)
                {
                    OX[j] = winMarker;
                    OX[j + 1] = winMarker;
                    OX[j + 2] = winMarker;
                    return true;
                }
            }
            //Check 1st row, and then down the columns vertically
            for (int j = 0; j < width; j++)
            {
                if (OX[j] == go && OX[j + width] == go && OX[j + 2 * width] == go)
                {
                    OX[j] = winMarker;
                    OX[j + width] = winMarker;
                    OX[j + 2 * width] = winMarker;
                    return true;
                }
            }
            //Check diaganol lines
            //check for the diagonal starting in the top left
            if (OX[0] == go && OX[width + 1] == go && OX[2 * (width + 1)] == go)
            {
                OX[0] = winMarker;
                OX[width + 1] = winMarker;
                OX[2 * (width + 1)] = winMarker;
                return true;
            }
            //check for the diagonal starting in the top right
            if (OX[width - 1] == go && OX[2 * (width - 1)] == go && OX[3 * (width - 1)] == go)
            {
                OX[width - 1] = winMarker;
                OX[2 * (width - 1)] = winMarker;
                OX[3 * (width - 1)] = winMarker;
                return true;
            }

            return false;
        }
        static void TournamentUpdate(bool singlePlayer)
        {
            //If we are in a 'tournament'
            if (games > 1)
            {
                Console.WriteLine("Game {0} of {1}", gameNumber, games);
                Console.WriteLine("Scores:");
                string X = "";
                string O = "";
                if (singlePlayer)
                {
                    X = (computerPlayer == 'X' ? "Computer" : "You");
                    O = (computerPlayer == 'O' ? "Computer" : "You");
                }
                else
                {
                    X = "X";
                    O = "O";
                }
                Console.WriteLine("{0}: {1}", X, scoreX);
                Console.WriteLine("{0}: {1}", O, scoreO);
            }
        }
        static void Update()
        {
            TournamentUpdate(false);
            AlternateUsers();
            Console.WriteLine("{0}'s go!", go);
            int i;
            do
            {
                i = MakeArrayPosition(GetCoOrds());
            }
            while (OX[i] != ' ');
            OX[i] = go;            
            Console.Clear();
            Console.Write(GridBuilder());
        }
        static void SinglePlayerUpdate()
        {
            TournamentUpdate(true);
            AlternateUsers();            
            if (go != computerPlayer)
            {
                Console.WriteLine("Your go! You are {0}", go);
                int i;
                do
                {
                    i = MakeArrayPosition(GetCoOrds());
                }
                while (OX[i] != ' ');
                OX[i] = go;                
            }
            else
            {
                Console.WriteLine("The computer is taking it's turn...");
                //OX[AI()] = go;
                OX[MiniMax()] = go;
            }
            Console.Clear();
            Console.Write(GridBuilder());
        }
        static void AlternateUsers()
        {
            if (go == 'O')
            {
                go = 'X';
            }
            else
            {
                go = 'O';
            }
        }
        static int MakeArrayPosition(int[] coOrds)
        {
            int i = 0;
            //check first row
            for (int k = 0; k < coOrds[1]; k++)
            {
                if (k + 1 == coOrds[1])
                {
                    for (int j = 1; j < coOrds[0]; j++, i++)
                    {
                    }
                }
                else
                {
                    for (int j = 0; j < width; j++, i++)
                    {
                    }
                }
            }
            return i;

        }
        static int[] GetCoOrds()
        {
            bool inPlay = true;
            while (inPlay)
            {
                int[] coOrds = CheckCoOrdinates(GetCoOrdinates());
                if (coOrds[0] != 0)
                {
                    return coOrds;
                }
            }
            int[] csDoesntWork = new int[2];
            return csDoesntWork;
        }
        static int[] CheckCoOrdinates(string rawInput)
        {
            int[] coOrds = new int[2];
            //horizontal co-ordinate
            if (rawInput.ToLower().Contains("a"))
            {
                coOrds[0] = 1;
            }
            else if (rawInput.ToLower().Contains("b"))
            {
                coOrds[0] = 2;
            }
            else if (rawInput.ToLower().Contains("c"))
            {
                coOrds[0] = 3;
            }
            //when coOrds[0] == 0, this is an error!
            else
            {
                coOrds[0] = 0;
            }
            //Vertical co-ordinate
            if (rawInput.ToLower().Contains("1"))
            {
                coOrds[1] = 1;
            }
            else if (rawInput.ToLower().Contains("2"))
            {
                coOrds[1] = 2;
            }
            else if (rawInput.ToLower().Contains("3"))
            {
                coOrds[1] = 3;
            }
            //when coOrds[0] == 0, this is an error!
            else
            {
                coOrds[0] = 0;
            }
            return coOrds;
        }
        static string GetCoOrdinates()
        {
            string coOrds;
            Console.Write("Enter the co-ordinates you want to make an entry in: ");
            coOrds = Console.ReadLine();
            return coOrds;
        }
        static string GridBuilder()
        {
            string grid = "";
            for (int i = 0; i < OX.Length; i++)
            {
                grid += OX[i];
                if ((i + 1) % width == 0)
                {
                    grid += "\n";
                    if ((i + 1) != OX.Length)
                    {
                        for (int j = 0; j < (spacer.Length * width); j++)
                        {
                            grid += "-";
                        }
                    }
                    grid += "\n";
                }
                else
                {
                    grid += spacer;
                }
            }
            return grid;
        }
        static void Initialise()
        {
            for (int i = 0; i < OX.Length; i++)
            {
                OX[i] = ' ';
            }
            go = 'O';
        }
        static int MiniMax()
        {
            int bestGo = 0;
            int[] terminalValues = new int[OX.Length];
            //determine the terminal value of going in each cell:
            for (int i = 0; i < terminalValues.Length; i++)
            {
                terminalValues[i] = ValueCell(i, OX, go);
            }
            //FIND & RETURN THE BEST GO:
            for (int i = 0; i < terminalValues.Length; i++)
            {
                bestGo = Math.Max(bestGo, terminalValues[i]);
            }
            return bestGo;
        }
        static int ValueCell(int cell, char[] currentGrid, char whosGo)
        {
            //pass OX as the current grid if it's the first time, else make ammendments to the 'current grid' where OX is left as the actual inPlay values
            int cellValue = -2;
            //If this would be an illegal move:
            if (currentGrid[cell] != ' ')
            {
                return -2;
            }

            //Else if it's a legal move:

                currentGrid[cell] = whosGo;

            //If the currentGrid is full (we are at the last fork of the process)
                if (!GridSpace(currentGrid))
                {
                    //If in the boards current state teh computer wins, return a value of 1
                    if (CheckCurrentWin(currentGrid, computerPlayer))
                    {
                        return 1;
                    }
                    //If in the boards current state, the human wins, return a value of -1
                    else if (CheckCurrentWin(currentGrid, RotateGo(computerPlayer)))
                    {
                        return -1;
                    }
                    //Else we drew, return 0
                    else
                    {
                        return 0;
                    }
                }

                    //declare an array of cell values for each possible move & make them 'impossible'
                    int[] goValue = new int[9];
                    for (int i = 0; i < goValue.Length; i++)
                    {
                        goValue[i] = -2;
                    }
                    //now set those that are possible to their actual values
                    for (int i = 0; i < currentGrid.Length; i++)
                    {
                        if (currentGrid[i] == ' ')
                        {
                            goValue[i] = ValueCell(i, currentGrid, RotateGo(whosGo));
                        }
                    }
                    //Now find the highest possible outcome by making this move:
                    for (int i = 0; i < goValue.Length; i++)
                    {
                        cellValue = Math.Max(cellValue, goValue[i]);
                    }
                    //return trhe cell's value to the parent fork.
                    return cellValue;
        }
        static bool GridSpace(char[] currentGrid)
        {
            foreach (char cell in currentGrid)
            {
                if (cell == ' ')
                {
                    return true;
                }
            }
            return false;
        }
        static char RotateGo(char currentGo)
        {
            if (currentGo == 'X')
            {
                currentGo = 'O';
            }
            else
            {
                currentGo = 'X';
            }
            return currentGo;
        }
        static bool CheckCurrentWin(char[] currentGrid, char whosGo)
        {
            //Check left column, and then along the rows horizontally
            for (int j = 0; j < currentGrid.Length; j += 3)
            {
                //If all cell's on the horizontal row hits. Game over.
                if (currentGrid[j] == whosGo && currentGrid[j + 1] == whosGo && currentGrid[j + 2] == whosGo)
                {
                    return true;
                }
            }
            //Check 1st row, and then down the columns vertically
            for (int j = 0; j < width; j++)
            {
                if (currentGrid[j] == whosGo && currentGrid[j + width] == whosGo && currentGrid[j + 2 * width] == whosGo)
                {
                    return true;
                }
            }
            //Check diaganol lines
            //check for the diagonal starting in the top left
            if (currentGrid[0] == whosGo && currentGrid[width + 1] == whosGo && currentGrid[2 * (width + 1)] == whosGo)
            {
                return true;
            }
            //check for the diagonal starting in the top right
            if (currentGrid[width - 1] == whosGo && currentGrid[2 * (width - 1)] == whosGo && currentGrid[3 * (width - 1)] == whosGo)
            {
                return true;
            }

            return false;
        }
    }
}

Recommended Answers

All 9 Replies

Your problem is at line 811 currentGrid[cell] = whosGo; Arrays are a reference type, so when you change currentGrid[cell] you are actually changing OX[cell] so the method cycles through filling each array entry.

Try using array.Clone() to pass the OX array in, or create a temporary array in the method to copy OX into.

commented: Great effort to wade through all that code! +5

Hi,
First & foremost, thankyou very much for the solution. It is greatly appreciated.

I just wanted to check i understood your explanation as to why this occured (so i don't do the same thing again in future).

The array that is 'made' for the second function to work on is merely a link/reference to the parent array? And it has write access to this?

Or is the linking usually like that, with ammendments being made, but not to the original as it doesn't have write access, yet in mine due to OX being static it had write access which caused the problem.

Or am i completely understanding what the problem was?
Once again thaks for your help with this,
Josh.

C# data types are eitehr reference or value. When you pass a value type as a parameter a copy of it is created in memory so anything you do to it is not reflected back to the original object.
Reference types essentially pass a pointer to their location in memory. SO anything you do to them in the method is reflected in the original object.

There's a lot of simple examples to highlight this behaviour over at msdn

That was of great help, I didn't understand that when an array gets passed it does not get copied by default like other data types.
Thanks :)

thanks a lot for your source code
I copied your code in my project but it found some errors in function [[[ [U][B]static int <strong class="highlight">AI</strong>()[/B][/U] ]]] and it didn't execute .

please help me whit this problem
why it does't work !!!

commented: Don't steal! +0

This code is outdated.
I'll give you the last version. Bear in mind that i stopped writing this before it was finished because I was rather busy, so expect there to be some errors. You shoild find that the AI here will work (although i cannot remember to what extent). Enjoy!

/*
 * Tic-Tac-Toe
 * J Keegan
 * 10/12/09
 */
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace OXO
{
    class Program
    {
        static int width = 3;
        static int height = 3;
        static char[] OX = new char[width * height];
        static string spacer = " | ";
        static char go;
        static char computerPlayer = 'O';
        static int games;
        static int gameNumber;
        static int scoreX;
        static int scoreO;
        static char lastWinner;
        static int AIdifficulty = 1;

        static void Main(string[] args)
        {
            bool playing = true;
            while (playing)
            {
                Initialise();
                //Would you like to play single player or multiplayer?
                int userChoice = MenuLevel0();

                Clear();
                    //Multi-Player
                    if (userChoice == 1)
                    {
                        while (gameNumber <= games)
                        {
                            Initialise();
                            //If we are into the second round or higher of a tournament, set the starting user to the player who loast last time:
                            if (gameNumber > 1)
                            {
                                go = lastWinner;
                            }                            
                            string grid = GridBuilder();
                            Console.Write(grid);

                            bool inPlay = true;
                            while (inPlay)
                            {
                                Update();
                                inPlay = !GameOver(userChoice);
                            }
                            gameNumber++;
                            Wait();
                        }
                        //If it was a tounament, declare the victor!
                        TourniVictor();
                        InitialiseTournament(1);
                    }

                    //Single-Player
                    else if (userChoice == 2)
                    {
                        while (gameNumber <= games)
                        {
                            Initialise();
                            //If we are into the second round or higher of a tournament, set the starting user to the player who loast last time:
                            if (gameNumber > 1)
                            {
                                go = lastWinner;
                            }
                            string grid = GridBuilder();
                            Console.Write(grid);

                            bool inPlay = true;
                            while (inPlay)
                            {
                                SinglePlayerUpdate();
                                inPlay = !GameOver(userChoice);
                            }
                            gameNumber++;
                            Wait();
                        }
                        //If it was a tounament, declare the victor!
                        TourniVictor();
                        InitialiseTournament(1);
                    }
                    //Change AI difficulty
                    else if (userChoice == -2)
                    {
                        Console.WriteLine("Change the AI difficulty to: \n1. Standard\n2. Human-Like");
                        int userSelection;
                        do
                        {
                            Console.Write("Please Enter Your Selection: ");
                        }
                        while (!int.TryParse(Console.ReadLine(), out userSelection) && !(userSelection == 1 || userSelection == 2));
                        AIdifficulty = userSelection;
                        Clear();
                    }
                    else if (userChoice == -1)
                    {
                        Console.WriteLine("Thankyou for playing!\nGoodbye!");
                        playing = false;
                    }                    
                }
        }
        static int MenuLevel0()
        {
            string userChoice;
            Console.WriteLine("Welcome to Tic-Tac-Toe!");
            Console.WriteLine("1. Play Multi-Player \n2. Play Single-Player\nD. Change AI difficulty\nQ. Quit Playing");
            do
            {                
                Console.Write("Please enter your choice: ");
                userChoice = Console.ReadLine();
            }
            while (!(userChoice == "1" || userChoice == "2" || userChoice.ToLower() == "q" || userChoice.ToLower() == "d"));
            //convert to integer value
            int selection;
            if (int.TryParse(userChoice, out selection))
            {
            }
                //For values that are actually letters, assign an equivelent integer value, for simplicity
                //KEY:
                //QUIT      q       -1
            else if (userChoice.ToLower() == "d")
            {
                selection = -2;
            }
            else if (userChoice.ToLower() == "q")
            {
                selection = -1;
            }


            //if the user wants to play:
            if (selection > 0)
            {
                MenuLevel1();
            }

            return selection;
        }
        static void MenuLevel1()
        {
            int userInput;
            Clear();
            Console.WriteLine("How many games would you like to play?");
            Console.WriteLine("1. Just the one game thanks!");
            Console.WriteLine("2. A mini-tournament please!");
            do
            {
                Console.Write("Enter your selection: ");
            }
            while (!(int.TryParse(Console.ReadLine(), out userInput)) && !(userInput<=2 && userInput>=1));

            if (userInput == 2)
            {
                do
                {
                    Clear();
                    Console.Write("Enter How Many Games You'd Like To Play: ");
                }
                while (!int.TryParse(Console.ReadLine(), out userInput));
                //Set up the tourni values
                InitialiseTournament(userInput);
            }
            
        }
        static void TourniVictor()
        {
            //If we just finished a tournament, declare the victor:
            if (games > 1)
            {
                Clear();
                char winner;
                //if X won
                if (scoreX > scoreO)
                {
                    winner = 'X';
                }
                //If O won
                else if (scoreO > scoreX)
                {
                    winner = 'O';
                }
                //If it was a draw
                else
                {
                    winner = 'd';
                }

                //If it was a draw:
                if (winner == 'd')
                {
                    Console.WriteLine("Alas, a draw!");
                }
                //Else declave the victor:
                else
                {
                    Console.WriteLine("Congratulations {0}! You won the Tournament :)", winner);
                }
                //reset the values
                InitialiseTournament(1);
                Wait();
            }
        }
        static void InitialiseTournament(int numberOfGames)
        {
            games = numberOfGames;
            gameNumber = 1;
            scoreO = 0;
            scoreX = 0;
        }
        static void Wait()
        {
            Console.WriteLine("\nPress any key to continue . . .");
            Console.ReadKey();
            Clear();
        }
        static void Clear()
        {
            //If we're in debugging mode, don't ever clear the console, to leave a complete log :)
#if !DEBUG
            Console.Clear();
#endif
        }
        static int AI()
        {
            AlternateUsers(); char enemy = go; AlternateUsers();
            int[] winPossibilityPriority = new int[8];
            int k = 0;
            
            //Horizontal Wins:
            for (int i = 0; i < OX.Length; i+=width, k++)
            {
                //construct a string which contains the char array
                string contents = "";
                for (int j = 0; j < width; j++)
                {
                    contents += OX[i + j];
                }
                //search for an empty cell. If it has one continue checking. Else move on.
                if (contents.Contains(" "))
                {
                        int numberOfEnemyPositions = 0;
                        int numberOfFriendlyPositions = 0;
                        //count how many enemies && friendlies are in the 3 cells.
                        for (int j = 0; j < width; j++)
                        {
                            if (contents[j] == enemy)
                            {
                                numberOfEnemyPositions++;
                            }
                            if (contents[j] == go)
                            {
                                numberOfFriendlyPositions++;
                            }
                        //Prioritise this 3 cell group (win possibility)
                        winPossibilityPriority[k] = numberOfEnemyPositions - numberOfFriendlyPositions;
                    }
                }
                else
                {
                    //we cannot go here.
                    winPossibilityPriority[k] = 0;
                }
            }

            //Vertical Wins:
            for (int i = 0; i < width; i++, k++)
            {
                //construct a string which contains the char array
                string contents = "";
                for (int j = 0; j < width; j++)
                {
                    contents += OX[i + (j*width)];
                }
                //search for an empty cell. If it has one continue checking. Else move on.
                if (contents.Contains(" "))
                {
                        int numberOfEnemyPositions = 0;
                        int numberOfFriendlyPositions = 0;
                        //count how many enemies && friendlies are in the 3 cells.
                        for (int j = 0; j < width; j++)
                        {
                            if (contents[j] == enemy)
                            {
                                numberOfEnemyPositions++;
                            }
                            if (contents[j] == go)
                            {
                                numberOfFriendlyPositions++;
                            }
                        //Prioritise this 3 cell group (win possibility)
                        winPossibilityPriority[k] = numberOfEnemyPositions - numberOfFriendlyPositions;
                    }
                }
                else
                {
                    //we cannot go here.
                    winPossibilityPriority[k] = 0;
                }
            }

            //Diagonal Wins:
            //Top Left to Bottom Right:
            //construct a string which contains the char array
            for (int i = 0; i < 1; i++, k++)//C# won't let me use contents string unless it's inside a child here... C# is great...
            {
                string contents = "";
                for (int j = 0; j < width; j++)
                {
                    contents += OX[j * 4];
                }
                //search for an empty cell. If it has one continue checking. Else move on.
                if (contents.Contains(" "))
                {
                        int numberOfEnemyPositions = 0;
                        int numberOfFriendlyPositions = 0;
                        //count how many enemies && friendlies are in the 3 cells.
                        for (int j = 0; j < width; j++)
                        {
                            if (contents[j] == enemy)
                            {
                                numberOfEnemyPositions++;
                            }
                            if (contents[j] == go)
                            {
                                numberOfFriendlyPositions++;
                            }
                        //Prioritise this 3 cell group (win possibility)
                        winPossibilityPriority[k] = numberOfEnemyPositions - numberOfFriendlyPositions;
                    }
                }
                else
                {
                    //we cannot go here.
                    winPossibilityPriority[k] = 0;
                }
            }

            //Top Right to Bottom Left:
            //construct a string which contains the char array
            for (int i = 0; i < 1; i++, k++)//C# won't let me use contents string unless it's inside a child here... C# is great...
            {
                string contents = "";
                for (int j = 2; j <= 6 ; j+=2)
                {
                    contents += OX[j];
                }
                //search for an empty cell. If it has one continue checking. Else move on.
                if (contents.Contains(" "))
                {
                        int numberOfEnemyPositions = 0;
                        int numberOfFriendlyPositions = 0;
                        //count how many enemies && friendlies are in the 3 cells.
                        for (int j = 0; j < width; j++)
                        {
                            if (contents[j] == enemy)
                            {
                                numberOfEnemyPositions++;
                            }
                            if (contents[j] == go)
                            {
                                numberOfFriendlyPositions++;
                            }
                        }
                        //Prioritise this 3 cell group (win possibility)
                        winPossibilityPriority[k] = numberOfEnemyPositions - numberOfFriendlyPositions;
                }
                else
                {
                    //we cannot go here.
                    winPossibilityPriority[k] = 0;
                }
            }

            //NOW ALL POSSIBLE WAYS TO WIN HAVE BEEN EVALUATED ONCE.
            //Everything has been giver a value of 2, 1, 0, -1 or 2

            //WIN OR LOSE EVENTS:
            //-2 means there are 2 allies in this sector. Any sector with this value means that one move will win the game!
            //2 means there are 2 enemies in this sector and so is High Priority! One move will stop the enemy winning via this sector.

            //NORMAL GAMEPLAY:
            //-1 means there is one ally in this sector. Going here will make this -2 for the enemy, during standard gameplay this is the highest value sector.
            //1 means there is an enemy in this sector. Low priority event.
            //0 means there is no value to playing in this sector. Either there is one enemy & one ally, or there is neither an ally nor an enemy.

            //Rearrange these into more readable priorities:
            for (int i = 0; i < winPossibilityPriority.Length; i++)
            {
                if (winPossibilityPriority[i] == -1)
                {
                    winPossibilityPriority[i] = 2;
                }
                else if (winPossibilityPriority[i] == 2)
                {
                    winPossibilityPriority[i] = 3;
                }
                else if (winPossibilityPriority[i] == -2)
                {
                    winPossibilityPriority[i] = 4;
                }
            }
            //NEW VALUES:

            //WIN OR LOSE EVENTS:
            //4 means there are 2 allies in this sector. Any sector with this value means that one move will win the game!
            //3 means there are 2 enemies in this sector and so is High Priority! One move will stop the enemy winning via this sector.

            //NORMAL GAMEPLAY:
            //2 means there is one ally in this sector. Going here will make this -2 for the enemy, during standard gameplay this is the highest value sector.
            //1 means there is an enemy in this sector. Low priority event.
            //0 means there is no value to playing in this sector. Either there is one enemy & one ally, or there is neither an ally nor an enemy.

            //FIND THE HIGHEST PRIORITY SECTOR:
            int highPriorityValue = 0;
            int highPrioritySector = 0;
            for (int i = 0; i < winPossibilityPriority.Length; i++)
            {
                if (highPriorityValue < winPossibilityPriority[i])
                {
                    highPriorityValue = winPossibilityPriority[i];
                    highPrioritySector = i;
                }
            }

            //The highest priority sector is now listed as a location in the array winPosibilityPriority

            //FIND THE ACTUAL GRID LOCATIONS:
            //(relative to the OX array)
            int[] gridLocations = new int[3];

            //If it's horizontal
            if (highPrioritySector < 3)
            {
                gridLocations[0] = highPrioritySector * 3;
                for (int i = 1; i < 3; i++)
                {
                    gridLocations[i] = gridLocations[0] + i;
                }
            }

            //If it's vertical
            else if (highPrioritySector < 6)
            {
                gridLocations[0] = highPrioritySector - 3;
                for (int i = 1; i < 3; i++)
                {
                    gridLocations[i] = gridLocations[0] + (i * width);
                }
            }

            //If it's diagonal
            else if (highPrioritySector == 6)
            {
                gridLocations[0] = 0;
                gridLocations[1] = 4;
                gridLocations[2] = 8;
            }
            else if (highPrioritySector == 7)
            {
                gridLocations[0] = 2;
                gridLocations[1] = 4;
                gridLocations[2] = 6;
            }

            //NOW GO THROUGH THE INDIVIDUAL VALUES OF THE HIGH PRIORITY SECTOR AND TAKE YOUR GO
            for (int i = 0; i < 3; i++)
            {
                if (OX[gridLocations[i]] == ' ')
                {
                    return gridLocations[i];
                }
            }
            //IF YOU GET THIS FAR, IT'S FUBAR
            //Give an *Important* error warning
            Console.Beep();
            //Return a value to prevent application hanging
            return 4;
        }
        static void KeepScore()
        {
            if (go == 'X')
            {
                scoreX++;
            }
            else
            {
                scoreO++;
            }
        }
        static bool GameOver(int gameType)
        {
            if (gameType == 1)
            {
                if (CheckWinCriteria() == true)
                {
                    //Write Out the new GridBuilder, as CheckWinCriteria will have placed hitmarkers on the winning cells
                    Clear();
                    Console.Write(GridBuilder());
                    Console.WriteLine("Well done {0}, you win!", go);
                    KeepScore();
                    TournamentUpdate(false);
                    //Determine the player who starts next time (if its a tourni)
                    lastWinner = go;
                    return true;
                }
            }
            else if (gameType == 2)
            {
                if (CheckWinCriteria() == true)
                {
                    if (go == computerPlayer)
                    {
                        //Write Out the new GridBuilder, as CheckWinCriteria will have placed hitmarkers on the winning cells
                        Clear();
                        Console.Write(GridBuilder());
                        Console.WriteLine("The computer won. Bad Luck!");
                    }
                    else
                    {
                        //Write Out the new GridBuilder, as CheckWinCriteria will have placed hitmarkers on the winning cells
                        Clear();
                        Console.Write(GridBuilder());
                        Console.WriteLine("Well done, you win!");
                    }
                    KeepScore();
                    TournamentUpdate(true);
                    //Determine the player who starts next time (if its a tourni)
                    lastWinner = go;
                    return true;
                }
            }
            if (CheckDrawCriteria() == true)
            {
                Console.WriteLine("Stand down, it's a draw...");
                return true;
            }
            return false;

        }
        static bool CheckDrawCriteria()
        {
            for (int i = 0; i < OX.Length; i++)
            {
                if (OX[i] == ' ')
                {
                    return false;
                }
            }
            return true;
        }
        static bool CheckWinCriteria()
        {
            char winMarker = '*';
            //Check left column, and then along the rows horizontally
            for (int j = 0; j < OX.Length; j += 3)
            {
                //If all cell's on the horizontal row hits. Game over.
                if (OX[j] == go && OX[j + 1] == go && OX[j + 2] == go)
                {
                    OX[j] = winMarker;
                    OX[j + 1] = winMarker;
                    OX[j + 2] = winMarker;
                    return true;
                }
            }
            //Check 1st row, and then down the columns vertically
            for (int j = 0; j < width; j++)
            {
                if (OX[j] == go && OX[j + width] == go && OX[j + 2 * width] == go)
                {
                    OX[j] = winMarker;
                    OX[j + width] = winMarker;
                    OX[j + 2 * width] = winMarker;
                    return true;
                }
            }
            //Check diaganol lines
            //check for the diagonal starting in the top left
            if (OX[0] == go && OX[width + 1] == go && OX[2 * (width + 1)] == go)
            {
                OX[0] = winMarker;
                OX[width + 1] = winMarker;
                OX[2 * (width + 1)] = winMarker;
                return true;
            }
            //check for the diagonal starting in the top right
            if (OX[width - 1] == go && OX[2 * (width - 1)] == go && OX[3 * (width - 1)] == go)
            {
                OX[width - 1] = winMarker;
                OX[2 * (width - 1)] = winMarker;
                OX[3 * (width - 1)] = winMarker;
                return true;
            }

            return false;
        }
        static void TournamentUpdate(bool singlePlayer)
        {
            //If we are in a 'tournament'
            if (games > 1)
            {
                Console.WriteLine("Game {0} of {1}", gameNumber, games);
                Console.WriteLine("Scores:");
                string X = "";
                string O = "";
                if (singlePlayer)
                {
                    X = (computerPlayer == 'X' ? "Computer" : "You");
                    O = (computerPlayer == 'O' ? "Computer" : "You");
                }
                else
                {
                    X = "X";
                    O = "O";
                }
                Console.WriteLine("{0}: {1}", X, scoreX);
                Console.WriteLine("{0}: {1}", O, scoreO);
            }
        }
        static void Update()
        {
            TournamentUpdate(false);
            AlternateUsers();
            Console.WriteLine("{0}'s go!", go);
            int i;
            do
            {
                i = MakeArrayPosition(GetCoOrds());
            }
            while (OX[i] != ' ');
            OX[i] = go;            
            Clear();
            Console.Write(GridBuilder());
        }
        static void SinglePlayerUpdate()
        {
            TournamentUpdate(true);
            AlternateUsers();            
            if (go != computerPlayer)
            {
                Console.WriteLine("Your go! You are {0}", go);
                int i;
                do
                {
                    i = MakeArrayPosition(GetCoOrds());
                }
                while (OX[i] != ' ');
                OX[i] = go;                
            }
            else
            {
                Console.WriteLine("The computer is taking it's turn...");
                //Run the correct AI diffuculty alogorithm
                if (AIdifficulty == 1)
                {
                    OX[AI()] = go;
                }
                else
                {
                    OX[MiniMax()] = go;
                }
            }
            Clear();
            Console.Write(GridBuilder());
        }
        static void AlternateUsers()
        {
            if (go == 'O')
            {
                go = 'X';
            }
            else
            {
                go = 'O';
            }
        }
        static int MakeArrayPosition(int[] coOrds)
        {
            int i = 0;
            //check first row
            for (int k = 0; k < coOrds[1]; k++)
            {
                if (k + 1 == coOrds[1])
                {
                    for (int j = 1; j < coOrds[0]; j++, i++)
                    {
                    }
                }
                else
                {
                    for (int j = 0; j < width; j++, i++)
                    {
                    }
                }
            }
            return i;

        }
        static int[] GetCoOrds()
        {
            bool inPlay = true;
            while (inPlay)
            {
                int[] coOrds = CheckCoOrdinates(GetCoOrdinates());
                if (coOrds[0] != 0)
                {
                    return coOrds;
                }
            }
            int[] csDoesntWork = new int[2];
            return csDoesntWork;
        }
        static int[] CheckCoOrdinates(string rawInput)
        {
            int[] coOrds = new int[2];
            //horizontal co-ordinate
            if (rawInput.ToLower().Contains("a"))
            {
                coOrds[0] = 1;
            }
            else if (rawInput.ToLower().Contains("b"))
            {
                coOrds[0] = 2;
            }
            else if (rawInput.ToLower().Contains("c"))
            {
                coOrds[0] = 3;
            }
            //when coOrds[0] == 0, this is an error!
            else
            {
                coOrds[0] = 0;
            }
            //Vertical co-ordinate
            if (rawInput.ToLower().Contains("1"))
            {
                coOrds[1] = 1;
            }
            else if (rawInput.ToLower().Contains("2"))
            {
                coOrds[1] = 2;
            }
            else if (rawInput.ToLower().Contains("3"))
            {
                coOrds[1] = 3;
            }
            //when coOrds[0] == 0, this is an error!
            else
            {
                coOrds[0] = 0;
            }
            return coOrds;
        }
        static string GetCoOrdinates()
        {
            string coOrds;
            Console.Write("Enter the co-ordinates you want to make an entry in: ");
            coOrds = Console.ReadLine();
            return coOrds;
        }
        static string GridBuilder()
        {
            string grid = "";
            for (int i = 0; i < OX.Length; i++)
            {
                grid += OX[i];
                if ((i + 1) % width == 0)
                {
                    grid += "\n";
                    if ((i + 1) != OX.Length)
                    {
                        for (int j = 0; j < (spacer.Length * width); j++)
                        {
                            grid += "-";
                        }
                    }
                    grid += "\n";
                }
                else
                {
                    grid += spacer;
                }
            }
            return grid;
        }
        static void Initialise()
        {
            for (int i = 0; i < OX.Length; i++)
            {
                OX[i] = ' ';
            }
            go = 'O';
        }
        static int MiniMax()
        {            
            int[] terminalValues = new int[OX.Length];
            //determine the terminal value of going in each cell:
            for (int i = 0; i < terminalValues.Length; i++)
            {
                terminalValues[i] = -2;
                //Here the array is cloned, as otherwise the new array is merely a reference to the previous one, producing the entire game being played out by the AI, rather than just making the one move.

                //If the cell has not been taken already:
                if (OX[i] == ' ')
                {
                    //Check if the match outcome is going to be decided within the next move. If so, prioritise accordingly :)
                    terminalValues[i] = OneMoveRequired(i, (char[])OX.Clone(), go);
                }

                //If the match outcome is not decided within the next move, run through the regular cell valuing process:
                if (terminalValues[i] == -2)
                {
                    terminalValues[i] = ValueCell(i, (char[])OX.Clone(), go);
                }
            }
            //FIND & RETURN THE BEST GO:
            int bestGo = -3;
            int bestGoIndex = 0;
            for (int i = 0; i < terminalValues.Length; i++)
            {
                int currentBestGo = bestGo;
                bestGo = Math.Max(bestGo, terminalValues[i]);
                if (bestGo != currentBestGo)
                {
                    bestGoIndex = i;
                }
            }
            return bestGoIndex;
        }
        static int ValueCell(int cell, char[] currentGrid, char whosGo)
        {
            //pass OX as the current grid if it's the first time, else make ammendments to the 'current grid' where OX is left as the actual inPlay values
            int cellValue = -2;
            //If this would be an illegal move:
            if (currentGrid[cell] != ' ')
            {
                return -2;
            }

            //Else if it's a legal move:

                currentGrid[cell] = whosGo;

            //If the currentGrid is full (we are at the last fork of the process)
                if (!GridSpace(currentGrid))
                {
                    //If in the boards current state teh computer wins, return a value of 1
                    if (CheckCurrentWin(currentGrid, computerPlayer))
                    {
                        return 1;
                    }
                    //If in the boards current state, the human wins, return a value of -1
                    else if (CheckCurrentWin(currentGrid, RotateGo(computerPlayer)))
                    {
                        return -1;
                    }
                    //Else we drew, return 0
                    else
                    {
                        return 0;
                    }
                }

                    //declare an array of cell values for each possible move & make them 'impossible'
                    int[] goValue = new int[9];
                    for (int i = 0; i < goValue.Length; i++)
                    {
                        goValue[i] = -2;
                    }
                    //now set those that are possible to their actual values
                    for (int i = 0; i < currentGrid.Length; i++)
                    {
                        if (currentGrid[i] == ' ')
                        {                            
                            goValue[i] = ValueCell(i, currentGrid, RotateGo(whosGo));
                        }
                    }
                    //Now find the highest possible outcome by making this move:
                    for (int i = 0; i < goValue.Length; i++)
                    {
                        cellValue = Math.Max(cellValue, goValue[i]);
                    }
                    //return trhe cell's value to the parent fork.
                    return cellValue;
        }
        static bool GridSpace(char[] currentGrid)
        {
            foreach (char cell in currentGrid)
            {
                if (cell == ' ')
                {
                    return true;
                }
            }
            return false;
        }
        static char RotateGo(char currentGo)
        {
            if (currentGo == 'X')
            {
                currentGo = 'O';
            }
            else
            {
                currentGo = 'X';
            }
            return currentGo;
        }
        static bool CheckCurrentWin(char[] currentGrid, char whosGo)
        {
            //Check left column, and then along the rows horizontally
            for (int j = 0; j < currentGrid.Length; j += 3)
            {
                //If all cell's on the horizontal row hits. Game over.
                if (currentGrid[j] == whosGo && currentGrid[j + 1] == whosGo && currentGrid[j + 2] == whosGo)
                {
                    return true;
                }
            }
            //Check 1st row, and then down the columns vertically
            for (int j = 0; j < width; j++)
            {
                if (currentGrid[j] == whosGo && currentGrid[j + width] == whosGo && currentGrid[j + 2 * width] == whosGo)
                {
                    return true;
                }
            }
            //Check diaganol lines
            //check for the diagonal starting in the top left
            if (currentGrid[0] == whosGo && currentGrid[width + 1] == whosGo && currentGrid[2 * (width + 1)] == whosGo)
            {
                return true;
            }
            //check for the diagonal starting in the top right
            if (currentGrid[width - 1] == whosGo && currentGrid[2 * (width - 1)] == whosGo && currentGrid[3 * (width - 1)] == whosGo)
            {
                return true;
            }

            return false;
        }
        static int OneMoveRequired(int cell, char[] currentGrid, char friendly)
        {
            //put the friendly there...
            currentGrid[cell] = friendly;
            //If it would win if the friendly were to go here... return the highest possible value
            if (CheckCurrentWin(currentGrid, friendly))
            {
                return 3;
            }
            //set up the grid again
            char enemy = RotateGo(friendly);
            currentGrid[cell] = enemy;  
            //If it were to win if the enemy were to go here, return the second highest value
            if (CheckCurrentWin(currentGrid, enemy))
            {
                return 2;
            }
            //If it satisfies the 'regular' cell criteria, we continue normal gameplay by returning the out of bounds low value:
            return -2;
        }
        //Note that emailing was never fully implemented, as the code is already messy enough :)
        static void EmailUpdate(char yourGo)
        {
            TournamentUpdate(false);
            Console.WriteLine("Your go!");
            int i;
            do
            {
                i = MakeArrayPosition(GetCoOrds());
            }
            while (OX[i] != ' ');
            OX[i] = go;
            Clear();
            Console.Write(GridBuilder());
            AlternateUsers();
            Console.WriteLine("You have taken your go, now emailing the new gameStatus to your opponent!");
            Email.Game(OX, go, "aroundthesims@hotmail.co.uk", "medalgod@yahoo.co.uk");
        }
    }
}

Thanks a lot
although it worked but as you said it has some errors yet .
When I enter co-ordinates in execute mode for for question " Enter the co-ordinates you want to make an entry in:" it doesn't do anything.
I'll be so great full if you correct it if it's not very time consuming for you.
I'll probably work on this project for my AI course in university .
Thanks a lot.

The coordinate system works fine, you enter one letter and one number eg a1 to go in the top left.
And no, I wont be making any changes, I posted it only so that you could build on it if you wanted, not so i could do a piece of work for you^^

you're right dear Medalgod
I'll try to work on you're project and develop it .
thanks again for you're helps.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.