Esempio n. 1
0
        /// <summary>
        /// Update a cell on the Gameboard to the desired CellState. Then calls AnalyseGameboard() to see if the new state has any rows of three, and if not checks if the Gameboard has any empty cells left for the game to continue.
        /// Finally if it has not yet exited, it set the next player to make a move.
        /// </summary>
        /// <param name="cell">The coordinates of the cell that should be changed.</param>
        /// <param name="cellState">The state the specified cell will be changed to.</param>
        private void UpdateGameboardCell(CellCoor cell, CellState cellState)
        {
            int m = cell.M;
            int n = cell.N;

            // Update the CellState in the Gameboard array to the new cellState
            if (cellState > (CellState)2)
            {
                cellState = CellState.Empty;
            }
            Gameboard[m, n] = cellState;

            // Select the correct symbol image based on cellState
            string imagePath = string.Empty;

            if (cellState == CellState.Empty)
            {
                imagePath = string.Empty;
            }
            else if (Gameboard[m, n] == CellState.X)
            {
                imagePath = SymbolX;
            }
            else if (Gameboard[m, n] == CellState.O)
            {
                imagePath = SymbolY;
            }
            else
            {
                Debug.WriteLine(string.Format("TicTacToe: UpdateGameboardCell failed to determine the correct symbol to use from cellState")); return;
            }
            BitmapImage newImage = new BitmapImage(new Uri("ms-appx:///" + imagePath));

            // Apply the new symbol image to the correct GameboardImage
            // (The use of a double-argument switch requires language version C# 8.0, the version was 7.3 originally, this is set manually in the .csproj file at the very end of the file, in case this change causes any problems)
            switch (m, n)
            {
Esempio n. 2
0
 public bool Equals(CellCoor cell)
 {
     return(cell.M == this.M && cell.N == this.N);
 }
Esempio n. 3
0
        // Computer behaviour, CellValue
        private void DoComputerTurnCellValue()
        {
            // Create an array of int with the same dimensions as Gameboard, and set each element to 0
            int[,] cellValues = new int[Gameboard.GetLength(0), Gameboard.GetLength(1)];
            for (int iCell = 0; iCell < cellValues.GetLength(0); iCell++)
            {
                for (int jCell = 0; jCell < cellValues.GetLength(1); jCell++)
                {
                    cellValues[iCell, jCell] = 0;
                }
            }

            // Value of cells if the row is completely empty of symbols
            int emptyValue = 1;
            // Value of cells if the row contains one ComputerSymbol
            int oneValue = 3;
            // Value of cells if the row contains two ComputerSymbols, is always larger than the maximum value a cell can reach with just emptyValue & oneValue, meaning this cell gets absolute priority
            int twoValue = ((emptyValue + oneValue) * PossibleRows.GetLength(0)) + 1;
            // Value of cells if the row contains two PlayerSymbols, almost the same as twoValue but the resulting cellValue should always be lower than twoValue (except when a single cell about to complete more than one row)
            int counterValue = (emptyValue + oneValue) * PossibleRows.GetLength(0);

            // Go over PossibleRows to see which rows contain only Empty cells or cells with ComputerSymbol, if so add a certain value, one of the above, to that cell in cellValues
            for (int i = 0; i < PossibleRows.GetLength(0); i++)
            {
                CellState cell0 = Gameboard[PossibleRows[i, 0].M, PossibleRows[i, 0].N];
                CellState cell1 = Gameboard[PossibleRows[i, 1].M, PossibleRows[i, 1].N];
                CellState cell2 = Gameboard[PossibleRows[i, 2].M, PossibleRows[i, 2].N];

                // If none of the cells contain the PlayerSymbol
                if (!cell0.Equals(PlayerSymbol) && !cell1.Equals(PlayerSymbol) && !cell2.Equals(PlayerSymbol))
                {
                    // Add all values of the CellStates together and adjust for the current ComputerSymbol (1 if X, 2 if O),
                    // Resulting in the number of times the ComputerSymbols is present in that row
                    int totalRowValue = (int)cell0 + (int)cell1 + (int)cell2;
                    totalRowValue = totalRowValue / (int)ComputerSymbol;

                    switch (totalRowValue)
                    {
                    // If the row contains no ComputerSymbol, ie it is empty, add emptyValue to all cells of that row
                    case (0):
                    {
                        cellValues[PossibleRows[i, 0].M, PossibleRows[i, 0].N] += emptyValue;
                        cellValues[PossibleRows[i, 1].M, PossibleRows[i, 1].N] += emptyValue;
                        cellValues[PossibleRows[i, 2].M, PossibleRows[i, 2].N] += emptyValue;
                        break;
                    }

                    // If the row contains one ComputerSymbol, add oneValue to all the empty cells in that row
                    case (1):
                    {
                        cellValues[PossibleRows[i, 0].M, PossibleRows[i, 0].N] += (cell0 == CellState.Empty) ? oneValue : 0;
                        cellValues[PossibleRows[i, 1].M, PossibleRows[i, 1].N] += (cell1 == CellState.Empty) ? oneValue : 0;
                        cellValues[PossibleRows[i, 2].M, PossibleRows[i, 2].N] += (cell2 == CellState.Empty) ? oneValue : 0;
                        break;
                    }

                    // If the row contains two ComputerSymbols, add twoValue to the empty cell
                    case (2):
                    {
                        cellValues[PossibleRows[i, 0].M, PossibleRows[i, 0].N] += (cell0 == CellState.Empty) ? twoValue : 0;
                        cellValues[PossibleRows[i, 1].M, PossibleRows[i, 1].N] += (cell1 == CellState.Empty) ? twoValue : 0;
                        cellValues[PossibleRows[i, 2].M, PossibleRows[i, 2].N] += (cell2 == CellState.Empty) ? twoValue : 0;
                        break;
                    }

                    // Something went wrong, log a message
                    default:
                    {
                        Debug.WriteLine(string.Format("TicTacToe: DoComputerTurn CellValue incorrectly calculates the number of ComputerSymbols in a row."));
                        break;
                    }
                    }
                }
                else
                {
                    // Check if the row contains two PlayerSymbols, meaning the player is about to win
                    if (((int)cell0 + (int)cell1 + (int)cell2) / (int)PlayerSymbol == 2)
                    {
                        // If the cell is not empty nor already equal to counterValue (meaning it has already been adjusted for the fact the player is about to win, preventing adding counterValue more then once, and thereby the possibility of the computer prioritising countering the player instead of winning itself)
                        if (cell0.Equals(CellState.Empty) && cellValues[PossibleRows[i, 0].M, PossibleRows[i, 0].N] != counterValue)
                        {
                            cellValues[PossibleRows[i, 0].M, PossibleRows[i, 0].N] += counterValue;
                        }
                        else if (cell1.Equals(CellState.Empty) && cellValues[PossibleRows[i, 1].M, PossibleRows[i, 1].N] != counterValue)
                        {
                            cellValues[PossibleRows[i, 1].M, PossibleRows[i, 1].N] += counterValue;
                        }
                        else if (cell2.Equals(CellState.Empty) && cellValues[PossibleRows[i, 1].M, PossibleRows[i, 1].N] != counterValue)
                        {
                            cellValues[PossibleRows[i, 2].M, PossibleRows[i, 2].N] += counterValue;
                        }
                        else
                        {
                            Debug.WriteLine(string.Format("TicTacToe: CellValues detected a row with two PlayerSymbols, but could not find the empty cell"));
                        }
                    }
                }

                // Should we log the cellValue values every loop, so each time a row in PossibleRows was analysed
                bool logEveryLoop = false;
                if (logEveryLoop)
                {
                    Debug.WriteLine(string.Format("TicTacToe: CellValues loop {0}", i.ToString()));
                    Debug.WriteLine(string.Format("TicTacToe: CellValues {0}, {1}, {2}", cellValues[0, 0].ToString(), cellValues[0, 1].ToString(), cellValues[0, 2].ToString()));
                    Debug.WriteLine(string.Format("TicTacToe: CellValues {0}, {1}, {2}", cellValues[1, 0].ToString(), cellValues[1, 1].ToString(), cellValues[1, 2].ToString()));
                    Debug.WriteLine(string.Format("TicTacToe: CellValues {0}, {1}, {2}", cellValues[2, 0].ToString(), cellValues[2, 1].ToString(), cellValues[2, 2].ToString()));
                }
            }

            // Should we log the cellValue values when all rows of PossibleRows were looked at
            bool logFinalCellValues = true;

            if (logFinalCellValues)
            {
                Debug.WriteLine(string.Format("TicTacToe: final CellValues are;"));
                Debug.WriteLine(string.Format("TicTacToe: CellValues {0}, {1}, {2}", cellValues[0, 0].ToString(), cellValues[0, 1].ToString(), cellValues[0, 2].ToString()));
                Debug.WriteLine(string.Format("TicTacToe: CellValues {0}, {1}, {2}", cellValues[1, 0].ToString(), cellValues[1, 1].ToString(), cellValues[1, 2].ToString()));
                Debug.WriteLine(string.Format("TicTacToe: CellValues {0}, {1}, {2}", cellValues[2, 0].ToString(), cellValues[2, 1].ToString(), cellValues[2, 2].ToString()));
            }

            // Find the highest value in cellValues
            int highestCellValue = 0;

            foreach (int cellValue in cellValues)
            {
                if (cellValue > highestCellValue)
                {
                    highestCellValue = cellValue;
                }
            }
            // Go over cellValues again, adding the coordinates of every cell that matches the highestCellValue to a List
            List <CellCoor> highestCells = new List <CellCoor>();

            for (int iHighestValue = 0; iHighestValue < cellValues.GetLength(0); iHighestValue++)
            {
                for (int jHighestValue = 0; jHighestValue < cellValues.GetLength(1); jHighestValue++)
                {
                    if (cellValues[iHighestValue, jHighestValue] == highestCellValue)
                    {
                        highestCells.Add(new CellCoor(iHighestValue, jHighestValue));
                    }
                }
            }

            // The cell to play
            CellCoor cellToPlay = new CellCoor();

            // If highestCells contains more than one element look if any of the cells would hinder the player from continuing one of its rows
            if (highestCells.Count > 1)
            {
                Debug.WriteLine("CellValue looking for counterPlayer cells");

                // New list of possible cells to play
                List <CellCoor> highestCells2 = new List <CellCoor>();

                foreach (CellCoor highCell in highestCells)
                {
                    for (int iCounterPlayer = 0; iCounterPlayer < PossibleRows.GetLength(0); iCounterPlayer++)
                    {
                        CellCoor antiCell0 = PossibleRows[iCounterPlayer, 0];
                        CellCoor antiCell1 = PossibleRows[iCounterPlayer, 1];
                        CellCoor antiCell2 = PossibleRows[iCounterPlayer, 2];

                        // If the current cell of highestCells is present in a row of PossibleRows
                        if (highCell.Equals(antiCell0) || highCell.Equals(antiCell1) || highCell.Equals(antiCell2))
                        {
                            // If the row contains a PlayerSymbol, add it to the new list
                            if (Gameboard[antiCell0.M, antiCell0.N].Equals(PlayerSymbol) || Gameboard[antiCell1.M, antiCell1.N].Equals(PlayerSymbol) || Gameboard[antiCell2.M, antiCell2.N].Equals(PlayerSymbol))
                            {
                                highestCells2.Add(highCell);
                                Debug.WriteLine(string.Format("CellValue found a counterPlayer cell at ({0}, {1})", highCell.M, highCell.N));
                            }
                        }
                    }
                }

                // If any cells were found and added to the new list, set the origional list to the new
                if (highestCells2.Count > 0)
                {
                    highestCells = new List <CellCoor>(highestCells2);
                }
            }

            // Pick a cell from highestCells, at random since all cells in the List are equally valuable
            cellToPlay = highestCells[Rand.Next(0, highestCells.Count)];
            Debug.WriteLine(string.Format("TicTacToe: DoComputerTurnCellValue() wants to play ({0}, {1}), out of {2} choices", cellToPlay.M, cellToPlay.N, highestCells.Count));

            // Play the selected cell
            UpdateGameboardCell(cellToPlay, ComputerSymbol);
        }