// looks through all cellLines to see if any are completely filled, and returns the line if so, null otherwise public static CellButton[] GetWinningLine() { foreach (var line in cellLines) { LineStatus lineStatus = GetLineStatus(line); if (lineStatus.CellsTaken == TileTacToe.BOARD_SIZE) { return(line); // all cells in the line were taken, this must be the winning one } } return(null); // no winning line was found }
// this function takes a line and returns a LineStatus (IsWinnable, Owner, CellsTaken) to describe its state private static LineStatus GetLineStatus(CellButton[] line) { LineStatus status = new LineStatus(); for (int i = 0; i < line.Length; i++) { if (status.Owner == 0 && line[i].Owner > 0) // if this is the first unowned cell, { status.Owner = line[i].Owner; // save owner in status status.CellsTaken++; // and increment count of cells taken } else if (status.Owner > 0 && line[i].Owner != 0) // if line already has an owned cell and this cell is also owned { if (line[i].Owner != status.Owner) // if this cell's owner is different than line's existing owner, { status.IsWinnable = false; // then this line is unwinnable return(status); // don't care about the rest, return status immediately } status.CellsTaken++; // add one to cells taken } } return(status); }
// this returns a numerical weight or value for a line of cells, to choose which line for the computer to play // it assumes TileTacToe.CurrentTurn is the current player and any other players are opponents private static int GetLineWeight(CellButton[] line) { int majorWeight = 0; // this is how important it is to place a cell on the line int minorWeight = 0; // adjusted by how important the line is strategically (the total weight of cells in the line) LineStatus status = GetLineStatus(line); bool isOpponents = (status.Owner != TileTacToe.CurrentTurn); // true if the line is occupied by an opponent if (status.IsWinnable) // only care about lines that can win; unwinnable lines can remain 0 weight { if (TileTacToe.Difficulty == 0) // easy difficulty { // in easy mode, line weights are a bit less intelligent if (status.CellsTaken == 3 && !isOpponents) // if computer has three cells in a line, highest priority to win { majorWeight = 6; } else if (status.CellsTaken > 1) // otherwise randomly pick any line with more than one owned cell { majorWeight = 4; } else if (status.CellsTaken == 1) // otherwise pick any line with just one owned cell { majorWeight = 2; } else // empty lines take lowest priority in easy mode { majorWeight = 1; } } else // hard difficulty { // easy difficulty exists because I've not won a game with the following weights! if (status.CellsTaken == 3 && !isOpponents) // if computer has three cells in a line, highest priority to win { majorWeight = 6; } else if (status.CellsTaken == 3) // if opponent has three cells in a line, block it { majorWeight = 5; } else if (status.CellsTaken == 2) // if either player has two cells in a line, equal weight { majorWeight = 4; } else if (status.CellsTaken == 1 && !isOpponents) // if computer has one cell in a line, claim it before following { majorWeight = 3; } else if (status.CellsTaken == 0) // if the line is empty { majorWeight = 2; } else // lastly, if the opponent has one cell in a line, can ignore it for now { majorWeight = 1; } } majorWeight *= 100; // multiply major weight by 100, minor weight will take up lower two digits // add up minorWeight which is the sum of the cell's weights to break ties when two lines have equal weight foreach (var cell in line) { minorWeight += cell.Weight; } } // a total weight is majorWeight + minorWeight return(majorWeight + minorWeight); }