next up previous
Next: Java Implementation Up: Von C++ zu Java Previous: Ein vergleichendes Beispiel

C++ Implementation

FourInaRow.h

// Aus: Michael A. Smith, Object-Oriented Software in C++, 
// Chapman & Hall, London 1995, Seite 98ff

#ifndef __FOURINAROW_H__
#define __FOURINAROW_H__ 

#include <iostream.h>

#ifdef FALSE
#undef FALSE 
#endif

#ifdef TRUE
#undef TRUE 
#endif

const int MAXROW = 9; // Maximun Rows
const int MAXCOLUMN = 9; // Maximum Columns

enum Boolean {FALSE, TRUE};
enum BoardState {DRAW, WIN, PLAY};

const int STONES_IN_A_WIN_LINE = 4;
const int NO_OF_PLAYERS = 2;
const int DEF_ROWS = 6; // Default number of rows
const int DEF_COLUMNS = 7; // Default number of columns

const char INVISIBLE = ' ';
const int SELECT_REPRESENTATION = 1;
#endif

Board.h

#ifndef __BOARD_H__
#define __BOARD_H__ 

#include "FourInaRow.h"
#include "Cell.h"

class Board 
{
public:
  Board(const int rows=DEF_ROWS, const int columns=DEF_COLUMNS);
  void reset(const int rows=DEF_ROWS, const int columns=DEF_COLUMNS);
  void drop_in_column(const int, const Counter);
  Boolean move_ok_for_column(const int) const;
  void display(void) const;
  BoardState situation(void) const;
protected:
  int check_for_a_win(const int, const int, const int, const char) const;
  void add_counter_to_board(const int, const Counter);
  Boolean is_there_a_win(void) const;
private:
  Cell the_grid[MAXROW][MAXCOLUMN]; // Board played on
  int the_height[MAXCOLUMN]; // Current height of counters col
  int the_row_size;
  int the_column_size; // Size of playing area
  int the_last_col;
  int the_last_row; // Last counter placed
  int the_no_empty_cells; // No. of cells still empty
};

#endif

Board.cc

#include "Board.h"

Board::Board(const int rows, const int columns)
{
  reset(rows, columns);
}

void Board::reset(const int rows, const int columns)
{
  the_row_size = rows; the_column_size = columns;
  for (int i=0; i<the_column_size; i++)
  {
    for (int j=0; j<the_row_size; j++)
    {
      the_grid[j][i].drop(Counter(INVISIBLE));
    }
    the_height[i] = 0;
  }
  the_last_row = the_last_col = 0;
  the_no_empty_cells = rows * columns;
}

void Board::drop_in_column(const int column, const Counter c)
{
  the_last_col = column; the_last_row = the_height[column];
  add_counter_to_board(column, c);
}

Boolean Board::move_ok_for_column(const int column) const
{
  if (column >= 0 && column < the_column_size)
  {
    if (the_height[column] < the_row_size)
    {
      return TRUE;
    }
  }
  return FALSE;
}

void Board::add_counter_to_board(const int column, const Counter players_counter)
{
  the_grid[the_height[column] ][column].drop(players_counter);
  the_height[column]++;
  the_no_empty_cells--;
}

BoardState Board::situation(void) const
{
  if (is_there_a_win() == TRUE)
  {
    return WIN;
  }
  if (the_no_empty_cells == 0)
  {
    return DRAW;
  }
  return PLAY;
}

Boolean Board::is_there_a_win(void) const
{
  char stone = the_grid[the_last_row][the_last_col].holds();
  for (int dir=1; dir <= 4; dir++)
  {
    int stones_in_a_line = 
      check_for_a_win(dir, the_last_row, the_last_col, stone) + 
      check_for_a_win(dir+4, the_last_row, the_last_col, stone) - 1;
    if ( stones_in_a_line >= STONES_IN_A_WIN_LINE )
    {
      return TRUE;
    }
  }
  return FALSE;
}

int Board::check_for_a_win(const int dir, const int x_coord, 
	const int y_coord, const char counter) const
{
  int x = x_coord; int y = y_coord;
  if ( (x >= 0) && (x < the_row_size) &&
       (y >= 0) && (y < the_column_size) &&
       (the_grid[x][y].holds() == counter) )
  {
    switch(dir)
    {
    case 1:      y++; break;
    case 2: x++; y++; break;
    case 3: x++;      break;
    case 4: x++; y--; break;

    case 5:      y--; break;
    case 6: x--; y--; break;
    case 7: x--;      break;
    case 8: x--; y++; break;

    default: cerr << "internal error 1\n";
    }
    return 1 + check_for_a_win(dir, x, y, counter);
  }
  else 
  {
    return 0;
  }
}


void Board::display(void) const
{
  cout << " ";
  for (int j=1; j<=the_column_size; j++)
    cout << j << "   ";
  cout << '\n';

  for (int i=the_row_size - 1; i>=0; i--)
  {
    cout << "| ";
    for (int j=0; j<the_column_size; j++)
    {
      the_grid[i][j].display();
      cout << " | ";
    }
    cout << '\n';
  }

  for (int k=the_row_size; k>=0; k--) cout << "----";
  cout << "-\n\n";
}


