Search code examples
c++arrayssdlsdl-2minimax

C++ How to hold lots of arrays dynamically?


Okay so basically I am building a simple checkers game using C++ SDL2 library

Currently I am holding the game board state data in a 8x8 2d array which is all the possible board spaces on a checkerboard. The value inside the array is either: 0 for empty space, 1 for red checker, 2 for blue checker.

I have basically the entire game done using this board as the logic and I am now going to be implementing the minimax algorithm to add computer AI as the opponent. So what I need to do is get all the possible board states and use that in the algorithm. Right now I am trying to find the right way to approach storing a bunch of arrays (board states) in a dynamic way since I will not know exactly every time how many states there will be. Is there any easy way to use a main array to hold all the board states (2d Arrays)? It needs to be dynamic, and arrays can only be static right?


Solution

  • I'd suggest creating a wrapper class around std::array<checker_type, 8 * 8> (since emulating 2D array using a 1D arrays usually proves to be faster due to caching). This way you can easily create and copy such boards.

    #include <array>
    #include <iostream>
    #include <vector>
    
    namespace game {
        enum class checker_type {
            empty, red, blue
        };
    
        struct board {
            std::array<checker_type, 8 * 8> data{};
    
            struct proxy_row {
                std::array<checker_type, 8 * 8>& data_ref;
                const std::size_t row;
    
                proxy_row(std::array<checker_type, 64>& data_ref, const size_t row) noexcept
                        : data_ref(data_ref), row(row) { }
    
                checker_type& operator [] (const std::size_t col) const noexcept {
                    return data_ref[8 * row + col];
                }
            };
    
            struct const_proxy_row {
                const std::array<checker_type, 8 * 8>& data_ref;
                const std::size_t row;
    
                const_proxy_row(const std::array<checker_type, 64>& data_ref, const size_t row) noexcept
                : data_ref(data_ref), row(row) { }
    
                const checker_type& operator [] (const std::size_t col) const noexcept {
                    return data_ref[8 * row + col];
                }
            };
    
            proxy_row operator [] (const std::size_t row) noexcept {
                return proxy_row(data, row);
            };
    
            const_proxy_row operator [] (const std::size_t row) const noexcept {
                return const_proxy_row(data, row);
            }
        };
    }
    
    void print_board(const game::board& board) noexcept {
        for (int i = 0; i < 8; ++i) {
            for (int j = 0; j < 8; ++j) {
                std::cout << static_cast<int>(board[i][j]) << ' ';
            }
            std::cout << '\n';
        }
    }
    

    As for creating multiple boards to run minmax algorithm, you can use an std::vector - a class template which provides a dynamic array functionality with lots of utilities:

    int main() {
        game::board board{};
    
        board[0][0] = game::checker_type::blue;
        board[1][1] = game::checker_type::blue;
        board[2][2] = game::checker_type::red;
    
        print_board(board);
    
        std::vector<game::board> boards{};
    
        const auto size = 1000;
        boards.reserve(size); // reserve memory for *size* boards
        for (int i = 0; i < size; ++i) {
            boards.emplace_back(); // creating *size* boards to run minmax algorithm
        }
    }
    

    To elaborate a little bit on your thought process:

    Right now I am trying to find the right way to approach storing a bunch of arrays (board states) in a dynamic way since I will not know exactly every time how many states there will be.

    You are correct that you want a dynamic way of storing some data if you do not know beforehand how much memory that data will require. std::vector is an excellent tool to handle that.

    [Array] needs to be dynamic, and arrays can only be static right?

    Wrong. First of all, static is not the opposite of dynamic. You can have a dynamic, static array (for example static int* arr = new int[10];).