1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50
     51
     52
     53
     54
     55
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
     72
     73
     74
     75
     76
     77
     78
     79
#include <cstdlib>
#include <iostream>

/* let "NimGame.hpp" define the static member of the
   NimGame template class instance we are using */
#define NIM_GAME_DEFINE

#include "HumanNimPlayer.hpp"
#include "NimGame.hpp"
#include "NimParameters.hpp"
#include "OptimalNimPlayer.hpp"
#include "UniformIntDistribution.hpp"

/* MAX_HEAP_SIZE and MOVES are coming from "NimParameters.hpp"
   and are to be configured at compile-time */
using Game = NimGame<MAX_HEAP_SIZE, MOVES>;

int main() {
   std::cout << "*** Game of Nim ***" << std::endl;

   // read parameters of the game
   unsigned int number_of_heaps;
   std::cout << "Number of heaps: ";
   if (!(std::cin >> number_of_heaps) || number_of_heaps == 0) {
      std::cout << "Bye!" << std::endl; return 1;
   }

   // setup game
   Game game(number_of_heaps);
   unsigned int minsize = game.moves[0];
   unsigned int maxsize = MAX_HEAP_SIZE;
   unsigned int range = maxsize - minsize + 1;
   UniformIntDistribution intdist;
   for (unsigned int i = 0; i < number_of_heaps; ++i) {
      game.set_heap_size(i, intdist.draw(range) + minsize);
   }

   std::cout << "Possible moves:";
   for (int move: game.moves) {
      std::cout << " " << move;
   }
   std::cout << std::endl;

   HumanNimPlayer<Game> human_player;
   OptimalNimPlayer<Game> optimal_player;

   while (!game.finished()) {
      std::cout << "Heaps:";
      for (unsigned int i = 0; i < number_of_heaps; ++i) {
     std::cout << " " << game.get_heap_size(i);
      }
      std::cout << std::endl;
      NimMove move;
      switch (game.get_next_player()) {
     case Game::PLAYER1:
        move = human_player.get_move(game); break;
     case Game::PLAYER2:
        move = optimal_player.get_move(game); break;
      }
      if (move.has_resigned()) {
     switch (game.get_next_player()) {
        case Game::PLAYER1:
           std::cout << "You resign." << std::endl; break;
        case Game::PLAYER2:
           std::cout << "The computer resigns." << std::endl; break;
     }
      } else {
     std::cout << move.get_count() << " items are taken from heap "
        << move.get_heap() << std::endl;
      }
      game.execute_move(move);
   }
   switch (game.winner()) {
      case Game::PLAYER1:
     std::cout << "Congratulations, you have won!" << std::endl; break;
      case Game::PLAYER2:
     std::cout << "Too bad, you lost!" << std::endl; break;
   }
}