add better method

This commit is contained in:
Sandipsinh Rathod 2024-12-06 20:40:19 -05:00
parent 6362853abd
commit db8e2596ef
No known key found for this signature in database
2 changed files with 60 additions and 31 deletions

@ -1,19 +1,13 @@
#include <iostream>
#include <limits>
#include "strategic_player1.h"
#include "common.h"
extern "C" IPlayer* PlayerFactory()
{
extern "C" IPlayer *PlayerFactory() {
return new StrategicPlayer1();
}
using namespace std;
string StrategicPlayer1::PlayerInfo() {
return "Big MAN Smol PP";
return "Sandipsinh Rathod (sdr5549@psu.edu), Sapan Shah (scs6041@psu.edu)";
}
void StrategicPlayer1::Init(int board_rows, int board_cols, char box_type, char line_type) {
@ -28,57 +22,73 @@ void StrategicPlayer1::Close() {
board.FreeBoard();
}
void StrategicPlayer1::EventAddLine(char bar, const Loc& loc) {
void StrategicPlayer1::EventAddLine(char bar, const Loc &loc) {
board(loc) = bar; // Update the board with the added line
}
void StrategicPlayer1::EventAddBox(char box, const Loc& loc) {
void StrategicPlayer1::EventAddBox(char box, const Loc &loc) {
board(loc) = box; // Update the board with the assigned box
}
Loc StrategicPlayer1::SelectLineLocation() {
Loc box_completing_move = FindBoxCompletingMove();
if (box_completing_move.row != -1 && box_completing_move.col != -1) {
return box_completing_move; // Prioritize moves that complete a box
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;
}
return FindOptimalMove(); // Fall back to a heuristic-based optimal move
// Step 2: Force opponent into bad moves
move = ForceOpponentMistake(empty_lines);
if (move.row != -1) {
return move;
}
// Step 3: Fall back to the optimal move
return FindOptimalMove();
}
StrategicPlayer1::~StrategicPlayer1() {
Close();
}
// Private helper functions
Loc StrategicPlayer1::FindBoxCompletingMove() {
vector<Loc> empty_lines;
ListEmptyLines(empty_lines);
for (const Loc& loc : empty_lines) {
for (const Loc &loc: empty_lines) {
int row = loc.row, col = loc.col;
// Check if adding a line at this location completes a box
if ((row % 2 == 0 && col % 2 == 1) || (row % 2 == 1 && col % 2 == 0)) {
if (DoesMoveCompleteBox(row, col)) {
return loc; // Return the first box-completing move found
}
if (DoesMoveCompleteBox(row, col)) {
return loc;
}
}
return Loc(-1, -1); // No box-completing move found
return Loc(-1, -1);
}
bool StrategicPlayer1::DoesMoveCompleteBox(int row, int col) {
// Check adjacent boxes based on the move's orientation
if (row % 2 == 0 && col % 2 == 1) { // Horizontal line
return (CountBoxLines(row - 1, col) == 3 || CountBoxLines(row + 1, col) == 3);
} else if (row % 2 == 1 && col % 2 == 0) { // Vertical line
return (CountBoxLines(row, col - 1) == 3 || CountBoxLines(row, col + 1) == 3);
}
return false;
}
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)) {
return loc; // Choose the first safe move
}
}
return best_move;
}
Loc StrategicPlayer1::FindOptimalMove() {
vector<Loc> empty_lines;
ListEmptyLines(empty_lines);
@ -86,7 +96,7 @@ Loc StrategicPlayer1::FindOptimalMove() {
int min_cost = numeric_limits<int>::max();
Loc best_move(-1, -1);
for (const Loc& loc : empty_lines) {
for (const Loc &loc: empty_lines) {
int cost = EvaluateMoveCost(loc.row, loc.col);
if (cost < min_cost) {
min_cost = cost;
@ -97,10 +107,28 @@ Loc StrategicPlayer1::FindOptimalMove() {
return best_move;
}
bool StrategicPlayer1::DoesMoveCreateChain(int row, int col) {
board(row, col) = name;
bool creates_chain = false;
if (row % 2 == 0 && col % 2 == 1) {
if (CountBoxLines(row - 1, col) == 2 || CountBoxLines(row + 1, col) == 2) {
creates_chain = true;
}
} else if (row % 2 == 1 && col % 2 == 0) {
if (CountBoxLines(row, col - 1) == 2 || CountBoxLines(row, col + 1) == 2) {
creates_chain = true;
}
}
board(row, col) = ' ';
return creates_chain;
}
int StrategicPlayer1::EvaluateMoveCost(int row, int col) {
int cost = 0;
// Evaluate the "cost" of the move by summing the number of sides completed for adjacent boxes
if (row % 2 == 0 && col % 2 == 1) { // Horizontal line
cost += CountBoxLines(row - 1, col);
cost += CountBoxLines(row + 1, col);
@ -113,13 +141,11 @@ int StrategicPlayer1::EvaluateMoveCost(int row, int col) {
}
int StrategicPlayer1::CountBoxLines(int row, int col) {
// Ensure the location is within bounds
if (row < 0 || row >= board.GetRows() || col < 0 || col >= board.GetCols()) {
return 0;
}
int count = 0;
// Check all four sides of the box
if (board(row - 1, col) != ' ') count++; // Top
if (board(row + 1, col) != ' ') count++; // Bottom
if (board(row, col - 1) != ' ') count++; // Left
@ -128,12 +154,12 @@ int StrategicPlayer1::CountBoxLines(int row, int col) {
return count;
}
void StrategicPlayer1::ListEmptyLines(vector<Loc>& empty_lines) {
void StrategicPlayer1::ListEmptyLines(vector<Loc> &empty_lines) {
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) == ' ') {
empty_lines.push_back(loc); // Add all empty line locations to the list
empty_lines.push_back(loc);
}
}
}

@ -5,6 +5,7 @@
#include "board.h"
#include "player.h"
#include <vector>
#include <limits>
class StrategicPlayer1 : public IPlayer {
char name;
@ -26,6 +27,8 @@ public:
void ListEmptyLines(vector<Loc>& empty_lines);
bool DoesMoveCompleteBox(int row, int col);
Loc FindBoxCompletingMove();
bool DoesMoveCreateChain(int row, int col);
Loc ForceOpponentMistake(const vector<Loc>& empty_lines);
~StrategicPlayer1();
};