Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

C++ STDIN Mancala: Each square, except the end zones (the long rectangles ones o

ID: 3698853 • Letter: C

Question

C++

STDIN

Mancala:

Each square, except the end zones (the long rectangles ones on the sides of the board) start with 3 marbles inside of them. The end zones start empty. This is a two person game, and each person has their own end zone. Player 1 has the end zone on the right and player 2 has the end zone on the left. The goal is to get as many pieces into your end zone. Each player takes a turn to move the marbles until a player’s end zone has 5 marbles in it. Then the game is over. Once that happens the marbles in the 4 right hand holes go into the right end zone, and the 4 on the left go to the left end zone, leaving the middle square untouched. Once the pieces have been distributed the winner is determined by who has the most marbles in their end zone.

On a player’s turn they move by selecting any hole with marbles in it, except the end zones. They pick up all the marbles in that hole and start traveling along the red path of movement dropping one marble in each hole they pass. The starting hole does not get a marble unless you pass over it again. If the player goes over their opponent’s end zone they skip over it without dropping a marble; but if they pass their own end zone they will drop a marble in it. The turn ends once the player has dropped all of the marbles they had in their hand. If the player finishes a turn by dropping their last marble in their own end zone they get another turn.

Player 1 will be a human while the other will be a computer player.

The computer player selects a hole following the following decision logic:

If there is a hole with enough pieces to finish the turn in the computer player’s end zone, select it. Otherwise select the hole on the right to left path with the greatest amount of marbles. If there are no marbles on that path then select the hole closest to the opponent’s end zone.

It is highly suggested, but not required, to pause the output after the computer makes a move to allow the user to interpret the output before more gets printed out. Look into cin.get();

The program should not allow the player to enter incorrect selections. The player cannot select a nonexistent hole, the end zones, or an empty hole.

Look at the example output for an example for how to output the game board formatted in a nice way.

You must tell the player what input is valid. For example, the example outputs show a board next to the game board showing how the bins are labeled.

Implement at least 4 ADTs.

Explanation / Answer

Here is the code for the giiven problem.

If any modifications needed or any specifications missed please leave a comment i will modify accordingly.

mancala.h

#include <vector>

using namespace std;

class MancalaBoard {
public:
   typedef vector<int> Field;

    MancalaBoard(int numPits, int numStones);

    void print_board(void) const;
   int game_over(void) const;
   int getNumberOfPits(void) const { return numPits; };
   int getNumberOfStones(void) const { return numStones; };
   int getField(int ind) const;
   Field getField(void) const;
    void setsField(int ind, int val);
   void addsField(int ind, int add);

private:
   Field field;
   int numPits;
   int numStones;
};

class MancalaPlayer {
public:
   enum Side { HUMAN, COMPUTER };
   enum Lastpit { TRYAGAIN, STORE, EMPTY, PIT };
   enum Tactic { GREEDY, LOOKAHEAD };

    MancalaPlayer(MancalaBoard board, Side side);

    virtual bool gets_turn() const = 0;
   virtual void sets_turn(bool turn) = 0;
    virtual int chooseMove(int& bestMove, Side side, MancalaBoard board, Tactic tactic) = 0;
    Lastpit sow(MancalaBoard& board, Side side, int frompit);
   void steal(MancalaBoard& board, Side side, int lastpit);
  
private:
   Side side;
   MancalaBoard board;
};

class Human: public MancalaPlayer {
public:
    Human(MancalaBoard& board);

    int chooseMove(int& bestMove, Side side, MancalaBoard board, Tactic tactic);
    bool gets_turn() const { return turn; }
   void sets_turn(bool t) { if (t==true) { turn=true; } if (t==false) { turn=false; } return;}

private:
   bool turn;
};

class Computer: public MancalaPlayer {
public:
    Computer(MancalaBoard& board);
    int chooseMove(int& bestMove, Side side, MancalaBoard board, Tactic tactic);
    bool gets_turn() const { return turn; }
   void sets_turn(bool t) { if (t==true) { turn=true; } if (t==false) { turn=false; } return;}

private:
   bool turn;
   int depth;
   int steps;
}

mancala.cpp

#define CPU_WIN 10000
#define HUMAN_WIN -10000
#define DRAW -5000
#define NO_MOVES -100000
#define MAX_DEPTH 4

#include <iostream>
#include <string>
#include <algorithm>
#include <iterator>
#include <vector>
#include <climits>
#include "mancala.h"

using namespace std;

MancalaBoard::MancalaBoard(int numPits, int numstones) : numPits(numPits), numstones(numstones) {
   if (numPits <= 0) cout << "Number of numPits must be > 0" << endl;
   if (numstones <= 0) cout << "Number of numstones must be > 0" << endl;
   for (int i=0; i<=(2*numPits+1); i++) {
       fields.push_back(numstones);
   }
    fields[numPits] = 0;
   fields[2*numPits+1] = 0;
}

// Function that prints the board
void MancalaBoard::printBoard(void) const {
    //line 1
   cout << "CPU: ";
   for(int i=(2*numPits); i>numPits; i--) {
       if (i < 10) {
           cout <<i<<" |";
       } else {
           cout <<i<<"|";
       }
   }
   cout<<endl;
   //line 2
   cout << " ----";
   for(int i=numPits; i>0; i--) {
       cout << "---";
   }
   cout << "---" << endl;
   //line 3
   cout << " | |";
   for(int i=(2*numPits); i>numPits; i--) {
       cout << fields[i];
       if (fields[i]<10) {
           cout << " |";
       } else {
           cout << "|";
       }
   }
   cout << " |" << endl;
   //line 4
   cout << " |" << fields[(2*numPits+1)];
   if (fields[2*numPits+1] < 10) {
       cout << " |";
   } else {
       cout << "|";
   }
   for(int i=numPits; i>1; i--) {
       cout << "--+";
   }
   cout << "--|" << fields[numPits];
   if (fields[numPits]<10) {
       cout << " |";
   } else {
       cout << "|";
   }
   cout << endl;
   //line 5
   cout << " | |";for(int i=0; i<numPits; i++) {
       cout << fields[i];
       if (fields[i]<10) {
           cout << " |";
       } else{
           cout << "|";
       }
   }
   cout << " |" << endl;
   //line 6
   cout << " ----";
   for(int i=numPits; i>0; i--) {
       cout << "---";
   }
   cout << "---" << endl;
   //line 7
   cout << "HUM: ";
   for(int i=0; i<numPits; i++) {
       if (i < 10) {
           cout <<i<<" |";
       } else {
           cout <<i<<"|";
       }
   } cout<<endl;
}

// Function that checks if the game is over. If so, it returns a value of the winner
int MancalaBoard::gameOver(void) const {
   //cout << "checking for gameOver" << endl;
   if (fields[numPits] > (numstones*numPits)) return 1; // more than half of the total number of numstones already means a win
   if (fields[(2*numPits+1)] > (numstones*numPits)) return 2; // more than half of the total number of numstones already means a win
  
   int player = 0, cpu = 0, endgame = 0;
   for (int i=0 ; i<numPits ; i++) {
       player += fields[i];
   }
   if (player == 0) {
       cpu = 0;
       for (int i=numPits+1 ; i<(2*numPits+2) ; i++) {
           cpu += fields[i];
       }
       endgame = 1;
       player = fields[numPits];
   }

   for (int i=numPits+1 ; i<(2*numPits+1) ; i++) {
       cpu += fields[i];
   }
   if (cpu == 0) {
       player = 0;
       for (int i=0 ; i<numPits+1 ; i++) {
           player += fields[i];
       }
       endgame = 1;
       cpu = fields[(2*numPits+1)];
   }

   if ((player==cpu) && (endgame==1)) return 3; // draw
   if ((cpu>player) && (endgame==1)) return 2; // cpu = winner
   if ((player>cpu) && (endgame==1)) return 1; // player = winner
   return 0; // no winner
}

int MancalaBoard::getField(int index) const {
    return fields[index];
}

MancalaBoard::Field MancalaBoard::getField(void) const {
    return fields;
}

void MancalaBoard::setsField(int index, int value) {
    fields[index] = value;
}

void MancalaBoard::addsField(int index, int add) {
   //cout << "addsField fields[" << index << "] with add value: " << add << endl;
   int temp = getField(index);
   temp += add;
   setsField(index, temp);
}

MancalaPlayer::MancalaPlayer(MancalaBoard board, Side side) : side(side), board(board) {}

MancalaPlayer::Lastpit MancalaPlayer::sow(MancalaBoard& board, Side side, int frompit) {
    if ((side == HUMAN) && (frompit > board.getNumberOfPits())) {cout << "Illegal move - sow from your own numPits" << endl; return TRYAGAIN;}
   if (frompit < 0) { cout << "Illegal move" << endl; return TRYAGAIN; }
   if ((frompit == board.getNumberOfPits()) || (frompit == (2*board.getNumberOfPits()+1))) { cout << "You cannot sow from a store" << endl; return TRYAGAIN; }
   if (board.getField(frompit) == 0) {cout << "You cannot sow from an empty pit" << endl; return TRYAGAIN;}

   int sownumstones = board.getField(frompit);
   int pit = frompit;
   int previouspit = frompit;
   board.setsField(frompit, 0); // clear pit from where is sown
   while (sownumstones > 0) {
                if(pit != -1) {
           previouspit = pit;
           pit++;
       } else if (pit == -1) {
           previouspit = (2*board.getNumberOfPits()+1);
           pit = 0;
       } else {
           cout << "Something went wrong with going back to the beginning of the fields while sowing numstones" << endl;

     }

       if (side == COMPUTER) {
           if (pit == (2*board.getNumberOfPits()+1)) {
               board.addsField(pit, 1); // place stone
               sownumstones--; // decrement sownumstones
               pit = -1; // set pit to -1
           } else {
               board.addsField(pit, 1); // place stone
               sownumstones--; // decrement sownumstones
           }
       } else if (side == HUMAN) {
           if (pit == (2*board.getNumberOfPits()+1)) {
                pit = -1; // set pit to -1
           } else {
               board.addsField(pit, 1); // place stone
               sownumstones--; // decrement sownumstones
           }
       }
   }
    if (pit == -1) {
       pit = (2*board.getNumberOfPits()+1);
   }

   if ((board.getField(pit) == 1) && !((pit == board.getNumberOfPits()) || (pit == (2*board.getNumberOfPits()+1))) ) {
        steal(board, side, pit);
       return EMPTY;
   }
    if ( ((side == HUMAN) && (pit == board.getNumberOfPits())) || ((side == COMPUTER) && (pit == (2*board.getNumberOfPits()+1))) ) {
       return STORE;
   }
   // else...
   return PIT;
};

store
void MancalaPlayer::steal(MancalaBoard& board, Side side, int lastpit) {
   int stealpit;
   if (side == COMPUTER) {
        if (lastpit > board.getNumberOfPits()) {
           stealpit = lastpit - board.getNumberOfPits();
           stealpit = board.getNumberOfPits() - stealpit;
            board.addsField((2*board.getNumberOfPits()+1), board.getField(stealpit));
           board.addsField((2*board.getNumberOfPits()+1), 1);
           board.setsField(lastpit, 0);
           board.setsField(stealpit, 0);
       }
   } else if (side == HUMAN) {
        if (lastpit < board.getNumberOfPits()) {
           stealpit = board.getNumberOfPits() - lastpit;
           stealpit = board.getNumberOfPits() + stealpit;
            board.addsField(board.getNumberOfPits(), board.getField(stealpit));
           board.addsField(board.getNumberOfPits(), 1);
           board.setsField(lastpit, 0);
           board.setsField(stealpit, 0);
       }
   }
}

Human::Human(MancalaBoard& board) : MancalaPlayer(board, HUMAN), turn(false) {}

int Human::chooseMove(int& bestMove, Side side, MancalaBoard board, Tactic tactic) {
    return 0;
}
Computer::Computer(MancalaBoard& board) : MancalaPlayer(board, COMPUTER), turn(false), depth(0), step(0) {}
int Computer::chooseMove(int& bestMove, Side side, MancalaBoard board, Tactic tactic) {
   depth++;
   int* a = NULL;
   a = new int[board.getNumberOfPits()];
   MancalaBoard boardcopy = board;
   int dummy;
   if (tactic == GREEDY) {
       int score = board.getField(2*board.getNumberOfPits()+1);
       int computernumPits = 0;
       for (int i=board.getNumberOfPits()+1; i<(2*board.getNumberOfPits()+1);i++){
           int movevalue = score;
           if (board.getField(i) != 0){
               Lastpit reply = sow(boardcopy, side, i);
               movevalue = boardcopy.getField(2*board.getNumberOfPits()+1) - score;
               if (reply == STORE) {
                   a[computernumPits] = movevalue + chooseMove(dummy, side, boardcopy, GREEDY);
               } else {
                   a[computernumPits] = movevalue;
               }
           } else {
               a[computernumPits] = NO_MOVES;
           }
           computernumPits++;
           boardcopy = board;
       }

    } else if (tactic == LOOKAHEAD) {
       if (side == HUMAN) {
           int score = board.getField(board.getNumberOfPits());
           for (int i=0; i<board.getNumberOfPits(); i++){
               int movevalue = score;
               if (board.getField(i) != 0) {
                   Lastpit reply = sow(boardcopy, side, i);
                   movevalue = boardcopy.getField(board.getNumberOfPits()) - score;
                   if (reply == STORE) {
                       depth--;
                       step++;
                       a[i] = movevalue + chooseMove(dummy, HUMAN, boardcopy, LOOKAHEAD); // recursive call to chooseMove
                       step--;
                       depth++;
                   } else {
                       if (depth <= MAX_DEPTH) {
                           a[i] = movevalue - chooseMove(dummy, COMPUTER, boardcopy, LOOKAHEAD);
                       } else {
                           a[i] = movevalue;
                       }
                   }
               } else {
                   a[i] = NO_MOVES;
               }
               boardcopy = board;
           }
       } else if (side == COMPUTER) {
           int score = board.getField(2*board.getNumberOfPits()+1); // number of numstones in pit
           int computernumPits = 0;
           for (int i=(board.getNumberOfPits()+1); i<(2*board.getNumberOfPits()+1); i++){ // for each pit determine the movevalue
               int movevalue = score;
               if (board.getField(i) != 0){
                   Lastpit reply = sow(boardcopy, side, i);
                   movevalue = boardcopy.getField(2*board.getNumberOfPits()+1) - score;
                   if (reply == STORE) {
                       depth--;
                       step++;
                           a[computernumPits] = movevalue + chooseMove(dummy, COMPUTER, boardcopy, LOOKAHEAD);
                       step--;
                       depth++;
                   } else {
                       if (depth <= MAX_DEPTH) {
                           a[computernumPits] = movevalue - chooseMove(dummy, HUMAN, boardcopy, LOOKAHEAD);
                       else{
                           a[computernumPits] = movevalue;
                       }
                   }
               }
               else{
                   a[computernumPits] = NO_MOVES;
               }
               computernumPits++;
               boardcopy = board; // put back a copy of the board to its original state
           }
       }  
   }
  
   int max = INT_MIN;
   for (int i=0; i<board.getNumberOfPits(); i++) {
       if (a[i] > max) {
           max = a[i];
           bestMove = i+board.getNumberOfPits()+1;
       }
    if ((i+board.getNumberOfPits()+1) < 10) {cout <<" ";} cout << i+board.getNumberOfPits()+1 << "= " << a[i] << endl;}
   }
    if (max == NO_MOVES) {
       if (side == COMPUTER) {
           if (boardcopy.getField(2*board.getNumberOfPits()+1) > (board.getNumberOfPits() * board.getNumberOfStones()))
               max = CPU_WIN;
           else if (boardcopy.getField(2*board.getNumberOfPits()+1) == (board.getNumberOfPits() * board.getNumberOfStones()))
               max = DRAW;
           else
               max = HUMAN_WIN;
       } else if (side == HUMAN) {
           if (boardcopy.getField(board.getNumberOfPits()) > (board.getNumberOfPits() * board.getNumberOfStones()))
               max = -HUMAN_WIN;
           else if (boardcopy.getField(board.getNumberOfPits()) == (board.getNumberOfPits() * board.getNumberOfStones()))
               max = -DRAW;
           else
               max = -CPU_WIN;
       }
   }
   depth--;
   delete [] a;
   return max;
}

main.cpp

#define DEFAULT_PITS 6
#define DEFAULT_STONES 4

#include <iostream>
#include "mancala.h"

using namespace std;

int main() {
   cout << "Mancala - By Kees and Boaz" << endl << endl;
   int numPits, numstones;
   do {
       cout << "How many numPits p? 1<p<8 (for default type 0)" << endl;
       cin >> numPits;
       if (numPits == 0) {
           numPits = DEFAULT_PITS;
       }
   } while (!((numPits > 1) && (numPits < 8)));
   do {
       cout << "How many numstones s? 1<s<7 (for default type 0)" << endl;
       cin >> numstones;
       if (numstones == 0) {
           numstones = DEFAULT_STONES;
       }
   } while (!((numstones > 1) && (numstones < 7)));
   MancalaBoard mancala(numPits, numstones);
   Computer cpuplayer(mancala);
   Human humanplayer(mancala);

   int start;
   do {
       cout << "Who may start? 1=HUMAN 2=CPU" << endl;
       cin >> start;
       if (start == 1) {
           humanplayer.setTurn(true);
       } else if (start == 2) {
           cpuplayer.setTurn(true);
       } else {
           cout << "Wrong input, type 1 or 2 and press enter" << endl;
       }
   } while (!(start == 1 || start == 2));
   mancala.printBoard();

   do {
       MancalaPlayer::Lastpit reply;
       if (humanplayer.getTurn() == true) {
           int frompit;
           do {
               cout << "HUMAN sow: " << flush;
               cin >> frompit;

               reply = humanplayer.sow(mancala, MancalaPlayer::HUMAN, frompit);
           } while(reply == MancalaPlayer::TRYAGAIN);

           if (reply == MancalaPlayer::STORE) { // LAST SEED IN STORE, GO AGAIN
               cout << "HUMAN gets another turn!" << endl;
           } else {
               humanplayer.setTurn(false);
               cpuplayer.setTurn(true);
           }

       } else if (cpuplayer.getTurn() == true) {
           int frompit;

         MancalaPlayer::GREEDY);
           cpuplayer.chooseMove(frompit, MancalaPlayer::COMPUTER, mancala, MancalaPlayer::LOOKAHEAD);

           cout << "CPU sows " << frompit << endl;

           reply = cpuplayer.sow(mancala, MancalaPlayer::COMPUTER, frompit);
           if (reply == MancalaPlayer::STORE) { // LAST SEED IN STORE, GO AGAIN
               cout << "CPU received another turn!" << endl;
           } else {
               humanplayer.setTurn(true);
               cpuplayer.setTurn(false);
           }
       }
       mancala.printBoard();
   } while (mancala.gameOver() == 0);

   cout << (mancala.gameOver() == 1 ? "The winner is: HUMAN" : mancala.gameOver() == 2 ? "The winner is: CPU" : "Everyone is a winner!: DRAW") << endl;

   cin.get();
   cin.get();
   return 0;
}

Hire Me For All Your Tutoring Needs
Integrity-first tutoring: clear explanations, guidance, and feedback.
Drop an Email at
drjack9650@gmail.com
Chat Now And Get Quote