public Position AnalysePosition(XoField field) { // Построение дерева // Создаём корневой узел var root = new Position {Field = {F = field.F}}; // Создаём дерево CreatePositionsBranches(root); return root; }
public Position(Position source) { Field = new XoField(); Field.F = new byte[3, 3]; for (int i = 0; i <= 2; i++) { for (int j = 0; j <= 2; j++) { Field.F[i, j] = source.Field.F[i, j]; } } Evaluation = 255; Next = new List<Position>(); }
private void CreatePositionsBranches(Position root) { // Создаём список пустых ячеек var freeCells = new List<XoMove>(); for (byte i = 0; i <= 2; i++) { for (byte j = 0; j <= 2; j++) { if (root.Field.F[i, j] == 0) { freeCells.Add(new XoMove { line = i, column = j }); } } } // Создаём ветви // Не просматриваем продолжение выигранных партий if (!WonPosition(root)) { foreach (var move in freeCells) { var nextPosition = new Position(root); nextPosition.Field.F[move.line, move.column] = DetectMove(nextPosition.Field); root.Next.Add(nextPosition); CreatePositionsBranches(nextPosition); } } switch (root.Next.Count) { case 0: // В случае если позиция конечная даём оценку. root.Evaluation = EvaluateEndPosition(root); break; case 1: // Вариантов нет. Ход только один. root.Evaluation = root.Next[0].Evaluation; break; default: // 2 и более // Находим лучший вариант byte bestChance = 255; switch (DetectMove(root.Field)) { case 1: // X 1 <= 0 <= 2 foreach (var position in root.Next) { switch (position.Evaluation) { case 1: bestChance = 1; break; case 0: if (bestChance != 1) bestChance = 0; break; case 2: if (bestChance == 255) bestChance = 2; break; } } break; case 2: // O 2 <= 0 <= 1 foreach (var position in root.Next) { switch (position.Evaluation) { case 2: bestChance = 2; break; case 0: if (bestChance != 2) bestChance = 0; break; case 1: if (bestChance == 255) bestChance = 1; break; } } break; } root.Evaluation = bestChance; break; } }
private bool WonPosition(Position root) { for (int i = 0; i <= 2; i++) { if (((root.Field.F[i, 0] == root.Field.F[i, 1]) && (root.Field.F[i, 1] == root.Field.F[i, 2])) && (root.Field.F[i, 0] != 0)) { return true; } } for (int i = 0; i <= 2; i++) { if (((root.Field.F[0, i] == root.Field.F[1, i]) && (root.Field.F[1, i] == root.Field.F[2, i])) && (root.Field.F[0, i] != 0)) { return true; } } if (((root.Field.F[0, 0] == root.Field.F[1, 1]) && (root.Field.F[1, 1] == root.Field.F[2, 2])) && (root.Field.F[0, 0] != 0)) { return true; } if (((root.Field.F[0, 2] == root.Field.F[1, 1]) && (root.Field.F[1, 1] == root.Field.F[2, 0])) && (root.Field.F[0, 2] != 0)) { return true; } return false; }
private byte EvaluateEndPosition(Position root) { // Горизонтальные линии for (int i = 0; i < 3; i++) { if ((root.Field.F[i, 0] == root.Field.F[i, 1]) && (root.Field.F[i, 1] == root.Field.F[i, 2])) { return root.Field.F[i, 0]; } } // Вериткальные линии for (int i = 0; i < 3; i++) { if ((root.Field.F[0, i] == root.Field.F[1, i]) && (root.Field.F[1, i] == root.Field.F[2, i])) { return root.Field.F[0, i]; } } // Диагонали if ((root.Field.F[0, 0] == root.Field.F[1, 1]) && (root.Field.F[1, 1] == root.Field.F[2, 2])) { return root.Field.F[0, 0]; } if ((root.Field.F[2, 0] == root.Field.F[1, 1]) && (root.Field.F[1, 1] == root.Field.F[0, 2])) { return root.Field.F[2, 0]; } return 0; }