Я создал полную игру в крестики-нолики на андроиде с минимаксным ИИ.
Сначала я написал и запустил код в окне консоли в IDE NetBeans для простоты тестирования, и код работал нормально. Однако, когда я интегрировал код в свое приложение для Android, ИИ потребовалось 5 секунд, чтобы совершить свой первый ход. Хотя время, необходимое для воспроизведения других ходов, составляло <1 секунда. <br>Если бы в коде были какие-либо проблемы, то другие ходы должны были бы также занять некоторое время.
Я не могу найти решение этой проблемы. Ниже приведен мой код:
AI_Move.java: -
class AI_Move {
private int x;
private int y;
private int score;
public AI_Move() {
}
public AI_Move(int score) {
this.score = score;
}
//getters and setters method.....
}
AI_Player.java: -
class AI_Player {
private GameActivity activeGame;
AI_Player(GameActivity gameActivity) {
activeGame = gameActivity;
}
AI_Move playMove() {
return getBestMove(PLAYER_AI);
}
private AI_Move getBestMove(String player) { //This is the minimax algorithm function
String status = activeGame.gameStatus();
if (status != null) {
switch (status) {
case PLAYER_AI:
return new AI_Move(10);
case PLAYER_HUMAN:
return new AI_Move(-10);
case GameActivity.TIE:
return new AI_Move(0);
}
}
ArrayList<AI_Move> moves = new ArrayList<>();
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (activeGame.getValue(i, j).equals(NO_VALUE)) { //if empty slot is found
activeGame.enterValue(i, j, player); //enter player (X or O)
AI_Move temp_move = new AI_Move();
if (player.equals(PLAYER_AI)) {
temp_move.setScore(getBestMove(PLAYER_HUMAN).getScore());
temp_move.setY(i);
temp_move.setX(j);
} else {
temp_move.setScore(getBestMove(PLAYER_AI).getScore());
temp_move.setY(i);
temp_move.setX(j);
}
moves.add(temp_move);
activeGame.enterValue(i, j, NO_VALUE);
}
}
}
int bestMove = 0;
int bestScore;
if (player.equals(PLAYER_AI)) {
bestScore = -100;
for (int i = 0; i < moves.size(); i++) {
if (moves.get(i).getScore() > bestScore) {
bestScore = moves.get(i).getScore();
bestMove = i;
}
}
} else if (player.equals(PLAYER_HUMAN)) {
bestScore = 100;
for (int i = 0; i < moves.size(); i++) {
if (moves.get(i).getScore() < bestScore) {
bestScore = moves.get(i).getScore();
bestMove = i;
}
}
}
return moves.get(bestMove);
}
}
Ниже приведена победная логика, содержащая функции (в GameActivity.java), используемые в AI_Player.java:-
public String gameStatus() { //this returns a string indicating the winner or a tie
ImageButton s1, s2, s3;
String status;
isTied = true;
for (int pos = 0; pos < 3; pos++) {
s1 = slots[pos][pos];
s2 = slots[pos][(pos + 1) % 3];
s3 = slots[pos][(pos + 2) % 3];
status = check(s1, s2, s3);
if (status != null && !status.equals(NO_VALUE)) {
return status;
}
s2 = slots[(pos + 1) % 3][pos];
s3 = slots[(pos + 2) % 3][pos];
status = check(s1, s2, s3);
if (status != null && !status.equals(NO_VALUE)) {
return status;
}
if (pos != 1) {
s1 = slots[2 - pos][0];
s2 = slots[1][1];
s3 = slots[pos][2];
status = check(s1, s2, s3);
if (status != null && !status.equals(NO_VALUE)) {
return status;
}
}
}
return isTied == false ? null : TIE;
}
private String check(ImageButton s1, ImageButton s2, ImageButton s3) {
if (!s1.getTag().equals(NO_VALUE) && !s2.getTag().equals(NO_VALUE) && !s3.getTag().equals(NO_VALUE)) { //if all three slots are filled then...
if (s1.getTag().equals(s2.getTag()) && s2.getTag().equals(s3.getTag())) { //return winner if the slots are same (contain same tags)
return s1.getTag().toString();
} else {
return null;
}
} else { //if any one slot is empty return NO_VALUE
isTied = false;
return NO_VALUE;
}
}
Мой «взлом» для задачи: -
Однако я нашел хак для этой проблемы. Я дал первый ход (который занимал 5 секунд) самому ИИ через следующий код и оставил остальные ходы для алгоритма: -
Random random = new Random();
int y = random.nextInt(3);
int x = random.nextInt(3);;
fillSlot(slots[y][x], PLAYER_AI);
Удивительно, но он работал как хотелось!
Я знаю, что это "грязная работа", но я не могу думать о чем-то другом, поэтому я пришел сюда.