#include <cstdlib>
#include <iostream>
#include <string>
#include <ctime>
#include <cmath>
using namespace std;
int user_play(int &pile);
int computer_play(int &pile);
int power_of_2(int n);
int main(int argc, char *argv[])
{
string ans, mode;
srand(time(NULL)); //generates a random number from 10 to 100//
do{
cout<<"Welcome to the Game of Nim!!"<<endl<<endl //welcome message and displays rule for user//
<<"Rules: The number of stones you take away must be between 1 and"<<endl
<<"half of the total pile inclusive. "<<endl
<<"The one who takes the last marble loses. "<<endl<<endl;
int pile = rand()%91+10;
cout<<"The game starts out with a size of "<<pile<<" stones.\n";
int player1 = rand()%2; //generates a random number between 0 and 1 to see who goes first//
if (player1 == 0) //if 0 then comp goes first, 1 then you go first//
cout<<"The computer gets to go first. \n";
else
cout<<"You go first. \n";
cout<<"Choose the mode for the computer, naive or smart? "; //asks user to input computer's difficulty level//
cin.ignore();
getline(cin, mode);
cout<<endl;
int nim = pile;
while (nim !=1) /*game stops when the pile size of the marble is 1, in which case
the last one forced to loot the marble loses*/
{
if (player1 ==1)
{
user_play(nim);
player1 = player1==0 ? 1 : 0;
}
else
{
computer_play(nim);
player1 = player1==0 ? 1 : 0;
}
}
if (player1 ==1)
{
cout<<"\nYou are forced to take the last marble, \nTHE COMPUTER WINS! Better luck next time!\n"; //game result and congrats player if he wins//
}
else
{
cout<<"\nThe computer is forced to take the last marble, YOU WIN!\n";
}
cout<<"\nDo you want to play again? "; //asks the player if he wishes to play the game again//
cin.ignore();
getline(cin,ans);
cout<<endl;
}while((ans,"yes")||(ans,"y"));
system("PAUSE");
return EXIT_SUCCESS;
}
int user_play(int &pile) /* Obtain the remaining marble count as input (use a reference parameter!)
ask the player the number of stones he would like to remove
validate the response, and repeat the request until a valid input is entered
modify the remaining marble count parameter.*/
{
int stones;
int tries = 10000000;
while(tries !=0)
{
cout<<"Enter the number of marble(s) you wish to take away: ";
cin>>stones;
if (1 <= stones && stones <= pile/2)
{
pile = pile - stones;
cout<<"There is/are "<<pile<<" marble(s) left. "<<endl;
tries = 0;
}
else
{
cout<<"Error! Please enter a number between 1 and "<<pile/2<<" inclusive. \n";
tries --;
}
}
}
int computer_play(int &pile) /* This function should obtain the remaining marble count and the play mode (naive/smart) as input
calculate and display the number of stones that the computer removes (according to the play mode)
in smart play mode only: obtain successive values of (2^n - 1) as needed
modify the remaining marble count parameter. */
{
string mode;
if((mode, "naive")||(mode,"n"))
{
int stones = rand()%(pile/2)+1;
pile = pile - stones;
cout<<"The computer took away " <<stones<<" nim marble(s).\n"
<<"There is/are "<<pile<<" nim marble(s) left. \n\n";
}
else
{
int stones = power_of_2(pile);
pile = pile - stones;
cout<<"The computer took away " <<stones<<" nim marble(s).\n"
<<"There is/are "<<pile<<" nim marble(s) left. \n"<<endl;
}
}
int power_of_2(int x) /* this helper function should
given an integer n, return the value (2^n - 1)
for use by the function computer_play, in smart mode only. */
{
if(x==2)
return 1;
int i = -1;
while((int)pow(2.0,i++) < x);
i--;
return ((int)pow(2.0, i) - 1);
}