add ss.*
This commit is contained in:
parent
3ecbd34211
commit
a6a1fca8cd
61
README.txt
Normal file
61
README.txt
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
Team member 1:
|
||||||
|
Name: Sandipsinh Rathod
|
||||||
|
Email: sdr5549@psu.edu
|
||||||
|
Class: CMPSC 330
|
||||||
|
|
||||||
|
Team member 2:
|
||||||
|
Name: Sapan Shah
|
||||||
|
Email: scs6041@psu.edu
|
||||||
|
Class: CMPSC 330
|
||||||
|
Homework 5
|
||||||
|
Due Date: December 6, 2024
|
||||||
|
|
||||||
|
Command used to create object file for strategic player
|
||||||
|
g++ -O3 -shared -fPIC -ansi -pedantic -std=c++14 board.cxx ss.cxx -o SandipsinhRathodsdr5549_SapanShahscs6041.so
|
||||||
|
|
||||||
|
Restructuring HW2 and HW4 in HW5
|
||||||
|
1. Class Abstraction and Polymorphism
|
||||||
|
|
||||||
|
HW2: The game logic was directly implemented without clear abstractions for players, relying on procedural logic.
|
||||||
|
HW4: Introduced polymorphism via Player, RandomPlayer, and StrategicPlayer classes. Players had distinct behavior, and polymorphism allowed dynamic handling of different player types.
|
||||||
|
HW5: Built on this by creating the StrategicPlayer1 class derived from IPlayer, implementing a robust and modular strategy for player decisions:
|
||||||
|
Interface Implementation: StrategicPlayer1 implements IPlayer, ensuring that all player-related behaviors are well-defined and standardized across implementations.
|
||||||
|
Enhanced Strategies: Added sophisticated methods like FindBoxCompletingMove and ForceOpponentMistake, making the strategy logic adaptable and focused on optimizing game outcomes.
|
||||||
|
|
||||||
|
2. Dynamic Memory Management
|
||||||
|
|
||||||
|
HW2: Basic memory management using raw pointers with manual deallocation.
|
||||||
|
HW4: Introduced the RAII (Resource Acquisition Is Initialization) pattern for managing board memory allocation and deallocation efficiently.
|
||||||
|
HW5: Continued RAII principles with a more structured approach to object lifecycles, ensuring robust cleanup:
|
||||||
|
Explicit initialization and cleanup methods (Init, Close) for the StrategicPlayer1 class.
|
||||||
|
Use of dynamic memory in a controlled and predictable way, minimizing risks of memory leaks.
|
||||||
|
|
||||||
|
3. Board Representation
|
||||||
|
|
||||||
|
HW2: The board was represented as a dynamically allocated 2D array, with logic scattered across functions.
|
||||||
|
HW4: Encapsulated board management into the Board class, which included methods for placing lines, checking box completion, and printing the board.
|
||||||
|
HW5: Enhanced the Board class functionality:
|
||||||
|
Added methods like ListEmptyLines to provide the player class with detailed insights into game state.
|
||||||
|
Improved the interface between the board and player, enabling complex strategic evaluations such as chain creation and cost evaluation.
|
||||||
|
|
||||||
|
4. Player Strategies
|
||||||
|
|
||||||
|
HW2: All moves were processed in a straightforward, procedural manner without differentiation between players.
|
||||||
|
HW4: Differentiated players using classes for random and strategic play. However, the strategic player logic was limited to basic box completion.
|
||||||
|
HW5: Refined the strategic player logic significantly:
|
||||||
|
Multi-step Decision Making: Implemented a three-step approach for move selection: completing boxes, avoiding chains, and fallback to optimal moves.
|
||||||
|
Move Evaluation: Added sophisticated cost evaluation (EvaluateMoveCost) and chain detection (DoesMoveCreateChain).
|
||||||
|
|
||||||
|
5. Event-Driven Design
|
||||||
|
|
||||||
|
HW4: The player and board interactions were tightly coupled.
|
||||||
|
HW5: Introduced event-driven methods (EventAddLine, EventAddBox) to separate game state updates from decision-making logic. This enhances modularity and makes the code easier to extend and debug.
|
||||||
|
|
||||||
|
Learnings
|
||||||
|
|
||||||
|
Modularity and Reusability: Encapsulation of functionality (e.g., board management, player behaviors) allows for better reuse and testing. The separation of concerns between classes improved maintainability.
|
||||||
|
Polymorphism and Interfaces: Leveraging polymorphism (IPlayer) provided a flexible framework to implement diverse player strategies while ensuring consistency.
|
||||||
|
Strategic Thinking: Developing a multi-step strategy for players helped refine algorithmic thinking and fostered a deeper understanding of game theory.
|
||||||
|
RAII and Memory Management: The shift to controlled memory allocation and deallocation in RAII patterns reduced errors and improved reliability.
|
||||||
|
Event-Driven Programming: Designing the game logic around events encouraged a cleaner architecture and reduced tight coupling.
|
||||||
|
Iterative Refinement: By analyzing and building upon previous homework, we demonstrated the importance of iterative development and incremental improvement in programming.
|
BIN
bar.so
BIN
bar.so
Binary file not shown.
BIN
foo.so
BIN
foo.so
Binary file not shown.
@ -1,122 +0,0 @@
|
|||||||
#include "custom_player.h"
|
|
||||||
#include <iostream>
|
|
||||||
#include <cstdlib> // for rand
|
|
||||||
#include <ctime> // for time
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
// Factory function for dynamic library loading
|
|
||||||
extern "C" IPlayer* PlayerFactory() {
|
|
||||||
return new CustomPlayer();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Constructor
|
|
||||||
CustomPlayer::CustomPlayer() {
|
|
||||||
srand(time(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Destructor
|
|
||||||
CustomPlayer::~CustomPlayer() {}
|
|
||||||
|
|
||||||
// Initializes the player with the board size and player symbols
|
|
||||||
void CustomPlayer::Init(int dots_in_rows, int dots_in_cols, char _player_box, char _player_line) {
|
|
||||||
board.AllocateBoard(dots_in_rows, dots_in_cols);
|
|
||||||
player_box = _player_box;
|
|
||||||
player_line = _player_line;
|
|
||||||
empty_lines = new Loc[board.GetRows() * board.GetCols()];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cleans up dynamically allocated memory
|
|
||||||
void CustomPlayer::Close() {
|
|
||||||
board.FreeBoard();
|
|
||||||
delete[] empty_lines;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns the player info
|
|
||||||
std::string CustomPlayer::PlayerInfo() {
|
|
||||||
return "Custom Strategic Player";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Updates the board when a line is added
|
|
||||||
void CustomPlayer::EventAddLine(char bar, const Loc& loc) {
|
|
||||||
board(loc) = bar;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Updates the board when a box is completed
|
|
||||||
void CustomPlayer::EventAddBox(char box, const Loc& loc) {
|
|
||||||
board(loc) = box;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Updates the list of available line locations
|
|
||||||
void CustomPlayer::ListEmptyLines() {
|
|
||||||
empty_lines_count = 0;
|
|
||||||
for (int r = 0; r < board.GetRows(); r++) {
|
|
||||||
for (int c = 0; c < board.GetCols(); c++) {
|
|
||||||
if (board(r, c) == ' ' && Loc(r, c).IsLineLocation()) {
|
|
||||||
empty_lines[empty_lines_count++] = Loc(r, c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helper function to check if a line completes a box
|
|
||||||
bool CustomPlayer::DoesLineCompleteBox(const Loc& loc) {
|
|
||||||
if (loc.IsLineHorizontalLocation()) {
|
|
||||||
if (loc.row > 0 && board(loc.row - 1, loc.col) != ' ' &&
|
|
||||||
board(loc.row - 1, loc.col - 1) != ' ' && board(loc.row - 1, loc.col + 1) != ' ')
|
|
||||||
return true;
|
|
||||||
if (loc.row < board.GetRows() - 1 && board(loc.row + 1, loc.col) != ' ' &&
|
|
||||||
board(loc.row + 1, loc.col - 1) != ' ' && board(loc.row + 1, loc.col + 1) != ' ')
|
|
||||||
return true;
|
|
||||||
} else if (loc.IsLineVerticalLocation()) {
|
|
||||||
if (loc.col > 0 && board(loc.row, loc.col - 1) != ' ' &&
|
|
||||||
board(loc.row - 1, loc.col - 1) != ' ' && board(loc.row + 1, loc.col - 1) != ' ')
|
|
||||||
return true;
|
|
||||||
if (loc.col < board.GetCols() - 1 && board(loc.row, loc.col + 1) != ' ' &&
|
|
||||||
board(loc.row - 1, loc.col + 1) != ' ' && board(loc.row + 1, loc.col + 1) != ' ')
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helper function to avoid giving the opponent a chance to complete a box
|
|
||||||
bool CustomPlayer::WouldGiveOpponentBox(const Loc& loc) {
|
|
||||||
// Temporarily add the line to the board
|
|
||||||
board(loc) = player_line;
|
|
||||||
|
|
||||||
// Check if the opponent can complete a box in the next move
|
|
||||||
for (int r = 0; r < board.GetRows(); r++) {
|
|
||||||
for (int c = 0; c < board.GetCols(); c++) {
|
|
||||||
if (board(r, c) == ' ' && Loc(r, c).IsLineLocation() &&
|
|
||||||
DoesLineCompleteBox(Loc(r, c))) {
|
|
||||||
board(loc) = ' '; // Revert the move
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Revert the move
|
|
||||||
board(loc) = ' ';
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Determines the next move
|
|
||||||
Loc CustomPlayer::SelectLineLocation() {
|
|
||||||
ListEmptyLines();
|
|
||||||
|
|
||||||
// Strategy: Prioritize moves that complete a box
|
|
||||||
for (int i = 0; i < empty_lines_count; i++) {
|
|
||||||
if (DoesLineCompleteBox(empty_lines[i])) {
|
|
||||||
return empty_lines[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Avoid moves that give the opponent a chance to complete a box
|
|
||||||
for (int i = 0; i < empty_lines_count; i++) {
|
|
||||||
if (!WouldGiveOpponentBox(empty_lines[i])) {
|
|
||||||
return empty_lines[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise, pick a random move
|
|
||||||
return empty_lines[rand() % empty_lines_count];
|
|
||||||
}
|
|
@ -1,54 +0,0 @@
|
|||||||
#ifndef __CUSTOM_PLAYER__
|
|
||||||
#define __CUSTOM_PLAYER__
|
|
||||||
|
|
||||||
#include "player.h"
|
|
||||||
#include "common.h"
|
|
||||||
#include "board.h"
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
class CustomPlayer : public IPlayer {
|
|
||||||
private:
|
|
||||||
Board board; // Game board to track state
|
|
||||||
char player_box; // Character representing the player's boxes
|
|
||||||
char player_line; // Character representing the player's lines
|
|
||||||
Loc* empty_lines; // Array to store available line locations
|
|
||||||
int empty_lines_count; // Number of available line locations
|
|
||||||
|
|
||||||
public:
|
|
||||||
CustomPlayer();
|
|
||||||
~CustomPlayer();
|
|
||||||
|
|
||||||
// Initializes the player with board details and player symbols
|
|
||||||
void Init(int dots_in_rows, int dots_in_cols, char player_box, char player_line) override;
|
|
||||||
|
|
||||||
// Cleans up dynamically allocated memory
|
|
||||||
void Close() override;
|
|
||||||
|
|
||||||
// Returns the player information
|
|
||||||
std::string PlayerInfo() override;
|
|
||||||
|
|
||||||
// Called when a line is added to the board
|
|
||||||
void EventAddLine(char bar, const Loc& loc) override;
|
|
||||||
|
|
||||||
// Called when a box is completed on the board
|
|
||||||
void EventAddBox(char box, const Loc& loc) override;
|
|
||||||
|
|
||||||
// Determines the next move based on the current state of the board
|
|
||||||
Loc SelectLineLocation() override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
// Updates the list of available line locations
|
|
||||||
void ListEmptyLines();
|
|
||||||
|
|
||||||
// Helper function to check if a line completes a box
|
|
||||||
bool DoesLineCompleteBox(const Loc& loc);
|
|
||||||
|
|
||||||
// Helper function to avoid giving the opponent a chance to complete a box
|
|
||||||
bool WouldGiveOpponentBox(const Loc& loc);
|
|
||||||
|
|
||||||
// Evaluate the best line location strategically
|
|
||||||
Loc GetBestStrategicMove();
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
10
readme.txt
10
readme.txt
@ -1,10 +0,0 @@
|
|||||||
Build mazerunner program and player_randommove.so library
|
|
||||||
|
|
||||||
g++ -ansi -pedantic -std=c++14 board.cxx dotsboxesgm.cxx main.cxx -o dotsboxes
|
|
||||||
g++ -shared -fPIC -ansi -pedantic -std=c++14 random_player.cxx board.cxx -o random_player.so
|
|
||||||
|
|
||||||
|
|
||||||
playing the dots and boxes games with multiple players
|
|
||||||
|
|
||||||
./dotsboxes ./strategic_player.so ./random_player.so ./strategic_player.so ./random_player.so
|
|
||||||
|
|
@ -1,4 +1,17 @@
|
|||||||
#include "strategic_player1.h"
|
// Team member 1
|
||||||
|
// Name: Sandipsinh Rathod
|
||||||
|
// Email: sdr5549@psu.edu
|
||||||
|
// Team member 2
|
||||||
|
// Name: Sapan Shah
|
||||||
|
// Email: scs6041@psu.edu
|
||||||
|
//
|
||||||
|
// Program homework 5
|
||||||
|
// Class: CMPSC 330
|
||||||
|
// Current Date: 6/12/24 9:15 PM
|
||||||
|
// Due Date: 6/12/24 11:59 PM
|
||||||
|
|
||||||
|
|
||||||
|
#include "ss.h"
|
||||||
|
|
||||||
extern "C" IPlayer *PlayerFactory() {
|
extern "C" IPlayer *PlayerFactory() {
|
||||||
return new StrategicPlayer1();
|
return new StrategicPlayer1();
|
@ -1,171 +0,0 @@
|
|||||||
#include "strategic_player.h"
|
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
extern "C" IPlayer* PlayerFactory()
|
|
||||||
{
|
|
||||||
return new StrategicPlayer();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helper functions
|
|
||||||
inline int normalize(int x) {
|
|
||||||
return (x + 1) >> 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline char getPoint(Board &board, const int row, const int col) {
|
|
||||||
return board(row, col);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool isLineValid(Board &board, const int row, const int col) {
|
|
||||||
return (row > -1 && row < board.GetRows() && col > -1 && col < board.GetCols()) &&
|
|
||||||
((row & 1) != (col & 1)) && (getPoint(board, row, col) == ' ');
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void set(Board &board, int r, int c, char ch) {
|
|
||||||
board(r, c) = ch;
|
|
||||||
}
|
|
||||||
//
|
|
||||||
|
|
||||||
|
|
||||||
string StrategicPlayer::PlayerInfo() {
|
|
||||||
return "Sandipsinh Rathod (sdr5549@psu.edu), Sapan Shah (scs6041@psu.edu)";
|
|
||||||
}
|
|
||||||
|
|
||||||
void StrategicPlayer::Init(int board_rows, int board_cols, char box_type, char line_type) {
|
|
||||||
this->name = box_type;
|
|
||||||
this->box_name = line_type;
|
|
||||||
this->board.AllocateBoard(board_rows, board_cols);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
StrategicPlayer::~StrategicPlayer() {
|
|
||||||
board.FreeBoard();
|
|
||||||
}
|
|
||||||
|
|
||||||
void StrategicPlayer::Close() {
|
|
||||||
board.FreeBoard();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// TODO: check if we needs checks :)
|
|
||||||
void StrategicPlayer::EventAddLine(char bar, const Loc &loc) {
|
|
||||||
set(board, loc.row, loc.col, bar);
|
|
||||||
}
|
|
||||||
|
|
||||||
void StrategicPlayer::EventAddBox(char box, const Loc &loc) {
|
|
||||||
set(board, loc.row, loc.col, box);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void selectLine(Board &board, int &row, int &col, int rows, int cols, char name) {
|
|
||||||
int max_row = 2 * rows - 2;
|
|
||||||
int max_col = 2 * cols - 2;
|
|
||||||
|
|
||||||
// Step 1: Try to complete a box
|
|
||||||
#pragma omp parallel for collapse(2)
|
|
||||||
for (int r = 1; r < max_row; r += 2) {
|
|
||||||
// Iterate over box centers (odd rows)
|
|
||||||
for (int c = 1; c < max_col; c += 2) {
|
|
||||||
// Iterate over box centers (odd cols)
|
|
||||||
// Check adjacent lines for an opportunity to complete a box
|
|
||||||
if (isLineValid(board, r - 1, c) && // Top line
|
|
||||||
getPoint(board, r + 1, c) != ' ' && // Bottom line
|
|
||||||
getPoint(board, r, c - 1) != ' ' && // Left line
|
|
||||||
getPoint(board, r, c + 1) != ' ') {
|
|
||||||
// Right line
|
|
||||||
row = r - 1;
|
|
||||||
col = c;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (isLineValid(board, r + 1, c) && // Bottom line
|
|
||||||
getPoint(board, r - 1, c) != ' ' && // Top line
|
|
||||||
getPoint(board, r, c - 1) != ' ' && // Left line
|
|
||||||
getPoint(board, r, c + 1) != ' ') {
|
|
||||||
// Right line
|
|
||||||
row = r + 1;
|
|
||||||
col = c;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (isLineValid(board, r, c - 1) && // Left line
|
|
||||||
getPoint(board, r - 1, c) != ' ' && // Top line
|
|
||||||
getPoint(board, r + 1, c) != ' ' && // Bottom line
|
|
||||||
getPoint(board, r, c + 1) != ' ') {
|
|
||||||
// Right line
|
|
||||||
row = r;
|
|
||||||
col = c - 1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (isLineValid(board, r, c + 1) && // Right line
|
|
||||||
getPoint(board, r - 1, c) != ' ' && // Top line
|
|
||||||
getPoint(board, r + 1, c) != ' ' && // Bottom line
|
|
||||||
getPoint(board, r, c - 1) != ' ') {
|
|
||||||
// Left line
|
|
||||||
row = r;
|
|
||||||
col = c + 1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Step 2: Avoid moves that leave a box with one line remaining
|
|
||||||
#pragma omp parallel for collapse(2)
|
|
||||||
for (int r = 0; r < 2 * rows - 1; ++r) {
|
|
||||||
// Iterate over all valid rows
|
|
||||||
for (int c = 0; c < 2 * cols - 1; ++c) {
|
|
||||||
// Iterate over all valid cols
|
|
||||||
if (isLineValid(board, r, c)) {
|
|
||||||
// Simulate placing the line
|
|
||||||
set(board, r, c, name);
|
|
||||||
|
|
||||||
// Check if this move leaves a box with only one line remaining
|
|
||||||
bool createsOpportunity = false;
|
|
||||||
for (int nr = 1; nr < max_row; nr += 2) {
|
|
||||||
// Iterate over box centers
|
|
||||||
for (int nc = 1; nc < max_col; nc += 2) {
|
|
||||||
if (getPoint(board, nr, nc) == ' ') {
|
|
||||||
int adjacentLines = 0;
|
|
||||||
if (nr > 0 && getPoint(board, nr - 1, nc) != ' ') adjacentLines++; // Top line
|
|
||||||
if (nr < max_row && getPoint(board, nr + 1, nc) != ' ') adjacentLines++; // Bottom line
|
|
||||||
if (nc > 0 && getPoint(board, nr, nc - 1) != ' ') adjacentLines++; // Left line
|
|
||||||
if (nc < max_col && getPoint(board, nr, nc + 1) != ' ') adjacentLines++; // Right line
|
|
||||||
|
|
||||||
if (adjacentLines == 3) {
|
|
||||||
// Opponent can complete this box
|
|
||||||
createsOpportunity = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (createsOpportunity) break;
|
|
||||||
}
|
|
||||||
|
|
||||||
set(board, r, c, ' '); // Undo the simulated move
|
|
||||||
|
|
||||||
if (!createsOpportunity) {
|
|
||||||
row = r;
|
|
||||||
col = c;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Step 3: Fallback to the first valid move
|
|
||||||
#pragma omp parallel for collapse(2)
|
|
||||||
for (int r = 0; r < 2 * rows - 1; ++r) {
|
|
||||||
for (int c = 0; c < 2 * cols - 1; ++c) {
|
|
||||||
if (isLineValid(board, r, c)) {
|
|
||||||
row = r;
|
|
||||||
col = c;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Loc StrategicPlayer::SelectLineLocation() {
|
|
||||||
int rows = normalize(board.GetRows());
|
|
||||||
int cols = normalize(board.GetCols());
|
|
||||||
|
|
||||||
int row, col;
|
|
||||||
selectLine(board, row, col, rows, cols, name);
|
|
||||||
|
|
||||||
return Loc(row, col);
|
|
||||||
}
|
|
@ -1,38 +0,0 @@
|
|||||||
|
|
||||||
#ifndef HW4_STRATEGIC_PLAYER_H
|
|
||||||
#define HW4_STRATEGIC_PLAYER_H
|
|
||||||
|
|
||||||
#include "common.h"
|
|
||||||
#include "board.h"
|
|
||||||
#include "player.h"
|
|
||||||
|
|
||||||
class StrategicPlayer: public IPlayer {
|
|
||||||
char name;
|
|
||||||
char box_name;
|
|
||||||
|
|
||||||
Board board;
|
|
||||||
public:
|
|
||||||
string PlayerInfo();
|
|
||||||
// Init(const int,const int) will be called before playing the game
|
|
||||||
// You can create your own data-structure
|
|
||||||
void Init
|
|
||||||
( int board_rows // the size of board (including dots, lines, and boxes)
|
|
||||||
, int board_cols // the size of board (including dots, lines, and boxes)
|
|
||||||
, char box_type // the character for the player's boxes
|
|
||||||
, char line_type // the character for the player's lines
|
|
||||||
);
|
|
||||||
// Close() will be called after finishing playing the game
|
|
||||||
// You can remove all dynamically allocated memories
|
|
||||||
void Close();
|
|
||||||
// EventAddLine() and EventAddBox() will be called
|
|
||||||
// when a player adds a line or when a system assign a box's owner
|
|
||||||
void EventAddLine(char bar, const Loc& loc);
|
|
||||||
void EventAddBox (char box, const Loc& loc);
|
|
||||||
// Loc SelectLineLocation() will be called
|
|
||||||
// when the game system ask where your player want to add a line
|
|
||||||
Loc SelectLineLocation();
|
|
||||||
|
|
||||||
~StrategicPlayer();
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif //HW4_STRATEGIC_PLAYER_H
|
|
Loading…
Reference in New Issue
Block a user