#include <algorithm>
#include <iostream>
#include <map>
#include <ctime>

class board
{
  int cell[3*3];

  public:
  board() { reset(); }
  void reset() { std::fill_n(cell, 3*3, 0); }

  int& operator()(int x, int y)
  { return cell[x+3*y]; }
  const int& operator()(int x, int y) const
  { return cell[x+3*y]; }
};
std::ostream& operator<<(std::ostream& os, const board& b)
{
  for ( int y = 0; y < 3; ++y ) {
    y != 0 && os << "-+-+-\n";
    os << b(0,y) << "|" << b(1,y) << "|" << b(2,y) << "\n";
  }
  return os;
}


class player
{
  static int player_id_;
  int id_;

  protected:
  player() : id_(++player_id_) {}
  virtual ~player();

  public:
  int id()const { return id_; }

  void operator()(board& b) const
  { next(b); }


  private:
  virtual void
    next(board& b)
  const = 0;
};
int player::player_id_ = 0;
player::~player() {}

class rand_player
: public player
{
  void next(board& b) const;
};
void
rand_player::next(board& b)
  const
{
  while (1) {
    int x = std::rand() % 3;
    int y = std::rand() % 3;
    if ( b(x,y) == 0 ) {
      b(x,y) = id();
      break;
    }
  }
}

struct board_checker
{
  int operator()(board& b) const;
};

int
board_checker::operator()(board& b)
  const
{
  bool draw=true;
  for (int x = 0; draw && x < 3; ++x )
    for (int y = 0; draw && y < 3; ++y )
      draw = b(x,y) != 0;
  if ( draw )
    return -1;
  
  if ( int id = b(1,1) )
    if ((b(0,0) == id && b(2,2) == id ) ||
        (b(0,2) == id && b(2,0) == id) ||
        (b(0,1) == id && b(2,1) == id) ||
        (b(1,0) == id && b(1,2) == id) )
      return id;
  if ( int id = b(0,0) )
    if ((b(0,1) == id && b(0,2) == id) ||
        (b(1,0) == id && b(2,0) == id) )
      return id;
  if ( int id = b(2,2) )
    if ((b(1,2) == id && b(0,2) == id) ||
        (b(2,1) == id && b(2,0) == id) )
      return id;

  // not finish
  return 0;
}

int main()
{
  std::srand(std::time(0));
  rand_player p1, p2;
  player *p[] = { &p1, &p2 };
  board b;
  board_checker bc;
  std::map<int, unsigned int> st;
  const std::size_t max = 10000
  for ( std::size_t i = 0; i < max; ++i ) {
    b.reset();
    int count = 0;
    while ( 1 ) {
      (*p[count++ % 2])(b);
//      std::cout << " i = " << i << " step = " << count << "\n" << b;
      if ( count >= 4 )
        if ( int result = bc(b) ) {
          st[result]++;
          break;
        }
    }
  }

  std::cout << "player " << p1.id() << " won : " << st[p1.id()]
    << "(" << st[p1.id()]/static_cast<double>(max) << ")\n";
  std::cout << "player " << p2.id() << " won : " << st[p2.id()]
    << "(" << st[p2.id()]/static_cast<double>(max) << ")\n";
  std::cout << "draw : " << st[-1]
    << "(" << st[-1]/static_cast<double>(max) << ")\n";


  return 0;
}
