Go back to Richel Bilderbeek's homepage.

Go back to Richel Bilderbeek's C++ page.

 

 

 

 

 

(C++) Reversi Console source code (version 1.0)

 

Reversi Console version 1.0 source code.

 

Operating system: Windows XP

IDE: C++ Builder 6.0 Enterprise Edition

Project type: GUI application

Compiler: supplied with C++ Builder 6.0 Enterprise Edition

Libraries used:

 

 

 

 

 

UnitReversi.cpp

 

//---------------------------------------------------------------------------
/*
    Reversi, a simple board game
    Copyright (C) 2007  Richel Bilderbeek

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
//---------------------------------------------------------------------------
// From http://www.richelbilderbeek.nl
//---------------------------------------------------------------------------
#pragma hdrstop

#include "UnitReversi.h"
//---------------------------------------------------------------------------
#include <cassert>
//---------------------------------------------------------------------------
Reversi::Reversi(const int size)
  : mBoard(size,std::vector<Square>(size,empty))
{
  assert( size > 0);
  assert( mBoard.size() == mBoard[0].size() );

  const int x = size / 2 - 1;
  const int y = size / 2 - 1;
  SetSquare(x  ,y  ,player1);
  SetSquare(x+1,y  ,player2);
  SetSquare(x  ,y+1,player2);
  SetSquare(x+1,y+1,player1);
}
//---------------------------------------------------------------------------
const std::vector<std::vector<Square> >& Reversi::GetBoard() const
{
  return mBoard;
}
//---------------------------------------------------------------------------
const Square Reversi::GetSquare(const int x, const int y) const
{
  return GetSquareXy(mBoard,x,y);
}
//---------------------------------------------------------------------------
//Simply sets a square
void Reversi::SetSquare(const int x, const int y, const Square player)
{
  assert(player != empty);

  mBoard[y][x] = player;

  assert(GetSquare(x,y)==player);
}
//---------------------------------------------------------------------------
//Do a complete move
void Reversi::DoMove(const int x, const int y, const Square player)
{
  assert(IsValidMove(x,y,player)==true || "Invalid move!");

  if (IsValidMoveUp(       x,y,player) == true) DoMoveUp(       x  ,y-1,player);
  if (IsValidMoveUpLeft(   x,y,player) == true) DoMoveUpLeft(   x-1,y-1,player);
  if (IsValidMoveLeft(     x,y,player) == true) DoMoveLeft(     x-1,y  ,player);
  if (IsValidMoveDownLeft( x,y,player) == true) DoMoveDownLeft( x-1,y+1,player);
  if (IsValidMoveDown(     x,y,player) == true) DoMoveDown(     x  ,y+1,player);
  if (IsValidMoveDownRight(x,y,player) == true) DoMoveDownRight(x+1,y+1,player);
  if (IsValidMoveRight(    x,y,player) == true) DoMoveRight(    x+1,y  ,player);
  if (IsValidMoveUpRight(  x,y,player) == true) DoMoveUpRight(  x+1,y-1,player);
  SetSquare(x,y,player);
}
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
const bool Reversi::IsValidMove(const int x, const int y, const Square player) const
{
  if (IsValidMoveUp(       x,y,player)==true) return true;
  if (IsValidMoveUpLeft(   x,y,player)==true) return true;
  if (IsValidMoveLeft(     x,y,player)==true) return true;
  if (IsValidMoveDownLeft( x,y,player)==true) return true;
  if (IsValidMoveDown(     x,y,player)==true) return true;
  if (IsValidMoveDownRight(x,y,player)==true) return true;
  if (IsValidMoveRight(    x,y,player)==true) return true;
  if (IsValidMoveUpRight(  x,y,player)==true) return true;
  return false;
}
//---------------------------------------------------------------------------
const bool Reversi::IsValidMoveUp(const int x, const int y, const Square player) const
{
  int b = y - 1;
  if (b < 1) return false;
  if (GetSquare(x,b) != GetOtherPlayer(player)) return false;
  while (b > 0)
  {
    b--;
    if (GetSquare(x,b) == player) return true;
    if (GetSquare(x,b) == empty) return false;
  }
  return false;
}
//---------------------------------------------------------------------------
const bool Reversi::IsValidMoveUpLeft(const int x, const int y, const Square player) const
{
  int a = x - 1;
  int b = y - 1;
  if (a < 1 || b < 1) return false;
  if (GetSquare(a,b) != GetOtherPlayer(player)) return false;
  while (a > 0 && b > 0)
  {
    a--;
    b--;
    if (GetSquare(a,b) == player) return true;
    if (GetSquare(a,b) == empty) return false;
  }
  return false;
}
//---------------------------------------------------------------------------
const bool Reversi::IsValidMoveLeft(const int x, const int y, const Square player) const
{
  int a = x - 1;
  if (a < 1) return false;
  if (GetSquare(a,y) != GetOtherPlayer(player)) return false;
  while (a > 0)
  {
    a--;
    if (GetSquare(a,y) == player) return true;
    if (GetSquare(a,y) == empty) return false;
  }
  return false;
}
//---------------------------------------------------------------------------
const bool Reversi::IsValidMoveDownLeft(const int x, const int y, const Square player) const
{
  const int size = mBoard.size();
  int a = x - 1;
  int b = y + 1;

  if (a < 1) return false;
  if (b > size -1 ) return false;
  if (GetSquare(a,b) != GetOtherPlayer(player)) return false;
  while (a > 0 && b < size - 1)
  {
    a--;
    b++;
    if (GetSquare(a,b) == player) return true;
    if (GetSquare(a,b) == empty) return false;
  }
  return false;
}
//---------------------------------------------------------------------------
const bool Reversi::IsValidMoveDown(const int x, const int y, const Square player) const
{
  const int size = mBoard.size();
  int b = y + 1;
  if (b > size -1 ) return false;
  if (GetSquare(x,b) != GetOtherPlayer(player)) return false;
  while (b < size - 1)
  {
    b++;
    if (GetSquare(x,b) == player) return true;
    if (GetSquare(x,b) == empty ) return false;
  }
  return false;
}
//---------------------------------------------------------------------------
const bool Reversi::IsValidMoveDownRight(const int x, const int y, const Square player) const
{
  const int size = mBoard.size();
  int a = x + 1;
  int b = y + 1;
  if (a > size - 1) return false;
  if (b > size -1 ) return false;
  if (GetSquare(a,b) != GetOtherPlayer(player)) return false;
  while (a < size - 1 && b < size - 1)
  {
    b++;
    a++;
    if (GetSquare(a,b) == player) return true;
    if (GetSquare(a,b) == empty ) return false;
  }
  return false;
}
//---------------------------------------------------------------------------
const bool Reversi::IsValidMoveRight(const int x, const int y, const Square player) const
{
  const int size = mBoard.size();
  int a = x + 1;
  if (a > size - 1) return false;
  if (GetSquare(a,y) != GetOtherPlayer(player)) return false;
  while (a < size - 1)
  {
    a++;
    if (GetSquare(a,y) == player) return true;
    if (GetSquare(a,y) == empty) return false;
  }
  return false;
}
//---------------------------------------------------------------------------
const bool Reversi::IsValidMoveUpRight(const int x, const int y, const Square player) const
{
  const int size = mBoard.size();
  int a = x + 1;
  int b = y - 1;
  if (a > size - 1) return false;
  if (b < 1) return false;
  if (GetSquare(a,b) != GetOtherPlayer(player)) return false;
  while (a < size - 1 && b > 0)
  {
    a++;
    b--;
    if (GetSquare(a,b) == player) return true;
    if (GetSquare(a,b) == empty) return false;
  }
  return false;
}
//---------------------------------------------------------------------------
const std::vector< std::pair<int,int> > Reversi::GetValidMoves(const Square player) const
{
  const int size = mBoard.size();
  std::vector< std::pair<int,int> > v;
  for (int y=0; y!=size; ++y)
  {
    for (int x=0; x!=size; ++x)
    {
      if (IsValidMove(x,y,player)==true)
      {
        v.push_back( std::make_pair(x,y) );
      }
    }
  }
  return v;
}
//---------------------------------------------------------------------------
void Reversi::DoMoveUp(const int x, int y, const Square player)
{
  while ( GetSquare(x,y) == GetOtherPlayer(player) )
  {
    SetSquare(x,y,player);
    --y;
  }
}
//---------------------------------------------------------------------------
void Reversi::DoMoveUpLeft(int x, int y, const Square player)
{
  while ( GetSquare(x,y) == GetOtherPlayer(player) )
  {
    SetSquare(x,y,player);
    --y;
    --x;
  }
}
//---------------------------------------------------------------------------
void Reversi::DoMoveLeft(int x, const int y, const Square player)
{
  while ( GetSquare(x,y) == GetOtherPlayer(player) )
  {
    SetSquare(x,y,player);
    --x;
  }

}
//---------------------------------------------------------------------------
void Reversi::DoMoveDownLeft(int x, int y, const Square player)
{
  while ( GetSquare(x,y) == GetOtherPlayer(player) )
  {
    SetSquare(x,y,player);
    ++y;
    --x;
  }
}
//---------------------------------------------------------------------------
void Reversi::DoMoveDown(const int x, int y, const Square player)
{
  while ( GetSquare(x,y) == GetOtherPlayer(player) )
  {
    SetSquare(x,y,player);
    ++y;
  }
}
//---------------------------------------------------------------------------
void Reversi::DoMoveDownRight(int x, int y, const Square player)
{
  while ( GetSquare(x,y) == GetOtherPlayer(player) )
  {
    SetSquare(x,y,player);
    ++y;
    ++x;
  }
}
//---------------------------------------------------------------------------
void Reversi::DoMoveRight(int x, const int y, const Square player)
{
  while ( GetSquare(x,y) == GetOtherPlayer(player) )
  {
    SetSquare(x,y,player);
    ++x;
  }
}
//---------------------------------------------------------------------------
void Reversi::DoMoveUpRight(int x, int y, const Square player)
{
  while ( GetSquare(x,y) == GetOtherPlayer(player) )
  {
    SetSquare(x,y,player);
    --y;
    ++x;
  }
}
//---------------------------------------------------------------------------
const int Reversi::GetSize() const
{
  return mBoard.size();
}
//---------------------------------------------------------------------------
const int Reversi::Count(const Square player) const
{
  const int size = GetSize();

  int sum = 0;

  for (int y=0; y!=size; ++y)
  {
    for (int x=0; x!=size; ++x)
    {
      if (mBoard[x][y] == player) ++sum;
    }
  }
  return sum;
}
//---------------------------------------------------------------------------
const Square GetOtherPlayer(const Square player)
{
  switch (player)
  {
    case player1: return player2;
    case player2: return player1;
  }
  assert(!"Invalid player");
  return empty;
}
//---------------------------------------------------------------------------
const Square GetSquareXy(
  const std::vector<std::vector<Square> >& board,
  const int x, const int y)
{
  const int size = board.size();
  assert(x >= 0);
  assert(y >= 0);
  assert(x < size);
  assert(y < size);
  return board[y][x];
}
//---------------------------------------------------------------------------


#pragma package(smart_init)

 

 

 

 

 

UnitReversi.h

 

//---------------------------------------------------------------------------
/*
    Reversi, a simple board game
    Copyright (C) 2007  Richel Bilderbeek

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
//---------------------------------------------------------------------------
// From http://www.richelbilderbeek.nl
//---------------------------------------------------------------------------
#ifndef UnitReversiH
#define UnitReversiH
//---------------------------------------------------------------------------
#include <vector>
enum Square { empty, player1, player2 };
//---------------------------------------------------------------------------
struct Reversi
{
  Reversi(const int size);
  const std::vector<std::vector<Square> >& GetBoard() const;
  const Square GetSquare(const int x, const int y) const;
  void DoMove(const int x, const int y, const Square player);
  void SetSquare(const int x, const int y, const Square player);
  const bool IsValidMove(const int x, const int y, const Square player) const;
  const std::vector< std::pair<int,int> > GetValidMoves(const Square player) const;
  const int GetSize() const;
  const int Count(const Square player) const;

  private:
  std::vector<std::vector<Square> > mBoard;

  const bool IsValidMoveUp(const int x, const int y, const Square player) const;
  const bool IsValidMoveUpLeft(const int x, const int y, const Square player) const;
  const bool IsValidMoveLeft(const int x, const int y, const Square player) const;
  const bool IsValidMoveDownLeft(const int x, const int y, const Square player) const;
  const bool IsValidMoveDown(const int x, const int y, const Square player) const;
  const bool IsValidMoveDownRight(const int x, const int y, const Square player) const;
  const bool IsValidMoveRight(const int x, const int y, const Square player) const;
  const bool IsValidMoveUpRight(const int x, const int y, const Square player) const;

  void DoMoveUp(const int x, int y, const Square player);
  void DoMoveUpLeft(int x, int y, const Square player);
  void DoMoveLeft(int x, const int y, const Square player);
  void DoMoveDownLeft(int x, int y, const Square player);
  void DoMoveDown(const int x, int y, const Square player);
  void DoMoveDownRight(int x, int y, const Square player);
  void DoMoveRight(int x, const int y, const Square player);
  void DoMoveUpRight(int x, int y, const Square player);

};

const Square GetSquareXy(const std::vector<std::vector<Square> >& board, const int x, const int y);
const Square GetOtherPlayer(const Square player);

#endif

 

 

 

 

 

UnitReversiMain.cpp

 

//---------------------------------------------------------------------------
/*
    Reversi Console, a simple board game
    Copyright (C) 2008  Richel Bilderbeek

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
//---------------------------------------------------------------------------
// From http://www.richelbilderbeek.nl
//---------------------------------------------------------------------------
#include <vector>
#include <numeric>
#include <algorithm>
#include <iostream>
#include <cassert>
#include <iterator>
#include <memory>
#include <sstream>
#include "UnitReversi.h"
//---------------------------------------------------------------------------
std::ostream& operator<<(std::ostream& os, const Square s)
{
  switch (s)
  {
    case empty  : os << "."; break;
    case player1: os << "1"; break;
    case player2: os << "2"; break;
    default: assert(!"Should not get here"); break;
  }
  return os;
}
//---------------------------------------------------------------------------
std::ostream& operator<<(std::ostream& os, const Reversi& r)
{
  { //Show the indices horizontally
    const int size = r.GetSize();
    os << "  ";
    for (int i=0; i!=size; ++i)
    {
      os << (i%10);
    }
    os << std::endl;
    os << std::endl;
  }
  {
    int i = 0;
    const std::vector<std::vector<Square> >& board = r.GetBoard();
    const std::vector<std::vector<Square> >::const_iterator lastRow = board.end();
    for (std::vector<std::vector<Square> >::const_iterator row = board.begin();
      row!=lastRow;
      ++row, ++i)
    {
      os << (i%10) << " ";
      std::copy( (*row).begin(), (*row).end(),std::ostream_iterator<Square>(os,""));
      os << " " << (i%10) << '\n';
    }
  }

  { //Show the indices horizontally
    os << std::endl;
    os << "  ";
    const int size = r.GetSize();
    for (int i=0; i!=size; ++i)
    {
      os << i%10;
    }
    os << std::endl;
  }
  return os;
}
//---------------------------------------------------------------------------
//From http://www.richelbilderbeek.nl/CppIsInt.htm
//Checks whether a std::string can be converted to an integer.
//Returns true if possible, also returning this integer by referencing.
//Returns false otherwise, setting the referenced integer to zero.
const bool IsInt(const std::string& s, int& rInt)
{
  std::istringstream i(s);
  if (!(i >> rInt))
  {
    rInt = 0;
    return false;
  }
  return true;
}
//---------------------------------------------------------------------------
const std::string GetInput()
{
  std::string s;
  std::getline(std::cin,s,'\n');
  return s;
}
//---------------------------------------------------------------------------
//From http://www.richelbilderbeek.nl/CppSeperateString.htm
const std::vector<std::string> SeperateString(std::string input, const char seperator)
{
  assert(input.empty()==false);
  assert(input[0]!=seperator);
  assert(input[input.size()-1]!=seperator);

  std::vector<std::string> result;
  int pos = 0;
  while(pos<static_cast<int>(input.size()))
  {
    if (input[pos]==seperator)
    {
      const std::string found = input.substr(0,pos);
      result.push_back(found);
      input = input.substr(pos+1,input.size()-pos);
      pos = 0;
    }
    ++pos;
  }
  result.push_back(input);
  return result;
}
//---------------------------------------------------------------------------
const bool IsCoordinat(const std::string& input, std::pair<int,int>& coordinat)
{
  if ( std::count(input.begin(), input.end(), ',') != 1) return false;
  if ( *(input.begin()) == ',' || *(input.end() - 1) == ',') return false;
  const std::string::const_iterator i = std::find(input.begin(), input.end(), ',');
  assert(i != input.end() ); //Comma must be in! Checked above!

  const std::vector<std::string> v(SeperateString(input,','));
  if (v.size() != 2) return false;
  if (IsInt(v[0],coordinat.first)==false) return false;
  if (IsInt(v[1],coordinat.second)==false) return false;
 return true;

}
//---------------------------------------------------------------------------
const int AskUserForBoardSize()
{
  //Get the board's size
  while (1)
  {
    std::cout << "Please enter the size of the reversi board" << std::endl;
    const std::string input = GetInput();
    int size = -1;
    if ( IsInt(input,size) == false)
    {
      std::cout << "Please enter an integer value. " << std::endl;
      continue;
    }
    if ( size < 4)
    {
      std::cout << "Please enter an integer value bigger then 4. " << std::endl;
      continue;
    }
    if ( size > 16)
    {
      std::cout << "Please enter an integer value less then 16. " << std::endl;
      continue;
    }
    return size;
  }
}
//---------------------------------------------------------------------------
int main()
{
  std::cout
    << "***********" << std::endl
    << "* REVERSI *" << std::endl
    << "***********" << std::endl
    << std::endl;
    
  Reversi r(AskUserForBoardSize());
  Square player = player1;

  while (1)
  {
    std::cout
      << "\nThe board's current state: " << std::endl
      << r << std::endl
      << "It is player " << player << "'s turn."
      << "Please enter a coordinat, 'p' to pass or 'q' to quit"
      << std::endl;

    const std::string input = GetInput();

    if (input == "q")
    {
      //Quit
      return 0;
    }
    if (input == "p")
    {
      //Pass
      player = (player == player1? player2 : player1);
      continue;
    }


    std::pair<int,int> coordinat;
    const bool isValidCoordinat = IsCoordinat(input, coordinat);

    if (isValidCoordinat == false)
    {
      std::cout
        << "Please enter a correctly formatted coordinat."
        << "\nFor example:  1,2  " << std::endl;
      continue;
    }
    if (r.IsValidMove(coordinat.first, coordinat.second, player) == false)
    {
      std::cout
        << "Please enter a valid coordinat." << std::endl;
      continue;
    }
    //Actually do the move
    r.DoMove(coordinat.first, coordinat.second, player);

    //Check if the game has ended
    if (r.Count(empty) == 0)
    {
      //No empty squares
      const int n1 = r.Count(player1);
      const int n2 = r.Count(player2);
      std::cout << "The game has ended." << std::endl
        << "Player 1 conquered " << n1 << " squares." << std::endl
        << "Player 2 conquered " << n2 << " squares." << std::endl
        << "The winner is player " << (n1 > n2 ? "1" : "2") << std::endl
        << "Congratulations!" << std::endl
        << std::endl
        << "Press any key to quit. " << std::endl;

      std::cin.get();
      return 0; //Terminate the program
    }

    //Check if other player can actually do a move
    if (r.GetValidMoves(player).empty()==true)
    {
      std::cout << "Too bad! Player " << player << " is unabled to do a valid move!";
      player = (player == player1 ? player2 : player1);
      std::cout << "\nThe next turn again goes to player " << player << "!" << std::endl;
      continue;
    }

    player = (player == player1 ? player2 : player1);
  }
}
//---------------------------------------------------------------------------

 

 

 

 

 

 

 

 

 

 

Go back to Richel Bilderbeek's C++ page.

Go back to Richel Bilderbeek's homepage.

 

Valid XHTML 1.0 Strict