mirror of
https://github.com/caperren/school_archives.git
synced 2025-11-10 06:01:13 +00:00
Added missing classes from final year at OSU
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
#include <iostream>
|
||||
#include <assert.h>
|
||||
#include "Board.h"
|
||||
|
||||
void Board::delete_grid() {
|
||||
for (int c = 0; c < num_cols; c++) {
|
||||
delete[] grid[c];
|
||||
}
|
||||
delete[] grid;
|
||||
}
|
||||
|
||||
Board::Board(int cols, int rows) :
|
||||
num_cols(cols), num_rows(rows) {
|
||||
grid = new char*[num_cols];
|
||||
for (int c = 0; c < num_cols; c++) {
|
||||
grid[c] = new char[num_rows];
|
||||
for (int r = 0; r < num_rows; r++) {
|
||||
grid[c][r] = EMPTY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Board::Board(const Board& other) {
|
||||
num_cols = other.num_cols;
|
||||
num_rows = other.num_rows;
|
||||
grid = new char*[num_cols];
|
||||
for (int c = 0; c < num_cols; c++) {
|
||||
grid[c] = new char[num_rows];
|
||||
for (int r = 0; r < num_rows; r++) {
|
||||
grid[c][r] = other.grid[c][r];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Board& Board::operator=(const Board& rhs) {
|
||||
if (this == &rhs) {
|
||||
return *this;
|
||||
} else {
|
||||
num_cols = rhs.num_cols;
|
||||
num_rows = rhs.num_rows;
|
||||
if (grid != NULL) {
|
||||
delete_grid();
|
||||
}
|
||||
grid = new char*[num_cols];
|
||||
for (int c = 0; c < num_cols; c++) {
|
||||
grid[c] = new char[num_rows];
|
||||
for (int r = 0; r < num_rows; r++) {
|
||||
grid[c][r] = rhs.grid[c][r];
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
|
||||
Board::~Board() {
|
||||
delete_grid();
|
||||
}
|
||||
|
||||
char Board::get_cell(int col, int row) const {
|
||||
assert((col >= 0) && (col < num_cols));
|
||||
assert((row >= 0) && (row < num_rows));
|
||||
return grid[col][row];
|
||||
}
|
||||
|
||||
void Board::set_cell(int col, int row, char val) {
|
||||
assert((col >= 0) && (col < num_cols));
|
||||
assert((row >= 0) && (row < num_rows));
|
||||
grid[col][row] = val;
|
||||
}
|
||||
|
||||
bool Board::is_cell_empty(int col, int row) const {
|
||||
if (grid[col][row] == EMPTY) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool Board::is_in_bounds(int col, int row) const {
|
||||
if ((col >= 0) && (col < num_cols) && (row >= 0) && (row < num_rows)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void Board::display() const {
|
||||
for (int r = get_num_rows() - 1; r >= 0; r--) {
|
||||
std::cout << r << ":| ";
|
||||
for (int c = 0; c < get_num_cols(); c++) {
|
||||
std::cout << get_cell(c, r) << " ";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
std::cout << " -";
|
||||
for (int c = 0; c < get_num_cols(); c++) {
|
||||
std::cout << "--";
|
||||
}
|
||||
std::cout << "\n";
|
||||
std::cout << " ";
|
||||
for (int c = 0; c < get_num_cols(); c++) {
|
||||
std::cout << c << " ";
|
||||
}
|
||||
std::cout << "\n\n";
|
||||
}
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
/**
|
||||
* Board class
|
||||
*/
|
||||
|
||||
#ifndef BOARD_H
|
||||
#define BOARD_H
|
||||
|
||||
#define EMPTY '.'
|
||||
|
||||
/** Directions enum for the Othello Board */
|
||||
enum Direction {N,NE,E,SE,S,SW,W,NW};
|
||||
|
||||
/**
|
||||
* This is a generic board class that serves as a wrapper for a 2D array.
|
||||
* It will be used for board games like Othello, Tic-Tac-Toe and Connect 4.
|
||||
*/
|
||||
class Board {
|
||||
public:
|
||||
|
||||
/**
|
||||
* @param cols The number of columns in the board
|
||||
* @param rows The number of rows in the board
|
||||
* Constructor that creates a 2D board with the given number of columns
|
||||
* and rows
|
||||
*/
|
||||
Board(int cols, int rows);
|
||||
|
||||
/**
|
||||
* @param other A reference to the Board object being copied
|
||||
* This is the copy constructor for the Board class
|
||||
*/
|
||||
Board(const Board& other);
|
||||
|
||||
/**
|
||||
* Destructor for the Board class
|
||||
*/
|
||||
~Board();
|
||||
|
||||
/**
|
||||
* @param rhs The "right-hand side" for the assignment ie. the object
|
||||
* you are copying from.
|
||||
* @return Returns a reference to the "left-hand side" of the assignment ie.
|
||||
* the object the values are assigned to
|
||||
* Overloaded assignment operator for the Board class
|
||||
*/
|
||||
Board& operator=(const Board& rhs);
|
||||
|
||||
/**
|
||||
* @return Returns the number of rows in the board
|
||||
* An accessor that gets the number of rows in the board
|
||||
*/
|
||||
int get_num_rows() const { return num_rows; }
|
||||
|
||||
/**
|
||||
* @return Returns the number of columns in the board
|
||||
* An accessor to get the number of columns in the board
|
||||
*/
|
||||
int get_num_cols() const { return num_cols; }
|
||||
|
||||
/**
|
||||
* @param col The column of the cell you want to retrieve
|
||||
* @param row The row of the cell you want to retrieve
|
||||
* @return Returns the character at the specified cell
|
||||
* Returns the character at the specified column and row
|
||||
*/
|
||||
char get_cell(int col, int row) const;
|
||||
|
||||
/**
|
||||
* @param col The column of the cell you want to set
|
||||
* @param row The row of the cell you want to set
|
||||
* @param val The value you want to set the cell to
|
||||
* Sets the cell at the given row and column to the specified value
|
||||
*/
|
||||
void set_cell(int col, int row, char val);
|
||||
|
||||
/**
|
||||
* @param col The column of the cell you are checking
|
||||
* @param row The row of the cell you are checking
|
||||
* @return true if the cell is empty and false otherwise
|
||||
*/
|
||||
bool is_cell_empty(int col, int row) const;
|
||||
|
||||
/**
|
||||
* @param col The column value for the in-bounds check
|
||||
* @param row The row value for the in-bounds check
|
||||
* @return true if the column is >= 0 and < num_cols and if the row is >= 0 and < num_rows. Returns false otherwise.
|
||||
*/
|
||||
bool is_in_bounds(int col, int row) const;
|
||||
|
||||
/**
|
||||
* Prints the board to screen. Should probably have overloaded >> but oh well.
|
||||
*/
|
||||
void display() const;
|
||||
|
||||
protected:
|
||||
|
||||
/** The number of rows in the board */
|
||||
int num_rows;
|
||||
|
||||
/** The number of columns in the board */
|
||||
int num_cols;
|
||||
|
||||
/** A 2D array of chars representing the board */
|
||||
char** grid;
|
||||
|
||||
/**
|
||||
* Deletes the 2D array.
|
||||
*/
|
||||
void delete_grid();
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,137 @@
|
||||
#include <iostream>
|
||||
#include <cstring>
|
||||
#include <stdlib.h>
|
||||
#include "GameDriver.h"
|
||||
|
||||
GameDriver::GameDriver(char* p1type, char* p2type, int num_rows, int num_cols) {
|
||||
if( strcmp(p1type,"human") == 0 ) {
|
||||
p1 = new HumanPlayer('X');
|
||||
} else if( strcmp(p1type,"minimax") == 0 ) {
|
||||
p1 = new MinimaxPlayer('X');
|
||||
} else {
|
||||
std::cout << "Invalid type of player for player 1" << std::endl;
|
||||
}
|
||||
|
||||
if( strcmp(p2type,"human") == 0 ) {
|
||||
p2 = new HumanPlayer('O');
|
||||
} else if( strcmp(p2type,"minimax") == 0 ) {
|
||||
p2 = new MinimaxPlayer('O');
|
||||
} else {
|
||||
std::cout << "Invalid type of player for player 2" << std::endl;
|
||||
}
|
||||
|
||||
board = new OthelloBoard(num_rows, num_cols,p1->get_symbol(), p2->get_symbol());
|
||||
board->initialize();
|
||||
}
|
||||
|
||||
GameDriver::GameDriver(const GameDriver& other) {
|
||||
board = new OthelloBoard(*(other.board));
|
||||
p1 = other.p1->clone();
|
||||
p2 = other.p2->clone();
|
||||
}
|
||||
|
||||
GameDriver& GameDriver::operator=(const GameDriver& rhs) {
|
||||
if (this == &rhs) {
|
||||
return *this;
|
||||
} else {
|
||||
if( board != NULL ) {
|
||||
delete board;
|
||||
}
|
||||
board = new OthelloBoard(*(rhs.board));
|
||||
if( p1 != NULL ) {
|
||||
delete p1;
|
||||
p1 = rhs.p1->clone();
|
||||
}
|
||||
if( p2 != NULL ) {
|
||||
delete p2;
|
||||
p2 = rhs.p2->clone();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
GameDriver::~GameDriver() {
|
||||
delete board;
|
||||
delete p1;
|
||||
delete p2;
|
||||
}
|
||||
|
||||
void GameDriver::display() {
|
||||
std::cout << std::endl << "Player 1 (" << p1->get_symbol() << ") score: "
|
||||
<< board->count_score(p1->get_symbol()) << std::endl;
|
||||
std::cout << "Player 2 (" << p2->get_symbol() << ") score: "
|
||||
<< board->count_score(p2->get_symbol()) << std::endl << std::endl;
|
||||
|
||||
board->display();
|
||||
}
|
||||
|
||||
void GameDriver::process_move(Player* curr_player, Player* opponent) {
|
||||
int col = -1;
|
||||
int row = -1;
|
||||
bool invalid_move = true;
|
||||
while (invalid_move) {
|
||||
curr_player->get_move(board, col, row);
|
||||
if (!board->is_legal_move(col, row, curr_player->get_symbol())) {
|
||||
std::cout << "Invalid move.\n";
|
||||
continue;
|
||||
} else {
|
||||
std::cout << "Selected move: col = " << col << ", row = " << row << std::endl;
|
||||
board->play_move(col,row,curr_player->get_symbol());
|
||||
invalid_move = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GameDriver::run() {
|
||||
int toggle = 0;
|
||||
int cant_move_counter=0;
|
||||
Player* current = p1;
|
||||
Player* opponent = p2;
|
||||
|
||||
display();
|
||||
std::cout << "Player 1 (" << p1->get_symbol() << ") move:\n";
|
||||
while (1) {
|
||||
if( board->has_legal_moves_remaining(current->get_symbol())) {
|
||||
cant_move_counter = 0;
|
||||
process_move(current, opponent);
|
||||
display();
|
||||
} else {
|
||||
std::cout << "Can't move\n";
|
||||
if( cant_move_counter == 1 ) {
|
||||
// Both players can't move, game over
|
||||
break;
|
||||
} else {
|
||||
cant_move_counter++;
|
||||
}
|
||||
}
|
||||
|
||||
toggle = (toggle + 1) % 2;
|
||||
|
||||
if (toggle == 0) {
|
||||
current = p1;
|
||||
opponent = p2;
|
||||
std::cout << "Player 1 (" << p1->get_symbol() << ") move:\n";
|
||||
} else {
|
||||
current = p2;
|
||||
opponent = p1;
|
||||
std::cout << "Player 2 (" << p2->get_symbol() << ") move:\n";
|
||||
}
|
||||
}
|
||||
|
||||
if ( board->count_score(p1->get_symbol()) == board->count_score(p2->get_symbol())) {
|
||||
std::cout << "Tie game" << std::endl;
|
||||
} else if ( board->count_score(p1->get_symbol()) > board->count_score(p2->get_symbol())) {
|
||||
std::cout << "Player 1 wins" << std::endl;
|
||||
} else {
|
||||
std::cout << "Player 2 wins" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
if( argc != 3 ) {
|
||||
std::cout << "Usage: othello <player1 type> <player2 type>" << std::endl;
|
||||
exit(-1);
|
||||
}
|
||||
GameDriver* game = new GameDriver(argv[1],argv[2],4,4);
|
||||
game->run();
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
#ifndef GAMEDRIVER_H
|
||||
#define GAMEDRIVER_H
|
||||
|
||||
#include "OthelloBoard.h"
|
||||
#include "Player.h"
|
||||
#include "HumanPlayer.h"
|
||||
#include "MinimaxPlayer.h"
|
||||
|
||||
/**
|
||||
* This class represents the main driver for the game. The driver controls the turn-based behavior
|
||||
* of the game.
|
||||
*/
|
||||
class GameDriver {
|
||||
public:
|
||||
|
||||
/**
|
||||
* @param p1type A string (human or minimax) describing the type of Player1
|
||||
* @param p2type A string (human or minimax) describing the type of Player2
|
||||
* @param num_rows The number of rows in Othello
|
||||
* @param num_cols The number of columns in Othello
|
||||
* This is the constructor for the GameDriver
|
||||
*/
|
||||
GameDriver(char* p1type, char* p2type, int num_rows, int num_cols);
|
||||
|
||||
/**
|
||||
* @param other The GameDriver object you are copying from
|
||||
* Copy constructor for the GameDriver class
|
||||
*/
|
||||
GameDriver(const GameDriver& other);
|
||||
|
||||
/**
|
||||
* @param rhs The right-hand side of the assignment
|
||||
* @return The left-hand side of the assignment
|
||||
* Overloaded assignment operator for the GameDriver class.
|
||||
*/
|
||||
GameDriver& operator=(const GameDriver& rhs);
|
||||
|
||||
/**
|
||||
* Destructor for the GameDriver class
|
||||
*/
|
||||
virtual ~GameDriver();
|
||||
|
||||
/**
|
||||
* Runs the game and keeps track of the turns.
|
||||
*/
|
||||
void run();
|
||||
|
||||
/**
|
||||
* Displays the game.
|
||||
*/
|
||||
void display();
|
||||
|
||||
private:
|
||||
|
||||
/** Internal Othello board object */
|
||||
OthelloBoard* board;
|
||||
|
||||
/** Player 1 object */
|
||||
Player* p1;
|
||||
|
||||
/** Player 2 object */
|
||||
Player* p2;
|
||||
|
||||
/**
|
||||
* @param curr_player A pointer to the player that has the current move
|
||||
* @param opponent A pointer to the opponent for the player that has the current move
|
||||
* Handles actually making a move in the game.
|
||||
*/
|
||||
void process_move(Player* curr_player, Player* opponent);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,22 @@
|
||||
#include <iostream>
|
||||
#include "HumanPlayer.h"
|
||||
|
||||
HumanPlayer::HumanPlayer(char symb) : Player(symb) {
|
||||
|
||||
}
|
||||
|
||||
HumanPlayer::~HumanPlayer() {
|
||||
|
||||
}
|
||||
|
||||
void HumanPlayer::get_move(OthelloBoard* b, int& col, int& row) {
|
||||
std::cout << "Enter col: ";
|
||||
std::cin >> col;
|
||||
std::cout << "Enter row: ";
|
||||
std::cin >> row;
|
||||
}
|
||||
|
||||
HumanPlayer* HumanPlayer::clone() {
|
||||
HumanPlayer *result = new HumanPlayer(symbol);
|
||||
return result;
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
#ifndef HUMAN_PLAYER
|
||||
#define HUMAN_PLAYER
|
||||
|
||||
#include "Player.h"
|
||||
#include "OthelloBoard.h"
|
||||
|
||||
/**
|
||||
* This class represents a human player
|
||||
*/
|
||||
class HumanPlayer : public Player {
|
||||
public:
|
||||
|
||||
/**
|
||||
* @symb The symbol used for the human player's pieces
|
||||
* The constructor for the HumanPlayer class
|
||||
*/
|
||||
HumanPlayer(char symb);
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~HumanPlayer();
|
||||
|
||||
/**
|
||||
* @param b The current board for the game.
|
||||
* @param col Holds the return value for the column of the move
|
||||
* @param row Holds the return value for the row of the move
|
||||
* Obtains the (col,row) coordinates for the current move
|
||||
*/
|
||||
void get_move(OthelloBoard* b, int& col, int& row);
|
||||
|
||||
/**
|
||||
* @return A pointer to a copy of the HumanPlayer object
|
||||
* This is a virtual copy constructor
|
||||
*/
|
||||
HumanPlayer *clone();
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,14 @@
|
||||
CXX = g++
|
||||
CXXFLAGS = -std=c++0x
|
||||
SRCS = Board.cpp OthelloBoard.cpp Player.cpp HumanPlayer.cpp GameDriver.cpp MinimaxPlayer.cpp
|
||||
HEADERS = Board.h OthelloBoard.h Player.h HumanPlayer.h GameDriver.h MinimaxPlayer.h
|
||||
OBJS = Board.o OthelloBoard.o Player.o HumanPlayer.o GameDriver.o MinimaxPlayer.o
|
||||
|
||||
all: ${SRCS} ${HEADERS}
|
||||
${CXX} ${CXXFLAGS} ${SRCS} -o othello
|
||||
|
||||
${OBJS}: ${SRCS}
|
||||
${CXX} -c $(@:.o=.cpp)
|
||||
|
||||
clean:
|
||||
rm -f *.o othello
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* MinimaxPlayer.cpp
|
||||
*
|
||||
* Created on: Apr 17, 2015
|
||||
* Author: wong
|
||||
*/
|
||||
#include <iostream>
|
||||
#include <assert.h>
|
||||
#include "MinimaxPlayer.h"
|
||||
|
||||
using std::vector;
|
||||
|
||||
MinimaxPlayer::MinimaxPlayer(char symb) :
|
||||
Player(symb) {
|
||||
|
||||
}
|
||||
|
||||
MinimaxPlayer::~MinimaxPlayer() {
|
||||
|
||||
}
|
||||
|
||||
void MinimaxPlayer::get_move(OthelloBoard* b, int& col, int& row) {
|
||||
// To be filled in by you
|
||||
}
|
||||
|
||||
MinimaxPlayer* MinimaxPlayer::clone() {
|
||||
MinimaxPlayer* result = new MinimaxPlayer(symbol);
|
||||
return result;
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* MinimaxPlayer.h
|
||||
*
|
||||
* Created on: Apr 17, 2015
|
||||
* Author: wong
|
||||
*/
|
||||
|
||||
#ifndef MINIMAXPLAYER_H
|
||||
#define MINIMAXPLAYER_H
|
||||
|
||||
#include "OthelloBoard.h"
|
||||
#include "Player.h"
|
||||
#include <vector>
|
||||
|
||||
/**
|
||||
* This class represents an AI player that uses the Minimax algorithm to play the game
|
||||
* intelligently.
|
||||
*/
|
||||
class MinimaxPlayer : public Player {
|
||||
public:
|
||||
|
||||
/**
|
||||
* @param symb This is the symbol for the minimax player's pieces
|
||||
*/
|
||||
MinimaxPlayer(char symb);
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~MinimaxPlayer();
|
||||
|
||||
/**
|
||||
* @param b The board object for the current state of the board
|
||||
* @param col Holds the return value for the column of the move
|
||||
* @param row Holds the return value for the row of the move
|
||||
*/
|
||||
void get_move(OthelloBoard* b, int& col, int& row);
|
||||
|
||||
/**
|
||||
* @return A copy of the MinimaxPlayer object
|
||||
* This is a virtual copy constructor
|
||||
*/
|
||||
MinimaxPlayer* clone();
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,179 @@
|
||||
/*
|
||||
* OthelloBoard.cpp
|
||||
*
|
||||
* Created on: Apr 18, 2015
|
||||
* Author: wong
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include "OthelloBoard.h"
|
||||
|
||||
OthelloBoard::OthelloBoard(int cols, int rows, char p1_symb, char p2_symb) :
|
||||
Board(cols, rows), p1_symbol(p1_symb), p2_symbol(p2_symb) {
|
||||
|
||||
}
|
||||
|
||||
OthelloBoard::OthelloBoard(const OthelloBoard& other) :
|
||||
Board(other), p1_symbol(other.p1_symbol), p2_symbol(other.p2_symbol) {
|
||||
|
||||
}
|
||||
|
||||
OthelloBoard::~OthelloBoard() {
|
||||
|
||||
}
|
||||
|
||||
void OthelloBoard::initialize() {
|
||||
set_cell(num_cols / 2 - 1, num_rows / 2 - 1, p1_symbol);
|
||||
set_cell(num_cols / 2, num_rows / 2, p1_symbol);
|
||||
set_cell(num_cols / 2 - 1, num_rows / 2, p2_symbol);
|
||||
set_cell(num_cols / 2, num_rows / 2 - 1, p2_symbol);
|
||||
|
||||
|
||||
}
|
||||
|
||||
OthelloBoard& OthelloBoard::operator=(const OthelloBoard& rhs) {
|
||||
Board::operator=(rhs);
|
||||
p1_symbol = rhs.p1_symbol;
|
||||
p2_symbol = rhs.p2_symbol;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void OthelloBoard::set_coords_in_direction(int col, int row, int& next_col,
|
||||
int& next_row, int dir) const {
|
||||
switch (dir) {
|
||||
case N:
|
||||
next_col = col;
|
||||
next_row = row + 1;
|
||||
break;
|
||||
case NE:
|
||||
next_col = col + 1;
|
||||
next_row = row + 1;
|
||||
break;
|
||||
case E:
|
||||
next_col = col + 1;
|
||||
next_row = row;
|
||||
break;
|
||||
case SE:
|
||||
next_col = col + 1;
|
||||
next_row = row - 1;
|
||||
break;
|
||||
case S:
|
||||
next_col = col;
|
||||
next_row = row - 1;
|
||||
break;
|
||||
case SW:
|
||||
next_col = col - 1;
|
||||
next_row = row - 1;
|
||||
break;
|
||||
case W:
|
||||
next_col = col - 1;
|
||||
next_row = row;
|
||||
break;
|
||||
case NW:
|
||||
next_col = col - 1;
|
||||
next_row = row + 1;
|
||||
break;
|
||||
default:
|
||||
assert("Invalid direction");
|
||||
}
|
||||
}
|
||||
|
||||
bool OthelloBoard::check_endpoint(int col, int row, char symbol, int dir,
|
||||
bool match_symbol) const {
|
||||
int next_row = -1;
|
||||
int next_col = -1;
|
||||
|
||||
if (!is_in_bounds(col, row) || is_cell_empty(col, row)) {
|
||||
return false;
|
||||
} else {
|
||||
if (match_symbol) {
|
||||
if (get_cell(col, row) == symbol) {
|
||||
return true;
|
||||
} else {
|
||||
set_coords_in_direction(col, row, next_col, next_row, dir);
|
||||
return check_endpoint(next_col, next_row, symbol, dir,
|
||||
match_symbol);
|
||||
}
|
||||
} else {
|
||||
if (get_cell(col, row) == symbol) {
|
||||
return false;
|
||||
} else {
|
||||
set_coords_in_direction(col, row, next_col, next_row, dir);
|
||||
return check_endpoint(next_col, next_row, symbol, dir,
|
||||
!match_symbol);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool OthelloBoard::is_legal_move(int col, int row, char symbol) const {
|
||||
bool result = false;
|
||||
int next_row = -1;
|
||||
int next_col = -1;
|
||||
if (!is_in_bounds(col, row) || !is_cell_empty(col, row)) {
|
||||
return result;
|
||||
}
|
||||
for (int d = N; d <= NW; d++) {
|
||||
set_coords_in_direction(col, row, next_col, next_row, d);
|
||||
if (check_endpoint(next_col, next_row, symbol, d, false)) {
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int OthelloBoard::flip_pieces_helper(int col, int row, char symbol, int dir) {
|
||||
int next_row = -1;
|
||||
int next_col = -1;
|
||||
|
||||
if (get_cell(col, row) == symbol) {
|
||||
return 0;
|
||||
} else {
|
||||
set_cell(col, row, symbol);
|
||||
set_coords_in_direction(col, row, next_col, next_row, dir);
|
||||
return 1 + flip_pieces_helper(next_col, next_row, symbol, dir);
|
||||
}
|
||||
}
|
||||
|
||||
int OthelloBoard::flip_pieces(int col, int row, char symbol) {
|
||||
int pieces_flipped = 0;
|
||||
int next_row = -1;
|
||||
int next_col = -1;
|
||||
|
||||
assert(is_in_bounds(col, row));
|
||||
for (int d = N; d <= NW; d++) {
|
||||
set_coords_in_direction(col, row, next_col, next_row, d);
|
||||
if (check_endpoint(next_col, next_row, symbol, d, false)) {
|
||||
pieces_flipped += flip_pieces_helper(next_col, next_row, symbol, d);
|
||||
}
|
||||
}
|
||||
return pieces_flipped;
|
||||
}
|
||||
|
||||
bool OthelloBoard::has_legal_moves_remaining(char symbol) const {
|
||||
for (int c = 0; c < num_cols; c++) {
|
||||
for (int r = 0; r < num_rows; r++) {
|
||||
if (is_cell_empty(c, r) && is_legal_move(c, r, symbol)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int OthelloBoard::count_score(char symbol) const {
|
||||
int score = 0;
|
||||
for (int c = 0; c < num_cols; c++) {
|
||||
for (int r = 0; r < num_rows; r++) {
|
||||
if (grid[c][r] == symbol) {
|
||||
score++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return score;
|
||||
}
|
||||
|
||||
void OthelloBoard::play_move(int col, int row, char symbol) {
|
||||
set_cell(col, row, symbol);
|
||||
flip_pieces(col, row, symbol);
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* OthelloBoard.h
|
||||
*
|
||||
* Created on: Apr 18, 2015
|
||||
* Author: wong
|
||||
*/
|
||||
|
||||
#ifndef OTHELLOBOARD_H_
|
||||
#define OTHELLOBOARD_H_
|
||||
|
||||
#include "Board.h"
|
||||
|
||||
/**
|
||||
* This class is a specialized version of the Board class for Othello. The OthelloBoard
|
||||
* class respects the rules of Othello and also keeps track of the symbols for Player
|
||||
* 1 and Player 2.
|
||||
*/
|
||||
class OthelloBoard : public Board {
|
||||
public:
|
||||
|
||||
/**
|
||||
* @cols The number of columns in the game of Othello
|
||||
* @rows The number of rows in the game of Othello
|
||||
* @p1_symbol The symbol used for Player 1's pieces on the board
|
||||
* @p2_symbol The symbol used for Player 2's pieces on the board
|
||||
* This is a constructor for an OthelloBoard clas.
|
||||
*/
|
||||
OthelloBoard(int cols, int rows, char p1_symbol, char p2_symbol);
|
||||
|
||||
/**
|
||||
* @param other The OthelloBoard object you are copying from.
|
||||
* This is the copy constructor for the OthelloBoard class.
|
||||
*/
|
||||
OthelloBoard(const OthelloBoard& other);
|
||||
|
||||
/**
|
||||
* The destructor for the OthelloBoard class.
|
||||
*/
|
||||
virtual ~OthelloBoard();
|
||||
|
||||
/**
|
||||
* Initializes the Othello board to the starting position of the pieces
|
||||
* for Players 1 and 2
|
||||
*/
|
||||
void initialize();
|
||||
|
||||
/**
|
||||
* @param rhs The right-hand side object of the assignment
|
||||
* @return The left-hand side object of the assignment
|
||||
* This is the overloaded assignment operator for the OthelloBoard class
|
||||
*/
|
||||
OthelloBoard& operator=(const OthelloBoard& rhs);
|
||||
|
||||
/**
|
||||
* @param col The column for where your piece goes
|
||||
* @param row The row for where your piece goes
|
||||
* @return true if the move is legal, false otherwise.
|
||||
* Checks the legality of a move that places a piece at the specified col and
|
||||
* row.
|
||||
*/
|
||||
bool is_legal_move(int col, int row, char symbol) const;
|
||||
|
||||
/**
|
||||
* @param symbol This is the symbol for the current player.
|
||||
* @param col The column for where your piece goes
|
||||
* @param row The row for where your piece goes
|
||||
* Flips the in-between pieces once you put down a piece the specified
|
||||
* col and row position. The symbol argument specifies who the
|
||||
* current move belongs to.
|
||||
*/
|
||||
int flip_pieces(int col, int row, char symbol);
|
||||
|
||||
/**
|
||||
* @param symbol This symbol specifies the symbol for the current player (i.e.
|
||||
* who the current move belongs to)
|
||||
* @return true if there are still moves remaining, false otherwise
|
||||
* Checks if the game is over.
|
||||
*/
|
||||
bool has_legal_moves_remaining(char symbol) const;
|
||||
|
||||
/**
|
||||
* @param symbol The symbol representing a particular player.
|
||||
* Returns the score for the player with the specified symbol.
|
||||
*/
|
||||
int count_score(char symbol) const;
|
||||
|
||||
/**
|
||||
* @param col The column where the piece goes
|
||||
* @param row The row where the piece goes
|
||||
* Plays the move by placing a piece, with the given symbol, down at the specified
|
||||
* col and row. Then, any pieces sandwiched in between the two endpoints are flipped.
|
||||
*/
|
||||
void play_move(int col, int row, char symbol);
|
||||
|
||||
/**
|
||||
* @return Returns the symbol for Player 1 (the maximizing player)'s pieces
|
||||
* Returns the symbol for Player 1's pieces
|
||||
*/
|
||||
char get_p1_symbol() { return p1_symbol; }
|
||||
|
||||
/**
|
||||
* @return Returns the symbol for Player 2 (the minimizing player)'s pieces
|
||||
* Returns the symbol for Player 2's pieces
|
||||
*/
|
||||
char get_p2_symbol() { return p2_symbol; }
|
||||
|
||||
private:
|
||||
|
||||
/** The symbol for Player 1's pieces */
|
||||
char p1_symbol;
|
||||
|
||||
/** The symbol for Player 2's pieces */
|
||||
char p2_symbol;
|
||||
|
||||
/**
|
||||
* @param col The column of the starting point
|
||||
* @param row The row of the starting point
|
||||
* @param next_col The return value for the column
|
||||
* @param next_row The return value for the row
|
||||
* @param dir The direction you want to move
|
||||
* Sets the coordinates of next_col and next_row to be the coordinates if you were
|
||||
* moving in the direction specified by the argument dir starting at position (col,row)
|
||||
*/
|
||||
void set_coords_in_direction(int col, int row, int& next_col, int& next_row, int dir) const;
|
||||
|
||||
/**
|
||||
* @param col The column of the starting point
|
||||
* @param row The row of the starting point
|
||||
* @param symbol The symbol of the current player. You will match (or not match) this symbol
|
||||
* at the endpoint
|
||||
* @param dir The direction you are moving in
|
||||
* @param match_symbol If true, it will return true if the arg symbol matches the endpoint. If false,
|
||||
* it will return true if the arg symbol doesn't match the endpoint.
|
||||
* If you start at (col,row) and move in direction dir, this function will check the endpoint
|
||||
* of a trail of pieces. If match_symbol is true, it will return true if the endpoint matches
|
||||
* the argument symbol (and false otherwise). If match_symbol is false, it will return true
|
||||
* if the endpoint doesn't match the argument symbol (and false otherwise).
|
||||
*/
|
||||
bool check_endpoint(int col, int row, char symbol, int dir,
|
||||
bool match_symbol) const;
|
||||
|
||||
/**
|
||||
* @param col The column of the starting point
|
||||
* @param row The row of the starting point
|
||||
* @param symbol This is the symbol at the endpoint that terminates the row of pieces flipped
|
||||
* @param dir The direction you are moving
|
||||
* This is a helper function for the recursive flip_pieces function.
|
||||
*/
|
||||
int flip_pieces_helper(int col, int row, char symbol, int dir);
|
||||
};
|
||||
|
||||
#endif /* OTHELLOBOARD_H_ */
|
||||
@@ -0,0 +1,9 @@
|
||||
#include "Player.h"
|
||||
|
||||
Player::Player(char symb) : symbol(symb) {
|
||||
|
||||
}
|
||||
|
||||
Player::~Player() {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* Player class
|
||||
*/
|
||||
|
||||
#ifndef PLAYER_H
|
||||
#define PLAYER_H
|
||||
|
||||
#include "OthelloBoard.h"
|
||||
|
||||
/**
|
||||
* This is an abstract base class for a Player
|
||||
*/
|
||||
class Player {
|
||||
public:
|
||||
/**
|
||||
* @param symb The symbol for the player's pieces
|
||||
*/
|
||||
Player(char symb);
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~Player();
|
||||
|
||||
/**
|
||||
* @return The player's symbol
|
||||
* Gets the symbol for the player's pieces
|
||||
*/
|
||||
char get_symbol() { return symbol; }
|
||||
|
||||
/**
|
||||
* @param b The current board
|
||||
* @param col Holds the column of the player's move
|
||||
* @param row Holds the row of the player's move
|
||||
* Gets the next move for the player
|
||||
*/
|
||||
virtual void get_move(OthelloBoard* b, int& col, int& row) = 0;
|
||||
|
||||
/**
|
||||
* @return A copy of the Player object
|
||||
* Virtual copy constructor
|
||||
*/
|
||||
virtual Player* clone() = 0;
|
||||
protected:
|
||||
|
||||
/** The symbol for the player's pieces*/
|
||||
char symbol;
|
||||
};
|
||||
|
||||
#endif
|
||||
Binary file not shown.
Reference in New Issue
Block a user