Advertisement
Guest User

Untitled

a guest
Jun 25th, 2018
73
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 12.79 KB | None | 0 0
  1. #region MINIMAX
  2.  
  3.         struct Available
  4.         {
  5.             public List<List<int[]>> boards; //dostępne plansze
  6.             public List<List<int>> moves; //dostępne ruchy
  7.         }
  8.         private int depth = GameLogic.difficulty; //głębokość przeszukiwania = poziom trudności
  9.  
  10.         class AlphaBeta_Core
  11.         {
  12.             bool m_TurnForPlayerX;
  13.             private List<int[]> board;
  14.             private List<int[]> m_possibleThrees = new List<int[]>
  15.             {
  16.                 //vertically |
  17.                 new [] {1, 2, 3},
  18.                 new [] {4,5,6},
  19.                 new [] {7,8,9},
  20.                 new [] {10,11,12},
  21.                 new [] {13,14,15},
  22.                 new [] {16,17,18},
  23.                 new [] {19,20,21},
  24.                 new [] {22,23,24},
  25.  
  26.                 //horizontally -
  27.                 new [] {1,10,22},
  28.                 new [] {4,11,19},
  29.                 new [] {7,12,16},
  30.                 new [] {2,5,8},
  31.                 new [] {17,20,23},
  32.                 new [] {9,13,18},
  33.                 new [] {6,14,21},
  34.                 new [] {3,15,24},
  35.  
  36.                 //obliquely /
  37.                 new [] {1,4,7},
  38.                 new [] {3,6,9},
  39.                 new [] {16,19,22},
  40.                 new [] {18,21,24}
  41.             };
  42.             private List<Neighborhood> m_neighborhoods = new List<Neighborhood>
  43.             {
  44.                 new Neighborhood(1, new List<int>{ 2,4,10 }),
  45.                 new Neighborhood(2, new List<int>{ 1,3,5 }),
  46.                 new Neighborhood(3, new List<int>{ 2,6,15 }),
  47.  
  48.                 new Neighborhood(4, new List<int>{ 1,5,7,11 }),
  49.                 new Neighborhood(5, new List<int>{ 2,4,6,8 }),
  50.                 new Neighborhood(6, new List<int>{ 3,5,9,14 }),
  51.  
  52.                 new Neighborhood(7, new List<int>{ 4,8,12 }),
  53.                 new Neighborhood(8, new List<int>{ 5,7,9 }),
  54.                 new Neighborhood(9, new List<int>{ 6,8,13 }),
  55.  
  56.                 new Neighborhood(10, new List<int>{ 1,11,22 }),
  57.                 new Neighborhood(11, new List<int>{ 4,10,12,19 }),
  58.                 new Neighborhood(12, new List<int>{ 7,11,16 }),
  59.  
  60.                 new Neighborhood(13, new List<int>{ 9,14,18 }),
  61.                 new Neighborhood(14, new List<int>{ 6,13,15,21 }),
  62.                 new Neighborhood(15, new List<int>{ 3,14,24 }),
  63.  
  64.                 new Neighborhood(16, new List<int>{ 12,17,19 }),
  65.                 new Neighborhood(17, new List<int>{ 16,18,20 }),
  66.                 new Neighborhood(18, new List<int>{ 13,17,21 }),
  67.  
  68.                 new Neighborhood(19, new List<int>{ 11,16,20,22 }),
  69.                 new Neighborhood(20, new List<int>{ 17,19,21,23 }),
  70.                 new Neighborhood(21, new List<int>{ 14,18,20,24 }),
  71.  
  72.                 new Neighborhood(22, new List<int>{ 10,19,23 }),
  73.                 new Neighborhood(23, new List<int>{ 20,22,24 }),
  74.                 new Neighborhood(24, new List<int>{ 15,21,23 })
  75.             };
  76.             private List<int> moves;
  77.             public int m_Score;
  78.  
  79.             Available available;
  80.  
  81.             public List<int> Moves
  82.             {
  83.                 get { return moves; }
  84.                 set { moves = value; }
  85.             }
  86.  
  87.             /*public List<int[]> Board
  88.             {
  89.                 get { return board; }
  90.             }*/
  91.  
  92.             public int RecursiveScore
  93.             {
  94.                 get;
  95.                 private set;
  96.             }
  97.             public bool GameOver
  98.             {
  99.                 get;
  100.                 private set;
  101.             }
  102.             public List<int[]> PossibleThrees { get => m_possibleThrees; set => m_possibleThrees = value; }
  103.             public List<Neighborhood> Neighborhoods { get => m_neighborhoods; set => m_neighborhoods = value; }
  104.  
  105.             public AlphaBeta_Core(List<int[]> values, bool turnForPlayerX) //konstruktor
  106.             {
  107.                 m_TurnForPlayerX = turnForPlayerX;
  108.                 board = values;
  109.                 available = new Available();
  110.                 available.boards = new List<List<int[]>> ();
  111.                 available.moves = new List<List<int>>();
  112.  
  113.                 GetScore();
  114.             }
  115.             // ------ FROM OUTER CLASS
  116.             private IEnumerable<int> getIdsTakenBy(int takenBy)
  117.             {
  118.                 return board.Where(f => f[1] == takenBy).Select(i => i[0]);
  119.             }
  120.  
  121.             private int getAssigment(int id)
  122.             {
  123.                 return board.Find(f => f[0] == id)[1];
  124.             }
  125.  
  126.             public List<int> CheckMovesFirstStage(int team, List<int[]> board)// team: 1-player, 2-computer, 0-nobody
  127.             {
  128.                 List<int> normal_moves_list = new List<int>();
  129.  
  130.                 var freeFields = getIdsTakenBy(0).ToList(); //TakenBy.Nobody == 0
  131.  
  132.                 return freeFields;
  133.             }
  134.  
  135.             public List<int> CheckMovesSecondStage(TakenBy team, int field_id, List<int[]> board)
  136.             {
  137.                 List<int> normal_moves_list = new List<int>();
  138.  
  139.                 var neighbours = m_neighborhoods.FirstOrDefault(n => n.Id == field_id).Neighbors;
  140.  
  141.                 if (!neighbours.Any(n => getAssigment(n) == 0)) return new List<int>(normal_moves_list);
  142.                 else
  143.                 {
  144.                     foreach (var neighbour in neighbours)
  145.                     {
  146.                         if (getAssigment(neighbour) == 0) //dodaj do listy ruchow
  147.                         {
  148.                             int tmp_array;
  149.                             tmp_array = neighbour;
  150.                             normal_moves_list.Add(tmp_array);
  151.                         }
  152.  
  153.                     }
  154.                 }
  155.  
  156.                 return new List<int>(normal_moves_list);
  157.             }
  158.  
  159.             public IEnumerable<AlphaBeta_Core> GetChildren()
  160.             {
  161.                 FindAvailableBoardsFirst(board, m_TurnForPlayerX ? 1 : 2);
  162.  
  163.                 for (int i = 0; i < available.boards.Count; i++)
  164.                 {
  165.                     List<int[]> newValues = new List<int[]>();
  166.                     available.boards[i].ForEach(j => newValues.Add(new int[] { j[0], j[1] }));
  167.  
  168.                     AlphaBeta_Core retChild = new AlphaBeta_Core(newValues, !m_TurnForPlayerX);
  169.                     retChild.Moves = new List<int>(available.moves[i]);
  170.                     yield return retChild;
  171.                 }
  172.             }
  173.  
  174.             //MiniMax z AlfaBeta cięciami
  175.             public int AlphaBetaPruning(int depth, bool needMax, int alpha, int beta, out AlphaBeta_Core childWithMax)
  176.             {
  177.                 childWithMax = null;
  178.                 if (depth == 0 )
  179.                 {
  180.                     RecursiveScore = m_Score;
  181.                     Debug.WriteLine("SCORE: " + m_Score);
  182.                     return m_Score;
  183.                 }
  184.  
  185.                 foreach (AlphaBeta_Core core in GetChildren())
  186.                 {
  187.                     AlphaBeta_Core foo;
  188.                     int score = core.AlphaBetaPruning(depth - 1, !needMax, alpha, beta, out foo);
  189.                     if (!needMax)
  190.                     {
  191.                         if (beta > score)
  192.                         {
  193.                             beta = score;
  194.                             childWithMax = core;
  195.                             if (alpha >= beta)
  196.                             {
  197.                                 break;
  198.                             }
  199.                         }
  200.                     }
  201.                     else
  202.                     {
  203.                         if (alpha < score)
  204.                         {
  205.                             alpha = score;
  206.                             childWithMax = core;
  207.                             if (alpha >= beta)
  208.                             {
  209.                                 break;
  210.                             }
  211.                         }
  212.                     }
  213.                 }
  214.                 RecursiveScore = needMax ? alpha : beta;
  215.                 return RecursiveScore;
  216.             }
  217.  
  218.             public AlphaBeta_Core FindNextMove(int depth)
  219.             {
  220.                 AlphaBeta_Core ret = null;
  221.                 AlphaBetaPruning(depth, m_TurnForPlayerX, int.MinValue + 1, int.MaxValue - 1, out ret);
  222.                 //Debug.WriteLine("ret score: "+ ret.m_Score);
  223.                 return ret;
  224.             }
  225.  
  226.             void GetScore()
  227.             {
  228.                 int[] points = new int[2];
  229.                 // m_red = whether the move resulted in a mill for AI player (1 for yes and 0 for no)
  230.                 // m_blue = whether the move resulted in a mill for Human player (1 for yes and 0 for no)
  231.  
  232.                 // p_red = number of potential mills for the AIs next turn as a result of a particular move
  233.                 // where a potential mill is 3 sequential cells with 2 occupied by the opponent and one blank
  234.  
  235.                 // p_blue = Number of potential mills on the next play for the opponent that would result from making a particular move
  236.                 // where a potential mill is 3 sequential cells with 2 occupied by the opponent and one blank
  237.  
  238.                 int m_blue = 0;
  239.                 int m_red = 0;
  240.  
  241.                 int p_red = 0;
  242.                 int p_blue = 0;
  243.  
  244.                 int l_red = 0;
  245.                 int l_blue = 0;
  246.  
  247.                 int avoid_red = 0;
  248.                 int avoid_blue = 0;
  249.  
  250.                 var computerFieldsIds = board.Where(cf => cf[1] == 2).Select(i => i[0]).ToList();
  251.                 var playerIdsFields = board.Where(pf => pf[1] == 1).Select(i => i[0]).ToList();
  252.  
  253.                 foreach (var line in m_possibleThrees)
  254.                 {
  255.                     if(line.Where(l => getAssigment(l) == 2).Count() == 3)
  256.                     {
  257.                         m_red += 1;
  258.                     }
  259.  
  260.                     if (line.Where(l => getAssigment(l) == 1).Count() == 3)
  261.                     {
  262.                         m_blue += 1;
  263.                     }
  264.                        
  265.                     if (line.Where(l => getAssigment(l) == 2).Count() == 2 &&
  266.                         line.Where(l => getAssigment(l) == 0).Count() == 1)
  267.                     {
  268.                         p_red += 1;
  269.                     }
  270.                     if (line.Where(l => getAssigment(l) == 1).Count() == 2 &&
  271.                         line.Where(l => getAssigment(l) == 0).Count() == 1)
  272.                     {
  273.                         p_blue += 1;
  274.                     }
  275.                     /*
  276.                     if (line.Where(l => getAssigment(l) == 2).Count() == 1 &&
  277.                         line.Where(l => getAssigment(l) == 0).Count() == 2)
  278.                     {
  279.                         l_red += 1;
  280.                     }
  281.                     if (line.Where(l => getAssigment(l) == 1).Count() == 1 &&
  282.                         line.Where(l => getAssigment(l) == 0).Count() == 2)
  283.                     {
  284.                         l_blue += 1;
  285.                     }*/
  286.                     //----------- PRZESZKADZANIE
  287.                     if (line.Where(l => getAssigment(l) == 2).Count() == 2 &&
  288.                         line.Where(l => getAssigment(l) == 1).Count() == 1)
  289.                     {
  290.                         avoid_blue += 1;
  291.                     }
  292.                     if (line.Where(l => getAssigment(l) == 1).Count() == 2 &&
  293.                         line.Where(l => getAssigment(l) == 2).Count() == 1)
  294.                     {
  295.                         avoid_red += 1;
  296.                     }
  297.                     //------------------------------
  298.                 }
  299.                 points[0] = (400 * m_blue) + (100 * p_blue) + (1 * l_blue) + (100 * avoid_blue);
  300.                 points[1] = (400 * m_red) + (100 * p_red) + (1 * l_red) + (100 * avoid_red);
  301.  
  302.                 if (computerFieldsIds.Count == 9 || playerIdsFields.Count == 9)
  303.                 {
  304.                     GameOver = true;
  305.                 }
  306.  
  307.                 m_Score = (points[0] - points[1]);
  308.             }
  309.  
  310.             private void FindAvailableBoardsFirst(List<int[]> board, int turn)
  311.             {
  312.                List<int> tmpAvailableMoves = CheckMovesFirstStage(turn, board); //pobranie wszystkich możliwych ruchów
  313.                 for (int k = 0; k < tmpAvailableMoves.Count; k++)
  314.                 {
  315.                     //List<int[]> newBoard = new List<int[]>(board);
  316.                     List<int[]> newBoard = new List<int[]>();
  317.                     board.ForEach(i => newBoard.Add(new int[] {i[0], i[1]}));
  318.                        
  319.                         List<int> moveA = new List<int>();
  320.                         moveA.Add(tmpAvailableMoves[k]);
  321.  
  322.                         newBoard[(tmpAvailableMoves[k]-1)][1] = turn;
  323.                        
  324.                         available.boards.Add(newBoard);
  325.                         available.moves.Add(moveA);
  326.                 }
  327.             }
  328.  
  329.         }
  330.  
  331.  
  332.         #endregion MINIMAX
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement