Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #region MINIMAX
- struct Available
- {
- public List<List<int[]>> boards; //dostępne plansze
- public List<List<int>> moves; //dostępne ruchy
- }
- private int depth = GameLogic.difficulty; //głębokość przeszukiwania = poziom trudności
- class AlphaBeta_Core
- {
- bool m_TurnForPlayerX;
- private List<int[]> board;
- private List<int[]> m_possibleThrees = new List<int[]>
- {
- //vertically |
- new [] {1, 2, 3},
- new [] {4,5,6},
- new [] {7,8,9},
- new [] {10,11,12},
- new [] {13,14,15},
- new [] {16,17,18},
- new [] {19,20,21},
- new [] {22,23,24},
- //horizontally -
- new [] {1,10,22},
- new [] {4,11,19},
- new [] {7,12,16},
- new [] {2,5,8},
- new [] {17,20,23},
- new [] {9,13,18},
- new [] {6,14,21},
- new [] {3,15,24},
- //obliquely /
- new [] {1,4,7},
- new [] {3,6,9},
- new [] {16,19,22},
- new [] {18,21,24}
- };
- private List<Neighborhood> m_neighborhoods = new List<Neighborhood>
- {
- new Neighborhood(1, new List<int>{ 2,4,10 }),
- new Neighborhood(2, new List<int>{ 1,3,5 }),
- new Neighborhood(3, new List<int>{ 2,6,15 }),
- new Neighborhood(4, new List<int>{ 1,5,7,11 }),
- new Neighborhood(5, new List<int>{ 2,4,6,8 }),
- new Neighborhood(6, new List<int>{ 3,5,9,14 }),
- new Neighborhood(7, new List<int>{ 4,8,12 }),
- new Neighborhood(8, new List<int>{ 5,7,9 }),
- new Neighborhood(9, new List<int>{ 6,8,13 }),
- new Neighborhood(10, new List<int>{ 1,11,22 }),
- new Neighborhood(11, new List<int>{ 4,10,12,19 }),
- new Neighborhood(12, new List<int>{ 7,11,16 }),
- new Neighborhood(13, new List<int>{ 9,14,18 }),
- new Neighborhood(14, new List<int>{ 6,13,15,21 }),
- new Neighborhood(15, new List<int>{ 3,14,24 }),
- new Neighborhood(16, new List<int>{ 12,17,19 }),
- new Neighborhood(17, new List<int>{ 16,18,20 }),
- new Neighborhood(18, new List<int>{ 13,17,21 }),
- new Neighborhood(19, new List<int>{ 11,16,20,22 }),
- new Neighborhood(20, new List<int>{ 17,19,21,23 }),
- new Neighborhood(21, new List<int>{ 14,18,20,24 }),
- new Neighborhood(22, new List<int>{ 10,19,23 }),
- new Neighborhood(23, new List<int>{ 20,22,24 }),
- new Neighborhood(24, new List<int>{ 15,21,23 })
- };
- private List<int> moves;
- public int m_Score;
- Available available;
- public List<int> Moves
- {
- get { return moves; }
- set { moves = value; }
- }
- /*public List<int[]> Board
- {
- get { return board; }
- }*/
- public int RecursiveScore
- {
- get;
- private set;
- }
- public bool GameOver
- {
- get;
- private set;
- }
- public List<int[]> PossibleThrees { get => m_possibleThrees; set => m_possibleThrees = value; }
- public List<Neighborhood> Neighborhoods { get => m_neighborhoods; set => m_neighborhoods = value; }
- public AlphaBeta_Core(List<int[]> values, bool turnForPlayerX) //konstruktor
- {
- m_TurnForPlayerX = turnForPlayerX;
- board = values;
- available = new Available();
- available.boards = new List<List<int[]>> ();
- available.moves = new List<List<int>>();
- GetScore();
- }
- // ------ FROM OUTER CLASS
- private IEnumerable<int> getIdsTakenBy(int takenBy)
- {
- return board.Where(f => f[1] == takenBy).Select(i => i[0]);
- }
- private int getAssigment(int id)
- {
- return board.Find(f => f[0] == id)[1];
- }
- public List<int> CheckMovesFirstStage(int team, List<int[]> board)// team: 1-player, 2-computer, 0-nobody
- {
- List<int> normal_moves_list = new List<int>();
- var freeFields = getIdsTakenBy(0).ToList(); //TakenBy.Nobody == 0
- return freeFields;
- }
- public List<int> CheckMovesSecondStage(TakenBy team, int field_id, List<int[]> board)
- {
- List<int> normal_moves_list = new List<int>();
- var neighbours = m_neighborhoods.FirstOrDefault(n => n.Id == field_id).Neighbors;
- if (!neighbours.Any(n => getAssigment(n) == 0)) return new List<int>(normal_moves_list);
- else
- {
- foreach (var neighbour in neighbours)
- {
- if (getAssigment(neighbour) == 0) //dodaj do listy ruchow
- {
- int tmp_array;
- tmp_array = neighbour;
- normal_moves_list.Add(tmp_array);
- }
- }
- }
- return new List<int>(normal_moves_list);
- }
- public IEnumerable<AlphaBeta_Core> GetChildren()
- {
- FindAvailableBoardsFirst(board, m_TurnForPlayerX ? 1 : 2);
- for (int i = 0; i < available.boards.Count; i++)
- {
- List<int[]> newValues = new List<int[]>();
- available.boards[i].ForEach(j => newValues.Add(new int[] { j[0], j[1] }));
- AlphaBeta_Core retChild = new AlphaBeta_Core(newValues, !m_TurnForPlayerX);
- retChild.Moves = new List<int>(available.moves[i]);
- yield return retChild;
- }
- }
- //MiniMax z AlfaBeta cięciami
- public int AlphaBetaPruning(int depth, bool needMax, int alpha, int beta, out AlphaBeta_Core childWithMax)
- {
- childWithMax = null;
- if (depth == 0 )
- {
- RecursiveScore = m_Score;
- Debug.WriteLine("SCORE: " + m_Score);
- return m_Score;
- }
- foreach (AlphaBeta_Core core in GetChildren())
- {
- AlphaBeta_Core foo;
- int score = core.AlphaBetaPruning(depth - 1, !needMax, alpha, beta, out foo);
- if (!needMax)
- {
- if (beta > score)
- {
- beta = score;
- childWithMax = core;
- if (alpha >= beta)
- {
- break;
- }
- }
- }
- else
- {
- if (alpha < score)
- {
- alpha = score;
- childWithMax = core;
- if (alpha >= beta)
- {
- break;
- }
- }
- }
- }
- RecursiveScore = needMax ? alpha : beta;
- return RecursiveScore;
- }
- public AlphaBeta_Core FindNextMove(int depth)
- {
- AlphaBeta_Core ret = null;
- AlphaBetaPruning(depth, m_TurnForPlayerX, int.MinValue + 1, int.MaxValue - 1, out ret);
- //Debug.WriteLine("ret score: "+ ret.m_Score);
- return ret;
- }
- void GetScore()
- {
- int[] points = new int[2];
- // m_red = whether the move resulted in a mill for AI player (1 for yes and 0 for no)
- // m_blue = whether the move resulted in a mill for Human player (1 for yes and 0 for no)
- // p_red = number of potential mills for the AIs next turn as a result of a particular move
- // where a potential mill is 3 sequential cells with 2 occupied by the opponent and one blank
- // p_blue = Number of potential mills on the next play for the opponent that would result from making a particular move
- // where a potential mill is 3 sequential cells with 2 occupied by the opponent and one blank
- int m_blue = 0;
- int m_red = 0;
- int p_red = 0;
- int p_blue = 0;
- int l_red = 0;
- int l_blue = 0;
- int avoid_red = 0;
- int avoid_blue = 0;
- var computerFieldsIds = board.Where(cf => cf[1] == 2).Select(i => i[0]).ToList();
- var playerIdsFields = board.Where(pf => pf[1] == 1).Select(i => i[0]).ToList();
- foreach (var line in m_possibleThrees)
- {
- if(line.Where(l => getAssigment(l) == 2).Count() == 3)
- {
- m_red += 1;
- }
- if (line.Where(l => getAssigment(l) == 1).Count() == 3)
- {
- m_blue += 1;
- }
- if (line.Where(l => getAssigment(l) == 2).Count() == 2 &&
- line.Where(l => getAssigment(l) == 0).Count() == 1)
- {
- p_red += 1;
- }
- if (line.Where(l => getAssigment(l) == 1).Count() == 2 &&
- line.Where(l => getAssigment(l) == 0).Count() == 1)
- {
- p_blue += 1;
- }
- /*
- if (line.Where(l => getAssigment(l) == 2).Count() == 1 &&
- line.Where(l => getAssigment(l) == 0).Count() == 2)
- {
- l_red += 1;
- }
- if (line.Where(l => getAssigment(l) == 1).Count() == 1 &&
- line.Where(l => getAssigment(l) == 0).Count() == 2)
- {
- l_blue += 1;
- }*/
- //----------- PRZESZKADZANIE
- if (line.Where(l => getAssigment(l) == 2).Count() == 2 &&
- line.Where(l => getAssigment(l) == 1).Count() == 1)
- {
- avoid_blue += 1;
- }
- if (line.Where(l => getAssigment(l) == 1).Count() == 2 &&
- line.Where(l => getAssigment(l) == 2).Count() == 1)
- {
- avoid_red += 1;
- }
- //------------------------------
- }
- points[0] = (400 * m_blue) + (100 * p_blue) + (1 * l_blue) + (100 * avoid_blue);
- points[1] = (400 * m_red) + (100 * p_red) + (1 * l_red) + (100 * avoid_red);
- if (computerFieldsIds.Count == 9 || playerIdsFields.Count == 9)
- {
- GameOver = true;
- }
- m_Score = (points[0] - points[1]);
- }
- private void FindAvailableBoardsFirst(List<int[]> board, int turn)
- {
- List<int> tmpAvailableMoves = CheckMovesFirstStage(turn, board); //pobranie wszystkich możliwych ruchów
- for (int k = 0; k < tmpAvailableMoves.Count; k++)
- {
- //List<int[]> newBoard = new List<int[]>(board);
- List<int[]> newBoard = new List<int[]>();
- board.ForEach(i => newBoard.Add(new int[] {i[0], i[1]}));
- List<int> moveA = new List<int>();
- moveA.Add(tmpAvailableMoves[k]);
- newBoard[(tmpAvailableMoves[k]-1)][1] = turn;
- available.boards.Add(newBoard);
- available.moves.Add(moveA);
- }
- }
- }
- #endregion MINIMAX
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement