Ask Question

Name:
Title:
Your Question:

Answer Question

Name:
Your Answer:
User Submitted Source Code!


Description:
  NineMorris
Language: C/C++
Code:
#include <iostream>
#define ITERATIONS 3
using namespace std;

// Globals
char b[78];
int depth=0;
int coordAlpha,coordBeta;
char currentPlayer='X';
char enemyPlayer='O';
int X_toPlace=9;
int O_toPlace=9;
int currentTurn=0;


void displayBoard(char* x)
{
    cout <<"    1   2   3   4   5   6   7\n\n A  "<<x[11]<<"..........."<<x[14]<<"..........."<<x[17]<<"  A    Player "<<currentPlayer<<"'s move...\n    .           .           .\n B  .   "<<x[22]<<"......."<<x[24]<<"......."<<x[26]<<"   .  B\n    .   .       .       .   .\n C  .   .   "<<x[33]<<"..."<<x[34]<<"..."<<x[35]<<"   .   .  C\n    .   .   .       .   .   .\n D  "<<x[41]<<"..."<<x[42]<<"..."<<x[43]<<"       "<<x[45]<<"..."<<x[46]<<"..."<<x[47]<<"  D\n    .   .   .       .   .   .\n E  .   .   "<<x[53]<<"..."<<x[54]<<"..."<<x[55]<<"   .   .  E\n    .   .       .       .   .\n F  .   "<<x[62]<<"......."<<x[64]<<"......."<<x[66]<<"   .  F\n    .           .           .\n G  "<<x[71]<<"..........."<<x[74]<<"..........."<<x[77]<<"  G\n\n    1   2   3   4   5   6   7\n";
}

void nextTurn(){char temp; temp=currentPlayer; currentPlayer=enemyPlayer; enemyPlayer=temp;}

void array_AtoB(char* A,char* B){int i; for(i=0;i<78;i++){B[i]=A[i];}}

int checkStage ()
{
        if (currentPlayer=='X' && X_toPlace>0){return 1;}
        if (currentPlayer=='O' && O_toPlace>0){return 1;}
        else {return 2;}
}

int charsOnBoard(char matcher, char testArray[78])
{
    int i,count=0; for(i=0;i<78;i++){ if(testArray[i]==matcher){++count;} }
    return count;
}


int nextCoord (int coord, int dir, char* board)
{
        while(coord>10 && coord<78 && (coord%10)<8 && (coord%10)>0 && coord!=44)
        {
        coord=coord+dir;
        if (board[coord]!='n'){return coord;}
        }
        return 0;
}

void makeMove (int A, int B, char* board)
{
        if (A==B)
        {
        board[A]=currentPlayer;
        if(currentPlayer=='X'){X_toPlace+=-1;}
        if(currentPlayer=='O'){O_toPlace+=-1;}
        }
        if (A!=B)
        {
        board[A]='.';board[B]=currentPlayer;
        }
}

int isMill(int coord,char board[78],char player)
{
        int originalCoord=coord, i=1, count=1;
    //test x-axis
    if (board[coord]=='n') {return 0;}
    while( (coord%10)>0 && coord!=44 )
    {
        if ( (coord%10)>6 || coord==43 ) {i=-1;}
        coord=originalCoord+i;
        i= i>0 ? i+1 : i-1;
        if (board[coord]==player) {++count;}
    }
        if (count==3) {return 1;}
        //test y-axis
        count=1; i=1;
    while( coord>10 && coord!=44)
    {
        if ( coord>70 || coord== 34) {i=-1;}
        coord=originalCoord+(10*i);
        i= i>=0 ? i+1 : i-1;
        if (board[coord]==player) {++count;}
    }
        if (count==3) {return 1;}
        return 0;
}

void ai_findAllMoves (char t[78], int* moves)
{
        int i,j,dir=1,secondCoord,m=0;
        if (checkStage()==1)
        {
                for(i=11;i<78;i++)
                {
                        if (t[i]=='.') {moves[m]=i;++m;moves[m]=i;++m;}
                }
        }
        if (checkStage()==2){for(i=11;i<78;i++){
            if (t[i]==currentPlayer)
            {
                for(j=0;j<4;j++)
                {
                        switch(j){case 0:dir=1;break;case 1:dir=-1;break;case 2:dir=10;break;case 3:dir=-10;break;}
                        secondCoord=nextCoord(i,dir,t);
                        if ( t[secondCoord]=='.' ){moves[m]=i;++m;moves[m]=secondCoord;++m;}
                }
            }
        }}
}


void ai_millMove(char board[78])
{
    char millTarget,k,millCount=0;
    for(k=11;k<78;k++)
    {
        if(board[k]==enemyPlayer){millCount+=isMill(k,board,enemyPlayer);}
    }
    if( millCount==charsOnBoard(enemyPlayer,board) )
    {
        do{millTarget=(rand()%78)+1;}while( board[millTarget]!=enemyPlayer );
    }
    else do{millTarget=(rand()%78)+1;}while( board[millTarget]!=enemyPlayer || isMill(millTarget,board,enemyPlayer) );
    board[millTarget]='.';
}


int heuristic_neighbor(char coordToken)
{
        if (coordToken=='.'){return 4;}
            if (coordToken==currentPlayer){return 10;}
            if (coordToken==enemyPlayer){return 6;}
            return 0;
}

int heuristic(char board[78])
{
    int i,Xs,Os,hVal=0;
    Xs=charsOnBoard('X',board);
    Os=charsOnBoard('O',board);
    hVal= currentPlayer=='X' ? ( (20*Xs)-(16*Os) ) : ( (20*Os)-(16*Xs) );
    for(i=11;i<78;i++)
        {
        if(board[i]==enemyPlayer)
        {
            if ( isMill(i,board,enemyPlayer) ) {hVal+=-15;}
        }
        if(board[i]==currentPlayer)
        {
            if ( isMill(i,board,enemyPlayer) ) {hVal+=40;}
            if ( isMill(i,board,currentPlayer) ) {hVal+=20;}
            hVal+=heuristic_neighbor(board[nextCoord(i,1,board)]);
            hVal+=heuristic_neighbor(board[nextCoord(i,-1,board)]);
            hVal+=heuristic_neighbor(board[nextCoord(i,10,board)]);
            hVal+=heuristic_neighbor(board[nextCoord(i,-10,board)]);
        }
        }
    return hVal;
}


int ai_getMove(char board[78])
{
    int store_X_toPlace=X_toPlace, store_O_toPlace=O_toPlace;
    char t[78];
    int moves[70]={0};
    int h_new=0,h_best=-6666;
    
    ++depth;

    ai_findAllMoves(board,moves);

    int i;
    for(i=0;i<35;i++){if(moves[i*2]>10)
    {
        array_AtoB(board,t);
        makeMove(moves[i*2],moves[i*2+1],t);

        if ( isMill(moves[i*2],t,currentPlayer) )
        {
            ai_millMove(t);
        }

        if(depth<ITERATIONS)
        {
            nextTurn();
            h_new=ai_getMove(t);
            nextTurn();
            if(depth!=1)
            {
                if (h_best==-6666) {h_best=h_new;} // for first iteration
                if ( (depth%2)==1 ){ if(h_new>h_best){h_best=h_new;} }
                if ( (depth%2)==0 ){ if(h_new<h_best){h_best=h_new;} }
            }
            if(depth==1)
            {
                if(h_new>=h_best){h_best=h_new; coordAlpha=moves[i*2]; coordBeta=moves[i*2+1];}
            }
        }
        if(depth==ITERATIONS)
        {
            h_new=heuristic(t);
            if (h_new>h_best){h_best=h_new;}
        }
        X_toPlace=store_X_toPlace; O_toPlace=store_O_toPlace;
    }}
    if(depth>1) {--depth; return h_best;}
    if(depth==1){--depth; return 0;}
        else{cout<<"\n * * ERROR!!! * *\n"; return 0;}
}

int gameIsOver()
{
    if ( (charsOnBoard('X',b) + X_toPlace)<3 ) {cout<<"\n\n Player O wins in "<<currentTurn<<" moves ! ! ! \n\n"; return 1;}
    if ( (charsOnBoard('O',b) + O_toPlace)<3 ) {cout<<"\n\n Player X wins in "<<currentTurn<<" moves ! ! ! \n\n"; return 1;}
    return 0;
}

int input_to_coord(string input)
{
    int coord;
    input[0]=tolower(input[0]);
    coord= ( 10 * (input[0]-'a'+1) ) + input[1]-'1'+1;
    return coord;
}


int main(){
fill_n(b, 78, 'n');
b[11]=b[14]=b[17]=b[22]=b[24]=b[26]=b[33]=b[34]=b[35]=b[41]=b[42]=b[43]=b[45]=b[46]=b[47]=b[53]=b[54]=b[55]=b[62]=b[64]=b[66]=b[71]=b[74]=b[77]='.';
char human_player;
string inputA,inputB;

//  Call srand once
srand(time(0));



cout<<"Welcome.  Please select your player.\n\n  X (play as \"X\")\n  O (play as \"O\")\n  C (watch the computer duke it out against itself)\n";
do{++currentTurn; if (currentTurn>1){cout<<" * * * please check your input * * *\n";} cin>>human_player;}while(human_player!='C' && human_player!='O' && human_player!='X');
if (human_player=='C') {cout<<"        ENGAGE!!! \n\n";}
if (human_player!='C') {cout<<"Alright, pathetic 'human' player "<<human_player<<", get ready...\n\n";}


    do{
        // love for computers and humans
        displayBoard(b);
        ++currentTurn;


        // HUMANS ONLY
        if (currentPlayer==human_player)
        {
            if(checkStage()==1)
            {
                cout<<"Player "<<currentPlayer<<" has "; if(currentPlayer=='X'){cout<<X_toPlace;}else{cout<<O_toPlace;}cout<<" pieces to place.  Your move: ";
                do
                {
                    cin>>inputA;
                    coordAlpha=input_to_coord(inputA);
                } while ( b[coordAlpha]!='.' );
                coordBeta=coordAlpha;
            }
            if(checkStage()==2)
            {
                cout<<"Player "<<currentPlayer<<", wake up, it's your move: ";
                do
                {
                    cin>>inputA>>inputB;
                    coordAlpha=input_to_coord(inputA);
                    coordBeta=input_to_coord(inputB);
                } while ( b[coordAlpha]!=currentPlayer || b[coordBeta]!='.' );
            }
            makeMove(coordAlpha,coordBeta,b);
            if( isMill(coordBeta,b,currentPlayer) )
            {
                displayBoard(b);
                cout<<"You have formed a Mill!  Wow!  Enter opponent's piece to remove: ";
                do
                {
                    cin>>inputA;
                    coordAlpha=input_to_coord(inputA);
                } while ( b[coordAlpha]!=enemyPlayer );
                b[coordAlpha]='.';
            }
        } // [end human trash]

        // AI SECTION
        else
        {
            cout<<"\nThe computer made a move.\n\n";
            ai_getMove(b);
            makeMove(coordAlpha,coordBeta,b);
            if ( isMill(coordBeta,b,currentPlayer) )
            {
                displayBoard(b);
                cout<<"Computer has formed a MILL!  Computer rules!\n";
                ai_millMove(b);
            }
        }
        // back to the love...
        nextTurn();
    }while( !gameIsOver() );


system("PAUSE");
return 0;
}
Comments: