After playing Mancala with my brother, I thought coding the game would be a fun project to practice my abilities in C++. I am relatively new to programming, having only done a few small projects to experiment with the basic features of the language. So I consider this to be my first legitimate application of my skills. 

Although proud of my result I figured it could be better, especially since I have a function for each player (p1 and p2) instead of a player class. The reason why is because I "translate" the inputs. Hopefully that makes sense when looking at the code. I tried to find other source code to compare to my game, but everything I have found so far does not make much use of C++ and is rather lengthy. I appreciate any advice, but would really enjoy a full answer as to how to improve my code and further my abilities.

My code is separated into three parts; a menu class, a match class, and a main file.

**mancala.h**

```
#ifndef MANCALA_H
#define MANCALA_H

#include <iostream>
#include <string>
#include <vector>

namespace mancala{  

    const std::vector<std::string> rules = {
        "\nOverview:\n\tMancala is an ancient family of board games,\n\tand there are numerous variants.\n\tThis is a version of the basic game,\n\tknown as two-rank Mancala and also known as Kalah.\n\t",
        "\nHoles & Stores:\n\tYour holes on the board are on the bottom right side.\n\tYour store is the last hole on your right.\n\t",
        "\nSow Stones:\n\tChoose a hole to pick up all pieces.\n\tMoving counter - clockwise, the game now deposits one of\n\tthe stones in each hole until the stones run out.\n\t",
        "\nStore:\n\tIf you run into your own store deposit one piece in it.\n\tIf you run into your opponents store, skip it.\n\t",
        "\nFree Turn:\n\tIf the last piece you drop is in your own store,\n\tyou get a free turn.\n\t",
        "\nCapture:\n\tIf the last piece you drop is on your side,\n\tyou capture that piece and any pieces in the\n\thole directly opposite.\n\t",
        "\nEnd:\n\tThe game ends when all six spaces on one side of the mancala\n\tboard are empty.  The player who still has pieces on his side of\n\tthe board when the game ends captures all of those pieces.\n\t",
        "\nWin:\n\tCount all the piecies in each store.\n\tThe winner is the player with the most pieces.\n\t"
    };    

    enum option{
        play = 1,
        info,
        quit 
    };

    class match{
        public://constructor
            match() : board{4,4,4,4,4,4,0,4,4,4,4,4,4,0}{
                begin();
                while(ingame)
                    {match::update();}
                results();
            };
        private://functions
            void results();
            void update();
            void begin();
            void end();
        //make player class
            void p1_display(const std::string& mod = "");
            void p2_display(const std::string& mod = "");
            int  p1_pit_select();
            int  p2_pit_select();
            bool p1_pit_distribute(const int& pit);
            bool p2_pit_distribute(const int& pit);
            bool p1_is_greater();
            bool p2_is_greater();
            bool p1_clear_pits();
            bool p2_clear_pits();

        private://variables
            static const int pits = 14;
            int board[pits];
            bool ingame;
    };
};

#endif//MANCALA_H 

```

**mancala.cpp**

```
#include "mancala.h"

#include <unistd.h>
#include <iomanip>
#include <cstdlib>

using namespace mancala;

void match::update(){

    match::p1_display();

    switch(match::p1_clear_pits() || match::p2_is_greater() || match::p1_pit_distribute(match::p1_pit_select()) || match::p1_clear_pits() || match::p2_is_greater()){
        case true:
            end();
            return;
    }
    switch(match::p2_clear_pits() || match::p1_is_greater() || match::p2_pit_distribute(match::p2_pit_select()) || match::p2_clear_pits() || match::p1_is_greater()){
        case true:
            end();
            return;
    }
};

void match::begin(){
    ingame = true;
};

void match::end(){
    ingame = false;
};

void match::results(){
    if(board[13] < board[6]){
        std::cout << "    *** P1 Wins ***\n";
    }else if(board[13] > board[6]){
        std::cout << "    *** P2 Wins ***\n";
    }else if(board[13] == board[6]){
        std::cout << "    ***   Tie   ***\n";
    }else{
        std::cout << "    *** WHOOPS! ***\n";                   
    }sleep(2);
};

 int match::p1_pit_select(){
    std::cout << "Player 1: Enter(0-5): ";
    std::string s_input;
    int n_input;
    std::cin >> s_input;
    switch(s_input.at(0)){
        case '0': case '1': case '2':
        case '3': case '4': case '5':
            std::cin.putback(s_input.at(0));
            std::cin >> n_input;
            if(board[n_input] == 0){
                match::p1_display();
                return p1_pit_select();
            }return n_input;
        default:
            if(s_input == "back"){
                match::p1_display();
                return -1;
            }else{
                match::p1_display();
                return p1_pit_select();
            }
    } 
};

int trans(const unsigned int& index){
    return (7 + index) % 14;
};

int match::p2_pit_select(){
    std::cout << "Player 2: Enter(0-5): ";
    std::string s_input;
    int n_input;
    std::cin >> s_input;
    switch(s_input.at(0)){
        case '0': case '1': case '2':
        case '3': case '4': case '5':
            std::cin.putback(s_input.at(0));
            std::cin >> n_input;
            if(board[trans(n_input)] == 0){
                match::p2_display();
                return p2_pit_select();
            }return n_input;
        default:
            if(s_input == "back"){
                match::p2_display();
                return -1;
            }else{
                match::p2_display();
                return p2_pit_select();
            }
    } 
};

bool match::p2_clear_pits(){
    for(int index = 0; index < 6; index++){
        if(board[index] != 0) return false;
    }
    for(int index = 7; index < 13; index++){
        board[13] += board[index];
        board[index] = 0;
        match::p1_display();
    }return true;
};

bool match::p1_pit_distribute(const int& pit){//0-5
    if(pit == -1) return true;
    int markers = board[pit];
    board[pit] = 0;
    for(int index = 1; index <= markers; index++){
        if(index == markers){
        //*** last marker ***
            if(board[(pit + index) % 13] == 0 && (pit + index) != 6 && (pit + index) >= 0 && (pit + index) <= 5 && board[(12 - (pit + index))] != 0){
            //*** capture ***
                board[6] += board[12 - (index + pit)] + 1;
                board[12 - (index + pit)] = 0;
                match::p2_display();
            }else if((pit + index == 6) && !match::p2_clear_pits()){
                  //*** free turn ***
                board[6]+=1;    
                match::p1_display("P1: ⟲");
                p1_pit_distribute(match::p1_pit_select());
            }else{
             //*** deposit & end turn ***
                board[(pit + index) % 13]+=1;
                match::p2_display();
            }
        }else{
         //*** deposit ***
            board[(pit + index) % 13]+=1;
        }   
    }return false;  
};

bool match::p1_clear_pits(){
    for(int index = 7; index < 13; index++){
        if(board[index] != 0) return false;
    }
    for(int index = 0; index < 6; index++){
        board[6] += board[index];
        board[index] = 0;
        match::p2_display();
    }return true;
};

bool match::p2_pit_distribute(const int& pit){//0-5
    if(pit == -1) return true;
    int markers = board[trans(pit)];
    board[trans(pit)] = 0;
    for(int index = 1; index <= markers; index++){
        if(index == markers){
            if(board[trans((pit + index))] == 0 && trans(pit + index) != 13 && (pit + index) >= 0 && (pit + index) <= 5 && board[trans(12 - (pit + index))] != 0){
                board[13] += board[trans(12 - (index + pit))] + 1;
                board[trans(12 - (index + pit))] = 0;
                match::p1_display();
            }else if((trans(pit + index) == 13) && !p1_clear_pits()){
                board[13]+=1;
                match::p2_display("P2: ⟲");
                p2_pit_distribute(match::p2_pit_select());
            }else{
                board[trans(pit + index)]+=1;
                match::p1_display();
            }
        }else{
            board[trans(pit + index)]+=1;
        }
    }return false;  
};

static bool ask = true;

bool match::p2_is_greater(){
    if((board[13] > 24) && ask){
        match::p1_display("\b\bP2: > 24");
        std::cout << "Player 1: Continue?: ";
        std::string option;
        std::cin >> option;
        if(option == "yes"){
            match::p1_display();
            return ask = false;
        }else if(option == "no"){
            match::p1_display();
            return true;
        }else{
            match::p1_display();
            return p2_is_greater();
        }
    }else return false;
};

static bool _ask = true;

bool match::p1_is_greater(){
    if((board[6] > 24) && _ask){
        match::p2_display("\b\bP1: > 24");
        std::cout << "Player 2: Continue?: ";
        std::string option;
        std::cin >> option;
        if(option == "yes"){
            match::p2_display();
            return _ask = false;
        }else if(option == "no"){
            match::p2_display();
            return true;
        }else{
            match::p2_display();
            return p1_is_greater();
        }
    }else return false;
};

void match::p1_display(const std::string& mod){
    system("clear");
        for(int index = pits - 1; index >= pits / 2; index--)
            std::cout << std::setw(2) << std::setfill(' ') << board[index] << ' ';
        std::cout << "P1\nP2 ";
    for(int index = 0; index < pits / 2; index++)
        std::cout << std::setw(2) << std::setfill(' ') << board[index] << ' ';
    std::cout << "\n         " << mod << "\n   ";
    for(int index = 0; index < 6; index ++)
        std::cout << std::setw(2) << std::setfill('*') << index << ' ';
    std::cout << '\n';
};

void match::p2_display(const std::string& mod){
    system("clear");
    for(int index = pits - 1; index >= pits / 2; index--)
        std::cout << std::setw(2) << std::setfill(' ') << board[trans(index)] << ' ';
    std::cout << "P2\nP1 ";
    for(int index = 0; index < pits / 2; index++)
        std::cout << std::setw(2) << std::setfill(' ') << board[trans(index)] << ' ';
    std::cout << "\n         " << mod << "\n   ";
    for(int index = 0; index < 6; index ++)
        std::cout << std::setw(2) << std::setfill('*') << index << ' ';
    std::cout << '\n';
};

```

**menu.h**

```
#ifndef MENU_H
#define MENU_H

#include <iostream>
#include <string>
#include <vector>

class menu{
    public:
        menu(const std::string& title, const std::vector<std::string>& options)
            : title(title), options(options){;};
        void display();
        int get_input();
    private:
        std::string title;
        std::vector<std::string> options;
};

#endif//MENU_H

```

**menu.cpp**

```
#include "menu.h"

#include <cstdlib>

int menu::get_input(){
    display();
    int index;
    std::cin >> index;
    if(!std::cin){
        std::cin.clear();
        std::cin.ignore(256, '\n');
        return get_input();
    }return index;
};

void menu::display(){
    system("clear");
    std::cout << title << std::endl;
    for(int index = 0; index < options.size(); index++){
        std::cout << "[" << index + 1 << "]" << options[index] << std::endl;
    }std::cout << "Enter index: ";
};

```

**main.cpp**

```
#include "mancala.h"
#include "menu.h"

menu home("Mancala - Type \"back\" from anywhere to return to the main menu. ", {"Play","Info","Quit"});

int main(){bool end = false;
    while(!end){
        switch(home.get_input()){
            case mancala::option::play:
                mancala::match();
                break;
            case mancala::option::info:
                system("clear");
                for(int index = 0; index < mancala::rules.size(); index++){
                    std::cout << "Mancala: Rules \n"            
                                 << mancala::rules[index] 
                                 << "   Enter any key: ";
                    std::string ws;
                    std::cin >> ws;
                    if(ws == "back"){
                        break;
                    }else{
                        system("clear");
                    }
                }
                break;
            case mancala::option::quit:
                end = true;
        }
    }return 0;
}

```