Cell.h

#ifndef __CELL_H__
#define __CELL_H__ 

#include "FourInaRow.h"
#include "Counter.h"

class Cell
{
public:
  Cell();
  void clear(void); // Clear the cell
  void drop(const Counter c); // Drop a counter into the cell
  char holds(void) const; // Return the counters colour
  void display(void) const; // Display the contents of a cell
private:
  Counter the_counter;
};
  
#endif

Cell.cc

#include "Cell.h"

Cell::Cell()
{
  the_counter = Counter(INVISIBLE);
}

void Cell::clear(void)
{
  the_counter = Counter(INVISIBLE);
}

void Cell::drop(const Counter c)
{
  the_counter = c;
}

char Cell::holds(void) const
{
  return the_counter.colour();
}

void Cell::display(void) const
{
  the_counter.display();
}

Counter.h

#ifndef __COUNTER_H__
#define __COUNTER_H__

#include "FourInaRow.h"

class Counter
{
public:
  static void prelude(void);
  Counter();
  Counter(const char);
  Counter(const int);
  char colour(void) const; // Returns the colour of a counter
  void display(void) const; // Display the counter
private:
  static int the_counter_no; // Which colour to allocate next
  char the_colour; // The colour of the counter
};

#endif

Counter.cc

#include "Counter.h"

int Counter::the_counter_no;

void Counter::prelude(void)
{
  the_counter_no = 0;
}

Counter::Counter()
{
  the_colour = INVISIBLE;
}

Counter::Counter(const int dummy)
{
  the_colour = "xo*+#"[the_counter_no++];
}

Counter::Counter(const char representation)
{
  the_colour = representation;
}

char Counter::colour(void) const
{
  return the_colour;
}

void Counter::display(void) const
{
  cout << the_colour;
}

Player.h

// Aus: Michael A. Smith, Object-Oriented Software in C++, 
// Chapman & Hall, London 1995, Seite 98ff
#ifndef __PLAYER_H__
#define __PLAYER_H__

#include "FourInaRow.h"
#include "Counter.h"

class Player
{
public:
  Player();
  int get_move(const Boolean) const; // Ask for a move
  Counter get_counter(void) const; // Get a counter
  void announce(const BoardState) const; // Announce win/draw
private:
  Counter the_players_counter;
};

#endif

Player.cc

#include "Player.h"

Player::Player()
{
  the_players_counter = Counter(SELECT_REPRESENTATION);
}

int Player::get_move(const Boolean first) const
{
  int move;
  if (first != TRUE)
    cout << "Error Invalid choice" << "\n";
  cout << "Move for player ";
  cout << the_players_counter.colour() << " is ";
  cin >> move;
  return move-1;
}

Counter Player::get_counter(void) const
{
  return the_players_counter;
}

void Player::announce(const BoardState what) const
{
  cout << "Player " << the_players_counter.colour();
  switch(what)
  {
  case WIN:
    cout << " wins\n";
    break;
  case DRAW:
    cout << " has filled the board\n";
    break;
  }
}

main.cc

#include "Board.h"
#include "Player.h"

void play()
{
  Board c_4; // The playing board
  Player contestant[NO_OF_PLAYERS]; // No of players
  BoardState state = PLAY; // Contestants can Play
  int no = 0; // First contestand

  c_4.display(); // display the board
  while (state == PLAY)
  {
    int move = contestant[no].get_move(TRUE);
    while(c_4.move_ok_for_column(move) == FALSE)
    {
      move = contestant[no].get_move(FALSE);
    }
    c_4.drop_in_column(move, contestant[no].get_counter());

    c_4.display();
    state = c_4.situation();
    if (state == PLAY)
      no = (no+1)%NO_OF_PLAYERS;
    else 
      contestant[no].announce(state); // The result
  }
}

main()
{
  Counter::prelude();
  play();
}

Makefile

# defines
CC= g++
CFLAGS= -g -Wall
CXX= g++
CXXFLAGS= -g -Wall
LD= g++
LIBS= -lm
BIN= four

# Programs
SRC=   Board.cc    Cell.cc     Counter.cc  Player.cc   main.cc 
OBJS=  Board.o     Cell.o      Counter.o   Player.o    main.o

all:    ${BIN}

# dependencies
Board.o: Board.cc Board.h FourInaRow.h
Cell.o: Cell.cc Cell.h FourInaRow.h
Counter.o: Counter.cc Counter.h FourInaRow.h
Player.o: Player.cc Player.h FourInaRow.h
main.o: main.cc
 
# linking
${BIN}: ${OBJS} ${SRC}
		${LD}   ${OBJS} -o ${BIN} ${LIBS}

clean:
	rm -f *.o *~ *.bak ${BIN} *.aux *.log *.dvi


next up previous
Next: C++ Implementation 2/11 Up: Von C++ zu Java Previous: Ein vergleichendes Beispiel

© 1997 Gottfried Rudorfer, C++-AG, Lehrveranstaltungen, Abteilung für Angewandte Informatik, Wirtschaftsuniversität Wien, 3/19/1998