- Home /
problem in minimax algorithm
Hello developers, i am trying to make a tic tac toe game . However, while creating the IA , using the minimax algorithm, i encountred and i don't really understand why .Any help would be appreciated. Error type : InvalidOperationException: operation is not valid due to the current state of the object. lines : 127,132. where i try to change the index . Appearently , the list is empty for some reason , when i debug its count , i get 0. here's what i'm using :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System.Linq;
public class GameManager : MonoBehaviour
{
public static GameManager instance;
public string[] board = { "0", "1", "2", "3", "4", "5", "6", "7", "8" };
public List<int> emptySpots = new List<int>();
public readonly int[,] winningCombos =
{
{0,1,2},
{3,4,5},
{6,7,8},
{0,3,6},
{1,4,7},
{2,5,8},
{0,4,8},
{2,4,6}
};
public bool Player1Turn = true;
public int AiDrawIndex;
public GameObject matrix;
private void Start()
{
if (instance == null)
{
instance = this;
DontDestroyOnLoad(gameObject);
}
else
{
Destroy(gameObject);
}
for (int i = 0; i < 9; i++)
{
board[i] = "" + i;
}
emptySpots = checkEmptySpots(board);
}
public bool CheckWin(string[] currentBoard, string s)
{
bool checkNext = false;
bool check = false;
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 3; j++)
{
checkNext = false;
if (currentBoard[winningCombos[i, j]] != s)
{
checkNext = true;
break;
}
}
if (checkNext)
{
continue;
}
else
{
return true;
}
}
return check;
}
public List<int> checkEmptySpots(string[] checkBoard)
{
List<int> emptySlots = new List<int>();
for (int i = 0; i < checkBoard.Length; i++)
{
if (board[i] != "X" && board[i] != "O")
{
emptySlots.Add(i);
}
}
return emptySlots;
}
public bool checkTie(List<int> checkList)
{
if (checkList.Count == 0)
{
return true;
}
return false;
}
public string[] drawString(int index, string s, string[]drawBoard, List<int> emptylist)
{
drawBoard[index] = s;
if (emptylist.Contains(index))
{
emptylist.Remove(index);
}
return drawBoard;
}
public int miniMax(string[] board,string player)
{
string _player = player;
List<int> availableSpots = checkEmptySpots(board);
if (CheckWin(board,"O"))
{
return +10;
}
else if (CheckWin(board,"X"))
{
return -10;
}
else if (checkTie(availableSpots))
{
return 0;
}
List<int> scores = new List<int>();
List<int> moves = new List<int>();
for (int i = 0; i <9; i++)
{
if (board[i] != "X" && board[i] != "O")
{
moves.Add(i);
scores.Add(miniMax(makeGridMove(board, player, i), switchPlayer(player)));
}
}
if (player == "O")
{
AiDrawIndex = moves[scores.IndexOf(scores.Max())];
return scores.Max();
}
else
{
AiDrawIndex = moves[scores.IndexOf(scores.Min())];
return scores.Min();
}
}
string[] cloneGrid(string[] Grid)
{
string[] Clone = new string[9];
for (int i = 0; i < 9; i++) Clone[i] = Grid[i];
return Clone;
}
string[] makeGridMove(string[] Grid, string Move, int Position)
{
string[] newGrid = cloneGrid(Grid);
newGrid[Position] = Move;
return newGrid;
}
public int returnMin(List<int> list)
{
int min = 100000;
int index = -1;
for (int i = 0; i < list.Count; ++i)
{
if (list[i] < min)
{
min = list[i];
index = i;
}
}
return list[index];
}
public int returnMax(List<int> list)
{
int max = -100000;
int index = -1;
for (int i = 0; i < list.Count; ++i)
{
if (list[i] > max)
{
max = list[i];
index = i;
}
}
return list[index];
}
public string switchPlayer(string Player)
{
if (Player == "X") return "O";
else return "X";
}
private void Update()
{
//Debug.Log(AiDrawIndex);
if (Player1Turn)
{
return;
}
else
{
miniMax(cloneGrid(board), "O");
drawString(AiDrawIndex, "O", board, emptySpots);
GameObject CorrectButton =matrix.transform.Find("" + AiDrawIndex).gameObject;
CorrectButton.transform.Find("Text").GetComponent<Text>().text = "O";
CorrectButton.GetComponent<Button>().interactable = false;
Player1Turn = !Player1Turn;
}
}
}
Answer by amouun · May 15, 2018 at 04:09 PM
I made a new Class instead of two lists , and it is working now here's what i used :
public class move
{
public int score;
public int index;
public move()
{
}
public move(int _score, int _index)
{
score = _score;
index = _index;
}
public void SetIndex (int _index)
{
index = _index;
}
public void SetScore(int _score)
{
score = _score;
}
}
public move miniMax(string[] board,string player)
{
string _player = player;
List<int> availableSpots = checkEmptySpots(board);
if (CheckWin(board,"O"))
{
move _move = new move();
_move.SetScore(10);
return _move;
}
else if (CheckWin(board,"X"))
{
move _move = new move();
_move.SetScore(-10);
return _move;
}
else if (checkTie(availableSpots))
{
move _move = new move();
_move.SetScore(0);
return _move;
}
//List<int> scores = new List<int>();
List<move> moves = new List<move>();
for (int i = 0; i <9; i++)
{
if (board[i] != "X" && board[i] != "O")
{
move _move = new move(miniMax(makeGridMove(board, player, i), switchPlayer(player)).score, i);
moves.Add( _move);
//scores.Add(miniMax(makeGridMove(board, player, i), switchPlayer(player)));
}
}
Debug.Log(moves.Count);
if (player == "O")
{
int max = -10000;
move maxMove=new move();
for (int i = 0; i < moves.Count; i++)
{
if (moves[i].score>max)
{
max = moves[i].score;
maxMove = moves[i];
}
}
//AiDrawIndex = maxMove.index;
return maxMove;
}
else
{
int min = 10000;
move minMove = new move();
for (int i = 0; i < moves.Count; i++)
{
if (moves[i].score < min)
{
min = moves[i].score;
minMove = moves[i];
}
}
//AiDrawIndex = minMove.index;
return minMove;
}
}
Your answer
Follow this Question
Related Questions
A node in a childnode? 1 Answer
Smooth path finding for agents with turning circles. 0 Answers
Why is everything being set the same? Please Help! 1 Answer
Stack overflow with recursive floodfill method. 2 Answers
Game AI Implementation 0 Answers