private void moveBlue() { // the blue oponent moves too fast, so a delay is added in order for the human to spot clearly what move has been made var timer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(1) }; timer.Start(); timer.Tick += (sender, args) => { timer.Stop(); warning.Text = ""; warning.Visibility = System.Windows.Visibility.Hidden; int move = 0; // blue opponent's first move is random int i = 1, j = 2, index = 1; if (firstMoveBlue) { while (a[i, j] != 0) { index = rand.Next(1, 25); Cell c = new Cell(index); i = c.i; j = c.j; } a[i, j] = 2; firstMoveBlue = false; drawEllipse(ellipseV[index], 2, blueColor, 35, false); move = index; ballPlayer2 -= 1; } else if (thirdPhaseBlue) { // check if red will soon create a mill List <Cell> incompleteRedMill = Mill.checkDangerMill(a, 1); // check if blue will create soon a mill List <Cell> incompleteBlueMill = Mill.checkDangerMill(a, 2); List <Mill> blueMills = Mill.getMills(a, 2); Cell moved = Mill.getBlueStoneThirdPhase(a); if (incompleteBlueMill.Count != 0) { a[moved.i, moved.j] = 0; drawEllipse(ellipseV[Helper.toIJ(moved.i, moved.j)], 2, yellowColor, 15, false); int ii = incompleteBlueMill[0].i; int jj = incompleteBlueMill[0].j; drawEllipse(ellipseV[Helper.toIJ(ii, jj)], 2, blueColor, 35, false); a[ii, jj] = 2; } else if (incompleteRedMill.Count != 0) { a[moved.i, moved.j] = 0; drawEllipse(ellipseV[Helper.toIJ(moved.i, moved.j)], 2, yellowColor, 15, false); int ii = incompleteRedMill[0].i; int jj = incompleteRedMill[0].j; drawEllipse(ellipseV[Helper.toIJ(ii, jj)], 2, blueColor, 35, false); a[ii, jj] = 2; } else if (blueMills.Count != 0) { Cell x = new Cell(blueMills[0].start); for (int k = 1; k < 25; k++) { Cell n = new Cell(k); if (a[n.i, n.j] == 0) { a[n.i, n.j] = 2; a[x.i, x.j] = 0; drawEllipse(ellipseV[Helper.toIJ(x.i, x.j)], 2, yellowColor, 15, false); drawEllipse(ellipseV[Helper.toIJ(n.i, n.j)], 2, blueColor, 35, false); } } } else { int ct = 0; Cell first = new Cell(0); Cell second = new Cell(0); for (int k = 1; k < 25; k++) { Cell x = new Cell(k); if ((a[x.i, x.j] == 2) && (ct == 0)) { ct++; first = x; } else if ((a[x.i, x.j] == 2) && (ct == 1)) { second = x; a[first.i, first.j] = 0; drawEllipse(ellipseV[Helper.toIJ(first.i, first.j)], 2, yellowColor, 15, false); for (int n = 1; n < 25; n++) { Cell n_c = new Cell(n); if (Cell.neighbour(a, n_c, second) && (a[n_c.i, n_c.j] == 0)) { a[n_c.i, n_c.j] = 2; drawEllipse(ellipseV[Helper.toIJ(n_c.i, n_c.j)], 2, blueColor, 35, false); break; } } } } } } else // if the game is in phase 1 check whether red will soon form a mill (two neighbour red stones) // and whether blue will form soon a mill; // completing blue mill has preference over blocking formation of red mill because after // completing a blue mill, it will remove a red stone that is inside a dangerous/ incomplete red mill) if (ballPlayer2 > 0) { // check if red will soon create a mill List <Cell> incompleteRedMill = Mill.checkDangerMill(a, 1); // check if blue will create soon a mill List <Cell> incompleteBlueMill = Mill.checkDangerMill(a, 2); // try to build blue mill Cell aimBlueMill = Mill.goMill(a); // if no danger of red mill was detected and blue will not create soon a mill if (incompleteRedMill.Count == 0 && incompleteBlueMill.Count == 0) { if (aimBlueMill != null) { a[aimBlueMill.i, aimBlueMill.j] = 2; drawEllipse(ellipseV[Helper.toIJ(aimBlueMill.i, aimBlueMill.j)], 2, blueColor, 35, false); move = Helper.toIJ(aimBlueMill.i, aimBlueMill.j); } else { i = 1; j = 2; index = 1; while (a[i, j] != 0) { index = rand.Next(1, 25); Cell c = new Cell(index); i = c.i; j = c.j; } a[i, j] = 2; drawEllipse(ellipseV[index], 2, blueColor, 35, false); move = index; } } else if ((incompleteRedMill.Count != 0) && (incompleteBlueMill.Count == 0)) { // danger for red to create mill and blue will not create soon a mill // => move blue stone to block red mill a[incompleteRedMill[0].i, incompleteRedMill[0].j] = 2; drawEllipse(ellipseV[Helper.toIJ(incompleteRedMill[0].i, incompleteRedMill[0].j)], 2, blueColor, 35, false); move = Helper.toIJ(incompleteRedMill[0].i, incompleteRedMill[0].j); checkMill(2, ellipseV[Helper.toIJ(incompleteRedMill[0].i, incompleteRedMill[0].j)]); } else if ((incompleteRedMill.Count != 0) && (incompleteBlueMill.Count != 0)) { // danger for red to create mill and blue will create soon a mill // => complete blue mill a[incompleteBlueMill[0].i, incompleteBlueMill[0].j] = 2; drawEllipse(ellipseV[Helper.toIJ(incompleteBlueMill[0].i, incompleteBlueMill[0].j)], 2, blueColor, 35, false); move = Helper.toIJ(incompleteBlueMill[0].i, incompleteBlueMill[0].j); } else { // no danger for red to create mill and blue will create soon a mill a[incompleteBlueMill[0].i, incompleteBlueMill[0].j] = 2; drawEllipse(ellipseV[Helper.toIJ(incompleteBlueMill[0].i, incompleteBlueMill[0].j)], 2, blueColor, 35, false); move = Helper.toIJ(incompleteBlueMill[0].i, incompleteBlueMill[0].j); } ballPlayer2 -= 1; } else if (secondPhase) { List <Cell> blueDangerousMills = Mill.checkDangerMill(a, 2); List <Cell> redDangerousMills = Mill.checkDangerMill(a, 1); List <Mill> blueMills = Mill.getMills(a, 2); bool blueMoved = false; // search through all the blue mills to get a free neighbour position where to move // one of the blue stones from inside the mill (strategy for removing red stones => next move will close back the mill) if (!blueMoved && (!breakMill)) { HashSet <int> blueStones = new HashSet <int>(); foreach (Mill m in blueMills) { blueStones.Add(m.start); blueStones.Add(m.middle); blueStones.Add(m.stop); } if (blueStones.Count != 0) { foreach (int stone in blueStones) { if (!blueMoved) { for (int k = 1; k < 25; k++) { Cell n_k = new Cell(k); Cell n_s = new Cell(stone); if (Cell.neighbour(a, n_k, n_s) && (a[n_k.i, n_k.j] == 0)) { drawEllipse(ellipseV[Helper.toIJ(n_k.i, n_k.j)], 2, blueColor, 35, false); move = Helper.toIJ(n_k.i, n_k.j); drawEllipse(ellipseV[Helper.toIJ(n_s.i, n_s.j)], 2, yellowColor, 15, false); a[n_k.i, n_k.j] = 2; a[n_s.i, n_s.j] = 0; blueMoved = true; breakMill = true; break; } } } else { break; } } } } // try to find an incomplete blue mill and if a blue stone is in the neighbourhood, move it to complete the mill if (!blueMoved && breakMill) { HashSet <int> StonesInMills = new HashSet <int>(); foreach (Mill m in blueMills) { StonesInMills.Add(m.start); StonesInMills.Add(m.middle); StonesInMills.Add(m.stop); } foreach (Cell blue in blueDangerousMills) { for (int k = 1; k < 25; k++) { if (!blueMoved) { Cell n = new Cell(k); if (Cell.neighbour(a, n, blue) && (a[n.i, n.j] == 2) && (!StonesInMills.Contains(k))) { drawEllipse(ellipseV[Helper.toIJ(blue.i, blue.j)], 2, blueColor, 35, false); move = Helper.toIJ(blue.i, blue.j); drawEllipse(ellipseV[Helper.toIJ(n.i, n.j)], 2, yellowColor, 15, false); a[n.i, n.j] = 0; a[blue.i, blue.j] = 2; blueMoved = true; breakMill = false; break; // found a good position to move the blue stone, so stop searching } } else { break; // break from the outer loop after finding a good postion to move } } } } // if the precedent case didn't result in a position where to move the blue stone // then search through all incomplete red mills for a position that has in // the neighbourhood a blue stone and if one is found, move blue stone to block forming a red mill if (!blueMoved) { foreach (Cell red in redDangerousMills) { for (int k = 1; k < 25; k++) { if (!blueMoved) { Cell n = new Cell(k); if (Cell.neighbour(a, n, red) && (a[n.i, n.j] == 2)) { drawEllipse(ellipseV[Helper.toIJ(red.i, red.j)], 2, blueColor, 35, false); move = Helper.toIJ(red.i, red.j); drawEllipse(ellipseV[Helper.toIJ(n.i, n.j)], 2, yellowColor, 15, false); a[n.i, n.j] = 0; a[red.i, red.j] = 2; blueMoved = true; break; } } else { break; } } } } while (!blueMoved) { index = rand.Next(1, 25); for (int k = 1; k < 25; k++) { Cell n_k = new Cell(k); Cell c = new Cell(index); if ((a[c.i, c.j] == 2) && (Cell.neighbour(a, n_k, c)) && (a[n_k.i, n_k.j] == 0)) { a[n_k.i, n_k.j] = 2; a[c.i, c.j] = 0; drawEllipse(ellipseV[k], 2, blueColor, 35, false); drawEllipse(ellipseV[index], 2, yellowColor, 15, false); move = index; blueMoved = true; } } } } Helper.printBoard(a); blueMill = false; checkMill(2, ellipseV[move]); oldBlueMills = bMills.Count; bMills = Mill.getMills(a, 2); newBlueMills = bMills.Count; if (oldBlueMills - newBlueMills == 1) { removedRedStone--; // blue moved so that one mill is broken } if (newBlueMills != removedRedStone) { Cell red = Mill.removeRedStone(a); warning.SetResourceReference(TextBox.TextProperty, "redStoneRemoved"); warning.Visibility = System.Windows.Visibility.Visible; a[red.i, red.j] = 0; Helper.printBoard(a); drawEllipse(ellipseV[Helper.toIJ(red.i, red.j)], 1, yellowColor, 15, false); removedRedStone++; } }; }
public static Cell removeRedStone(int[,] a) { // returns what red stone should be removed in case blue formed a mill // check if red could create soon a mill (two red stones in vecinity) // else remove random red stone List <Cell> redDangerousMills = Mill.checkDangerMill(a, 1); List <Mill> redMills = Mill.getMills(a, 1); HashSet <int> redStonesInMills = new HashSet <int>(); int stone = 0; foreach (Mill m in redMills) { redStonesInMills.Add(m.start); redStonesInMills.Add(m.middle); redStonesInMills.Add(m.stop); stone = m.start; } foreach (int s in redStonesInMills) { Console.Out.WriteLine(s + " "); } if (redDangerousMills.Count != 0) { // remove red stone that is inside an incomplete mill foreach (Cell incomplete in redDangerousMills) { // find its neighbours that could form a mill for (int i = 1; i < 25; i++) { for (int j = i + 1; j < 25; j++) { int k = Helper.toIJ(incomplete.i, incomplete.j); var numbers = new int[] { i, j, k }; Array.Sort(numbers); Cell x = new Cell(numbers[0]); Cell y = new Cell(numbers[1]); Cell z = new Cell(numbers[2]); // check if the stones are different, neighbours and on the same row or column if ((k != i) && (k != j) && (Cell.neighbour(a, x, y)) && (Cell.neighbour(a, y, z)) && Cell.consecutive(x, y, z)) { if (a[x.i, x.j] == 1 && (!redStonesInMills.Contains(numbers[0]))) { return(x); } else if (a[y.i, y.j] == 1 && (!redStonesInMills.Contains(numbers[1]))) { return(y); } else if (a[z.i, z.j] == 1 && (!redStonesInMills.Contains(numbers[2]))) { return(z); } } } } } // remove red stone that is in the vecinity of an incomplete mill, regardless of row or column foreach (Cell incomplete in redDangerousMills) { for (int k = 1; k < 25; k++) { Cell c = new Cell(k); if (Cell.neighbour(a, incomplete, c) && (a[c.i, c.j] == 1) && (!redStonesInMills.Contains(k))) { return(c); } } } } for (int index = 1; index < 25; index++) { Cell w = new Cell(index); if ((a[w.i, w.j] == 1) && (!redStonesInMills.Contains(index))) { return(w); } } return(new Cell(stone)); }