Go to file
Sandipsinh Rathod a6a1fca8cd
add ss.*
2024-12-06 21:24:11 -05:00
board.cxx init 2024-12-06 17:06:18 -05:00
board.h init 2024-12-06 17:06:18 -05:00
CMakeLists.txt init 2024-12-06 17:06:18 -05:00
common.h init 2024-12-06 17:06:18 -05:00
dotsboxesgm.cxx revert to original files 2024-12-06 17:31:01 -05:00
input1.txt init 2024-12-06 17:06:18 -05:00
main.cxx revert to original files 2024-12-06 17:31:01 -05:00
player.h init 2024-12-06 17:06:18 -05:00
random_player.cxx init 2024-12-06 17:06:18 -05:00
random_player.h init 2024-12-06 17:06:18 -05:00
README.txt add ss.* 2024-12-06 21:24:11 -05:00
ss.cxx add ss.* 2024-12-06 21:24:11 -05:00
ss.h add ss.* 2024-12-06 21:24:11 -05:00

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.