Advertisement
fabis_sparks

SoltreePolina

Dec 23rd, 2016
162
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 9.07 KB | None | 0 0
  1. #include <QtWidgets>
  2. #include <QtDebug>
  3.  
  4.  
  5. //Поменять местами два значения
  6. void swap(SolutionTree::CellType &a, SolutionTree::CellType &b)
  7. {
  8.     SolutionTree::CellType tmp;
  9.     tmp = a;
  10.     a = b;
  11.     b = tmp;
  12. }
  13.  
  14. //Конструктор дерева решения
  15. SolutionTree::SolutionTree(int size, Color color, bool moveOfAI, int numberOfCheckers)
  16. {
  17.     this->color = color;
  18.     //Создание начального состояния
  19.     QVector< QVector < SolutionTree::CellType > > startField(size, QVector< SolutionTree::CellType > (size, None));
  20.  
  21.     for (int i = 0; i < numberOfCheckers; ++i)
  22.     {
  23.         startField[size - i / 3 - 1][i % 3] = color == White ? Own : Enemy;
  24.         startField[i / 3][size - i % 3 - 1] = color == White ? Enemy : Own;
  25.     }
  26.     //Инициализирование корня дерева
  27.     root = new State(startField, moveOfAI);
  28.     //Srand()
  29.     srand(NULL);
  30.  
  31.     //Построить первые ветви с состояниями
  32.     makeSolutionTree(root, this->TREE_SIZE);
  33. }
  34.  
  35. //Проверка-можем ли мы идти в  [i][j]
  36. bool SolutionTree::canGoTo(State* state, int i, int j)
  37. {
  38.    if (i >= 0 && i < state->field.size() && j >= 0 && j < state->field.size())
  39.    {
  40.        return true;
  41.    }
  42.    else
  43.    {
  44.        return false;
  45.    }
  46. }
  47. // Возвращает все возможные ходы
  48. QSet<SolutionTree::Move> SolutionTree::getPossibleMoves(State *state, int i, int j)
  49. {
  50.     QSet<Move> result;
  51.  
  52.     Color checkerColor = this->color;
  53.  
  54.     if (state->field[i][j] ==  Enemy)
  55.     {
  56.         checkerColor = this->color == White ? Black : White;
  57.     }
  58.  
  59.     if (checkerColor == White)
  60.     {
  61.         if (canGoTo(state, i - 1, j) && state->field[i - 1][j] == None) result.insert(Move(i, j, i - 1, j));
  62.         if (canGoTo(state, i, j + 1) && state->field[i][j + 1] == None) result.insert(Move(i, j, i, j + 1));
  63.     }
  64.     else
  65.     {
  66.         if (canGoTo(state, i, j - 1) && state->field[i][j - 1] == None) result.insert(Move(i, j, i, j - 1));
  67.         if (canGoTo(state, i + 1, j) && state->field[i + 1][j] == None) result.insert(Move(i, j, i + 1, j));
  68.     }
  69.    
  70. // Делаем стоимость состояния
  71. int SolutionTree::moveCost(State* state)
  72. {
  73.  
  74.     CellType type = !state->moveOfAI ? Own : Enemy;
  75.     Color color = this->color;
  76.     if (type == Enemy) color = color == Black ? White : Black;
  77.  
  78.     // Проверка потери вариантов (cost == 0):
  79.          // Если состояние приходит в тупик
  80.     int deltaRow = 0;
  81.     int deltaCol = 0;
  82.     for (int k = 0; k < 3; ++k)
  83.     {
  84.         int checkerAtRowCount = 0;
  85.         int checkerAtColCount = 0;
  86.         int allCount = 0;
  87.         if ((color == White && state->field[k][state->field.size() - k - 1] == type) || (color == Black && state->field[state->field.size() - k - 1][k] == type)) allCount--;
  88.  
  89.         for (int i = k; i < state->field.size(); ++i)
  90.         {
  91.             if ((color == White && state->field[k][state->field.size() - 1 - i] == type) || (color == Black && state->field[state->field.size() - 1 - k][i] == type)) checkerAtRowCount++;
  92.             if ((color == White && state->field[i][state->field.size() - 1 - k] == type) || (color == Black && state->field[state->field.size() - 1 - i][k] == type)) checkerAtColCount++;
  93.         }
  94.  
  95.         allCount += checkerAtColCount + checkerAtRowCount;
  96.         if (checkerAtColCount <= 3 - k && checkerAtRowCount <= 3 - k && allCount <= 5 - 2 * k)
  97.         {
  98.                 deltaRow += 3 - k - checkerAtRowCount;
  99.                 deltaCol += 3 - k - checkerAtColCount;
  100.         }
  101.         else
  102.         {
  103.             return 0;
  104.         }
  105.     }
  106.  
  107.     int cost = 0;
  108.  
  109.     // Создание ненулевой стоимости хода
  110.         cost = rand() % (MAX_COST / 5) + 1;
  111.     // Сделать дерево, чтобы выйти из позиции в первую очередь
  112.     if (state->turnNumber <= 55)
  113.     {
  114.         if (color == White)
  115.         {
  116.             //Если шашка на позиции
  117.             if (state->field.size() - 3 <= state->move.fromI && state->move.fromI < state->field.size() && 0 <= state->move.fromJ && state->move.fromJ < 3)
  118.             {
  119.                 cost = MAX_COST - 1;
  120.                 if (state->move.toI < state->field.size() - 3 || state->move.toJ >= 3) cost++;
  121.             }
  122.             //Если другая блокирует её
  123.             if ((state->move.fromI == state->field.size() - 4 && state->field[state->move.fromI + 1][state->move.fromJ] == type) || (state->move.fromJ == 3 && state->field[state->move.fromI][state->move.fromJ - 1] == type))
  124.             {
  125.                 cost = MAX_COST;
  126.             }
  127.         }
  128.         else
  129.         {
  130.             //Если шашка на позиции
  131.             if (state->field.size() - 3 <= state->move.fromJ && state->move.fromJ < state->field.size() && 0 <= state->move.fromI && state->move.fromI < 3)
  132.             {
  133.                 cost = MAX_COST - 1;
  134.                 if (state->move.toI >= 3 || state->move.toJ < state->field.size() - 3) cost++;
  135.             }
  136.             //если другая блокирует её
  137.             if ((state->move.fromI == 3 && state->field[state->move.fromI - 1][state->move.fromJ] == type) || (state->move.fromJ == state->field.size() - 4 && state->field[state->move.fromI][state->move.fromJ + 1] == type))
  138.             {
  139.                 cost = MAX_COST;
  140.             }
  141.         }
  142.     }
  143.  
  144.     return cost;
  145. }
  146.  
  147. //Рекурсивная функция строит дерево для корневого состояния
  148. void SolutionTree::makeSolutionTree(State *state, int count)
  149. {
  150.     if (count == 0) return;
  151.  
  152.     QSet<Move> moves;
  153.  
  154.     //получение хода
  155.     for (int i = 0; i < state->field.size(); ++i)
  156.     {
  157.         for (int j = 0; j < state->field.size(); ++j)
  158.         {
  159.             if ((state->moveOfAI && state->field[i][j] == Own) || (!state->moveOfAI && state->field[i][j] == Enemy))
  160.             {
  161.                 moves += getPossibleMoves(state, i, j);
  162.             }
  163.         }
  164.     }
  165.  
  166.     //Создание потомков
  167.     for (QSet<Move>::iterator it = moves.begin(); it != moves.end(); ++it)
  168.     {
  169.         swap(state->field[it->fromI][it->fromJ], state->field[it->toI][it->toJ]);
  170.  
  171.         state->child.push_back(new State(state->field, !state->moveOfAI, *it, state->turnNumber + 1));
  172.         state->child.last()->cost = moveCost(state->child.last());      //Создаёт стоимость хода
  173.         makeSolutionTree(state->child.last(), count - 1);
  174.         //Заявление минимакса
  175.         if (state->cost < MAX_COST - 2 && state->cost != 0)
  176.         {
  177.             for (int i = 0; i < state->child.size(); ++i)
  178.             {
  179.                 if (i == 0) state->cost = 1;
  180.                 if (state->child[i]->cost == 0) continue;
  181.                 if (state->moveOfAI) state->cost = qMax(state->cost, state->child[i]->cost);
  182.                 else state->cost = qMin(state->cost, state->child[i]->cost);
  183.             }
  184.         }
  185.  
  186.         swap(state->field[it->fromI][it->fromJ], state->field[it->toI][it->toJ]);
  187.     }
  188.  
  189. }
  190.  
  191. //Удаление всех потомков
  192. void SolutionTree::deleteBranch(State *state)
  193. {
  194.     if (state == NULL) return;
  195.  
  196.     for (int i = 0; i < state->child.size(); ++i)
  197.     {
  198.         deleteBranch(state->child[i]);
  199.     }
  200.     delete state;
  201. }
  202.  
  203. //Возвращает ход
  204. SolutionTree::Move SolutionTree::getMove(State *state)
  205. {
  206.     if (root == NULL)
  207.     {
  208.         root = state;
  209.         root->moveOfAI = true;
  210.         makeSolutionTree(root, TREE_SIZE);
  211.     }
  212.  
  213.     if (root->child.size() == 0)
  214.     {
  215.         makeSolutionTree(root, TREE_SIZE);
  216.     }
  217.  
  218.     //Перемещение состояния на экране
  219.     State* newState = root;
  220.  
  221.     //Найти состояние из поля в дереве и удалить другие
  222.     if (!root->moveOfAI)
  223.     {
  224.         for (int i = 0; i < root->child.size(); ++i)
  225.         {
  226.             if (state->field == root->child[i]->field)
  227.             {
  228.                 newState = root->child[i];
  229.             }
  230.             else
  231.             {
  232.                 deleteBranch(root->child[i]);
  233.             }
  234.         }
  235.         delete root;
  236.     }
  237.  
  238.     root = newState;
  239.  
  240.     if (root->child.size() == 0)
  241.     {
  242.         makeSolutionTree(root, TREE_SIZE);
  243.     }
  244.     //Сделать ход с большей стоимостью
  245.     int cost = - 1;
  246.     int index = 0;
  247.     for (int i = 0; i < root->child.size(); ++i)
  248.     {
  249.         if (root->child[i]->cost > cost || (root->child[i]->cost == cost && rand() % 2))
  250.         {
  251.             cost = root->child[i]->cost;
  252.             index = i;
  253.         }
  254.     }
  255.  
  256.     Move move = root->child[index]->move;
  257.     newState = root->child[index];
  258.  
  259.     //Удалить остальные
  260.     for (int i = 0; i < root->child.size(); ++i)
  261.     {
  262.         if (root->child[i] != newState) deleteBranch(root->child[i]);
  263.     }
  264.     delete root;
  265.  
  266.     root = newState;
  267.  
  268.     return move;
  269.  
  270. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement