cmpsc330hw5/ss.cxx

180 lines
4.4 KiB
C++
Raw Normal View History

2024-12-07 02:24:11 +00:00
// 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"
2024-12-07 00:04:43 +00:00
2024-12-07 01:40:19 +00:00
extern "C" IPlayer *PlayerFactory() {
2024-12-07 00:04:43 +00:00
return new StrategicPlayer1();
}
using namespace std;
string StrategicPlayer1::PlayerInfo() {
2024-12-07 01:40:19 +00:00
return "Sandipsinh Rathod (sdr5549@psu.edu), Sapan Shah (scs6041@psu.edu)";
2024-12-07 00:04:43 +00:00
}
void StrategicPlayer1::Init(int board_rows, int board_cols, char box_type, char line_type) {
this->box_name = box_type;
this->name = line_type;
int blank_line_count = 0;
board.AllocateBoard(board_rows, board_cols, blank_line_count);
}
void StrategicPlayer1::Close() {
board.FreeBoard();
}
2024-12-07 01:40:19 +00:00
void StrategicPlayer1::EventAddLine(char bar, const Loc &loc) {
2024-12-07 01:52:13 +00:00
board(loc) = bar;
2024-12-07 00:04:43 +00:00
}
2024-12-07 01:40:19 +00:00
void StrategicPlayer1::EventAddBox(char box, const Loc &loc) {
2024-12-07 01:52:13 +00:00
board(loc) = box;
2024-12-07 00:04:43 +00:00
}
Loc StrategicPlayer1::SelectLineLocation() {
2024-12-07 01:40:19 +00:00
vector<Loc> empty_lines;
ListEmptyLines(empty_lines);
// Step 1: Look for a move to complete a box
Loc move = FindBoxCompletingMove();
if (move.row != -1) {
return move;
}
// Step 2: Force opponent into bad moves
move = ForceOpponentMistake(empty_lines);
if (move.row != -1) {
return move;
2024-12-07 00:04:43 +00:00
}
2024-12-07 01:40:19 +00:00
// Step 3: Fall back to the optimal move
return FindOptimalMove();
2024-12-07 00:04:43 +00:00
}
StrategicPlayer1::~StrategicPlayer1() {
Close();
}
Loc StrategicPlayer1::FindBoxCompletingMove() {
vector<Loc> empty_lines;
ListEmptyLines(empty_lines);
2024-12-07 01:40:19 +00:00
for (const Loc &loc: empty_lines) {
2024-12-07 00:04:43 +00:00
int row = loc.row, col = loc.col;
2024-12-07 01:40:19 +00:00
if (DoesMoveCompleteBox(row, col)) {
return loc;
2024-12-07 00:04:43 +00:00
}
}
2024-12-07 01:40:19 +00:00
return Loc(-1, -1);
2024-12-07 00:04:43 +00:00
}
bool StrategicPlayer1::DoesMoveCompleteBox(int row, int col) {
2024-12-07 01:52:13 +00:00
if (!(row & 1) && col & 1) {
2024-12-07 00:04:43 +00:00
return (CountBoxLines(row - 1, col) == 3 || CountBoxLines(row + 1, col) == 3);
2024-12-07 01:52:13 +00:00
} else if (row & 1 && !(col & 1)) {
2024-12-07 00:04:43 +00:00
return (CountBoxLines(row, col - 1) == 3 || CountBoxLines(row, col + 1) == 3);
}
return false;
}
2024-12-07 01:40:19 +00:00
Loc StrategicPlayer1::ForceOpponentMistake(const vector<Loc> &empty_lines) {
Loc best_move(-1, -1);
for (const Loc &loc: empty_lines) {
if (!DoesMoveCreateChain(loc.row, loc.col)) {
2024-12-07 01:52:13 +00:00
return loc;
2024-12-07 01:40:19 +00:00
}
}
return best_move;
}
2024-12-07 00:04:43 +00:00
Loc StrategicPlayer1::FindOptimalMove() {
vector<Loc> empty_lines;
ListEmptyLines(empty_lines);
int min_cost = numeric_limits<int>::max();
Loc best_move(-1, -1);
2024-12-07 01:40:19 +00:00
for (const Loc &loc: empty_lines) {
2024-12-07 00:04:43 +00:00
int cost = EvaluateMoveCost(loc.row, loc.col);
if (cost < min_cost) {
min_cost = cost;
best_move = loc;
}
}
return best_move;
}
2024-12-07 01:40:19 +00:00
bool StrategicPlayer1::DoesMoveCreateChain(int row, int col) {
board(row, col) = name;
bool creates_chain = false;
2024-12-07 01:52:13 +00:00
if (!(row & 1) && col & 1) {
2024-12-07 01:40:19 +00:00
if (CountBoxLines(row - 1, col) == 2 || CountBoxLines(row + 1, col) == 2) {
creates_chain = true;
}
2024-12-07 01:52:13 +00:00
} else if (row & 1 && !(col & 1)) {
2024-12-07 01:40:19 +00:00
if (CountBoxLines(row, col - 1) == 2 || CountBoxLines(row, col + 1) == 2) {
creates_chain = true;
}
}
board(row, col) = ' ';
return creates_chain;
}
2024-12-07 00:04:43 +00:00
int StrategicPlayer1::EvaluateMoveCost(int row, int col) {
int cost = 0;
2024-12-07 01:52:13 +00:00
if (!(row & 1) && col & 1) { // Horizontal line
2024-12-07 00:04:43 +00:00
cost += CountBoxLines(row - 1, col);
cost += CountBoxLines(row + 1, col);
2024-12-07 01:52:13 +00:00
} else if (row & 1 && !(col & 1)) { // Vertical line
2024-12-07 00:04:43 +00:00
cost += CountBoxLines(row, col - 1);
cost += CountBoxLines(row, col + 1);
}
return cost;
}
int StrategicPlayer1::CountBoxLines(int row, int col) {
if (row < 0 || row >= board.GetRows() || col < 0 || col >= board.GetCols()) {
return 0;
}
int count = 0;
if (board(row - 1, col) != ' ') count++; // Top
if (board(row + 1, col) != ' ') count++; // Bottom
if (board(row, col - 1) != ' ') count++; // Left
if (board(row, col + 1) != ' ') count++; // Right
return count;
}
2024-12-07 01:40:19 +00:00
void StrategicPlayer1::ListEmptyLines(vector<Loc> &empty_lines) {
2024-12-07 00:04:43 +00:00
for (int r = 0; r < board.GetRows(); r++) {
for (int c = 0; c < board.GetCols(); c++) {
Loc loc(r, c);
if (loc.IsLineLocation() && board(r, c) == ' ') {
2024-12-07 01:40:19 +00:00
empty_lines.push_back(loc);
2024-12-07 00:04:43 +00:00
}
}
}
}