private static float PlayBestGlobalMove(int[, , ,] Cells, int player, ref int Bc, ref int Br, out int Cc, out int Cr, ref int age, int maxAge) { List <int> availableBc = new List <int>(); List <int> availableBr = new List <int>(); List <int> availableCc = new List <int>(); List <int> availableCr = new List <int>(); Cc = -1; Cr = -1; if (age > maxAge) { float wins = 0; float loses = 0; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { if ( Cells[i, j, 0, 0] + Cells[i, j, 0, 1] + Cells[i, j, 0, 2] == player * 3 || Cells[i, j, 1, 0] + Cells[i, j, 1, 1] + Cells[i, j, 1, 2] == player * 3 || Cells[i, j, 2, 0] + Cells[i, j, 2, 1] + Cells[i, j, 2, 2] == player * 3 || Cells[i, j, 0, 0] + Cells[i, j, 1, 0] + Cells[i, j, 2, 0] == player * 3 || Cells[i, j, 0, 1] + Cells[i, j, 1, 1] + Cells[i, j, 2, 1] == player * 3 || Cells[i, j, 0, 2] + Cells[i, j, 1, 2] + Cells[i, j, 2, 2] == player * 3 || Cells[i, j, 0, 0] + Cells[i, j, 1, 1] + Cells[i, j, 2, 2] == player * 3 || Cells[i, j, 0, 2] + Cells[i, j, 1, 1] + Cells[i, j, 2, 0] == player * 3 ) { wins++; } else if ( Cells[i, j, 0, 0] + Cells[i, j, 0, 1] + Cells[i, j, 0, 2] == -1 * player * 3 || Cells[i, j, 1, 0] + Cells[i, j, 1, 1] + Cells[i, j, 1, 2] == -1 * player * 3 || Cells[i, j, 2, 0] + Cells[i, j, 2, 1] + Cells[i, j, 2, 2] == -1 * player * 3 || Cells[i, j, 0, 0] + Cells[i, j, 1, 0] + Cells[i, j, 2, 0] == -1 * player * 3 || Cells[i, j, 0, 1] + Cells[i, j, 1, 1] + Cells[i, j, 2, 1] == -1 * player * 3 || Cells[i, j, 0, 2] + Cells[i, j, 1, 2] + Cells[i, j, 2, 2] == -1 * player * 3 || Cells[i, j, 0, 0] + Cells[i, j, 1, 1] + Cells[i, j, 2, 2] == -1 * player * 3 || Cells[i, j, 0, 2] + Cells[i, j, 1, 1] + Cells[i, j, 2, 0] == -1 * player * 3 ) { loses++; } } } return((wins - loses) / 9); // instead retun a franction between -1 and 1 based on finished boards } FindAvailableMoves(Cells, Bc, Br, availableBc, availableBr, availableCc, availableCr); if (availableBc.Count == 0) { return(0); // instead retun a franction between -1 and 1 based on finished boards } float bestScore = -10; int bestAge = 0; for (int i = 0; i < availableBc.Count; i++) { int localAge = age; float score = -10; //int[,,,] cells = new int[3, 3, 3, 3]; GameEngine localEngine = new GameEngine(); localEngine.NextPlayer = player; int cc, cr; Array.Copy(Cells, localEngine.Cells, Cells.Length); // do not call the next line for a less smart AI localEngine.recalculateBoards(); MoveState res = localEngine.PlayMove(player, availableBc[i], availableBr[i], availableCc[i], availableCr[i]); localAge++; if (res == MoveState.SUCCESS_BOARD_WON_GAME_WON || res == MoveState.SUCCESS_BOARD_DRAW_GAME_WON) { score = 1; } else if (res == MoveState.SUCCESS_BOARD_WON_GAME_LOST || res == MoveState.SUCCESS_BOARD_DRAW_GAME_LOST) { score = -1; } else if (!localEngine.IsMoveSuccess(res)) { break; } else { score = -1 * PlayBestGlobalMove(localEngine.Cells, -1 * player, ref localEngine.NextBoardCol, ref localEngine.NextBoardRow, out cc, out cr, ref localAge, maxAge); } if (score > bestScore || (bestScore != 1 && score == bestScore && localAge >= bestAge) || (bestScore == 1 && score == bestScore && localAge <= bestAge)) { if (localAge == bestAge && score == bestScore) { if (new Random().Next() % 2 == 0) { bestScore = score; Bc = availableBc[i]; Br = availableBr[i]; Cc = availableCc[i]; Cr = availableCr[i]; bestAge = localAge; } } else { bestScore = score; Bc = availableBc[i]; Br = availableBr[i]; Cc = availableCc[i]; Cr = availableCr[i]; bestAge = localAge; } } } age = bestAge; return(bestScore); }