Advertisement
Guest User

Untitled

a guest
Mar 30th, 2017
56
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.60 KB | None | 0 0
  1. #include <iostream>
  2. #include <vector>
  3.  
  4. #include "nim.h"
  5.  
  6. #define INF 999999
  7.  
  8. Move::Move(int amount = 0, int heap = -1): amount(amount), heap(heap)
  9. {
  10. }
  11.  
  12. Move::Move() {}
  13.  
  14. Nim::Nim()
  15. {
  16.     heaps[0] = 3;
  17.     heaps[1] = 2;
  18.     heaps[2] = 2;
  19. }
  20.  
  21. /**
  22.  * Returneaza o lista cu mutarile posibile
  23.  * care pot fi efectuate de player
  24.  */
  25. std::vector<Move>
  26. Nim::get_moves(int player)
  27. {
  28.     std::vector<Move> ret;
  29.     for (int i = 0; i < 3; i++)
  30.         for (int k = 1; k <= 3; k++)
  31.             if (k <= heaps[i])
  32.                 ret.push_back(Move(k, i));
  33.     return ret;
  34. }
  35.  
  36. /**
  37.  * Intoarce true daca jocul este intr-o stare finala
  38.  */
  39. bool
  40. Nim::ended()
  41. {
  42.     if (heaps[0] == 0 && heaps[1] == 0 && heaps[2] == 0)
  43.         return true;
  44.     return false;
  45. }
  46.  
  47. /**
  48.  * Functia de evaluare a starii curente a jocului
  49.  * Evaluarea se face din perspectiva jucatorului
  50.  * aflat curent la mutare (player)
  51.  */
  52. int
  53. Nim::eval(int player)
  54. {
  55.     /**
  56.      * TODO Implementati o functie de evaluare
  57.      * pentru starea curenta a jocului
  58.      *
  59.      * Aceasta trebuie sa intoarca:
  60.      * Inf daca jocul este terminat in favoarea lui player
  61.      * -Inf daca jocul este terminat in defavoarea lui player
  62.      *
  63.      * In celelalte cazuri ar trebui sa intoarca un scor cu atat
  64.      * mai mare, cu cat player ar avea o sansa mai mare de castig
  65.      */
  66.     if (ended()) {
  67.         return (player * INF);
  68.     }
  69.     return 0;
  70.  
  71.     int xor_sum = heaps[0] ^ heaps[1] ^ heaps[2];
  72.     if (xor_sum == 0) {
  73.         return 1;
  74.     }
  75.     else {
  76.         return 0;
  77.     }
  78.  
  79.  
  80. }
  81.  
  82. /**
  83.  * Aplica o mutarea a jucatorului asupra starii curente
  84.  * Returneaza false daca mutarea e invalida
  85.  */
  86. bool
  87. Nim::apply_move(const Move &move)
  88. {
  89.     /**
  90.      * TODO Realizati efectuarea mutarii
  91.      * (scadeti move.amount din multimea corespunzatoare
  92.      */
  93.  
  94.     int currentAmount = move.first;
  95.     int currentHeap = move.second;
  96.     if (currentAmount >= heaps[currentHeap]) {
  97.         heaps[currentHeap] -= currentAmount;
  98.         return true;
  99.     }
  100.     return false;
  101. }
  102.  
  103. /**
  104.  * Afiseaza starea jocului
  105.  */
  106. void
  107. Nim::print()
  108. {
  109.     for (int i = 0; i < 3; i++)
  110.     {
  111.         std::cout << i << ":";
  112.         for (int j = 0; j < heaps[i]; j++)
  113.             std::cout << " *";
  114.         std::cout << std::endl;
  115.     }
  116.     std::cout << std::endl;
  117. }
  118.  
  119. /**
  120.  * Implementarea algoritmului minimax (negamax)
  121.  * Intoarce o pereche <x, y> unde x este cel mai bun scor
  122.  * care poate fi obtinut de jucatorul aflat la mutare,
  123.  * iar y este mutarea propriu-zisa
  124.  */
  125.  
  126. std::pair<int, Move> maxi(Nim init, int depth, int player) {
  127.     std::vector<Move> moves = init.get_moves(player);
  128.     Move maxMove;
  129.     if (init.ended() || depth == 0){
  130.         Move emptyMove;
  131.         return pair<int, Move> (init.eval(player), emptyMove);
  132.     }
  133.     int mx = -INF;
  134.     for (Move move : moves) {
  135.         int score = (std::pair<int, Move> mini(init, depth - 1, player)).first;
  136.         if (score > mx) {
  137.             mx = score;
  138.             maxMove = move;
  139.         }
  140.     }
  141.     return std::pair<int, Move>(mx, maxMove);
  142. }
  143.  
  144. std::pair<int, Move> mini(Nim init, int depth, int player) {
  145.     std::vector<Move> moves = get_moves(player);
  146.     Move minMove;
  147.     if (init.ended() || depth == 0) {
  148.         Move emptyMove;    
  149.         int evaluation = - init.eval(player);
  150.         return std::pair<int, Move> (evaluation, emptyMove);
  151.     }
  152.     int mn = INF;
  153.     for (Move move : moves) {
  154.         int score = (std::pair<int, Move> maxi(init, depth - 1, player)).first;
  155.         if (score < mn) {
  156.             mn = score;
  157.             minMove = move;
  158.         }
  159.     }
  160.     return std::pair<int, Move>(mn, minMove);
  161. }
  162.  
  163. /**
  164.  * Implementarea de negamax cu alpha-beta pruning
  165.  * Intoarce o pereche <x, y> unde x este cel mai bun scor
  166.  * care poate fi obtinut de jucatorul aflat la mutare,
  167.  * iar y este mutarea propriu-zisa
  168.  */
  169. std::pair<int, Move>
  170. minimax_abeta(Nim init, int player, int depth, int alfa, int beta)
  171. {
  172.     /**
  173.      * TODO Implementati conditia de oprire
  174.      */
  175.  
  176.     std::vector<Move> moves = init.get_moves(player);
  177.  
  178.     /**
  179.      * TODO Determinati cel mai bun scor si cea mai buna mutare
  180.      * folosind algoritmul minimax cu alfa-beta pruning
  181.      */
  182.  
  183.     return std::pair<int, Move>(-Inf, Move());
  184. }
  185.  
  186. int main()
  187. {
  188.     Nim nim;
  189.  
  190.     nim.heaps[0] = 3;
  191.     nim.heaps[1] = 2;
  192.     nim.heaps[2] = 2;
  193.  
  194.     nim.print();
  195.  
  196.     /* Choose here if you want COMP vs HUMAN or COMP vs COMP */
  197.     bool HUMAN_PLAYER = true;
  198.     int player = 1;
  199.  
  200.     while (!nim.ended())
  201.     {
  202.         std::pair<int, Move> p;
  203.         if (player == 1)
  204.         {
  205.             p = maxi(nim, player, 6);
  206.             //p = minimax_abeta(nim, player, 13, -Inf, Inf);
  207.  
  208.             std::cout << "Player " << player << " evaluates to " << p.first << std::endl;
  209.             nim.apply_move(p.second);
  210.         }
  211.         else
  212.         {
  213.             if (!HUMAN_PLAYER)
  214.             {
  215.                 p = mini(nim, player, 6);
  216.                 //p = minimax_abeta(nim, player, 13, -Inf, Inf);
  217.  
  218.                 std::cout << "Player " << player << " evaluates to " << p.first << std::endl;
  219.                 nim.apply_move(p.second);
  220.             }
  221.             else
  222.             {
  223.                 bool valid = false;
  224.                 while (!valid)
  225.                 {
  226.                     int am, h;
  227.                     std::cout << "Insert amount [1, 2 or 3] and heap [0, 1 or 2]: ";
  228.                     std::cin >> am >> h;
  229.                     valid = nim.apply_move(Move(am, h));
  230.                 }
  231.             }
  232.         }
  233.  
  234.         nim.print();
  235.         player *= -1;
  236.     }
  237.  
  238.     int w = nim.heaps[0] + nim.heaps[1] + nim.heaps[2];
  239.     if (w == 0)
  240.         std::cout << "Player " << player << " WON!" << std::endl;
  241.     else
  242.         std::cout << "Player " << player << " LOST!" << std::endl;
  243. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement