Counetrfeit Coin Game

np complete 0 Tallied Votes 356 Views Share

What is it : A simple logic (text based) game, in which you are required to identify the counterfeit coin within 3 chances.

How it works : You are given 'x' coins ( best is to play it with 12 coins ). You are asked how many coins you want to put in Pan 1. You enter 'y' amount of coins. Then same process with Pan 2. After that, it shows which Pan is heavier, for example if Pan 1 is heavier than Pan 2 then it shows, ' Pan 1 > Pan 2 '. Then using this information you need to identify the 'bad' coin ( using suitable algorithm if you want ) within 3 chances.

Disclaimer : This is my first code snippet that I'm submitting in this forum under C++. So if there is any error/improvement please let me know. It would really be nice of you and would help me build my programming skill. Thanks.

/*****
Counterfeit Coin Game

Coder : np complete
Build in : MinGW compiler
IDE : code::blocks
DATE : 19/8/2012
LICENSE :

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

Disclaimer : If there is any error, please inform 'np complete',
email : abhi.workspace@gmail.com.

*****/

# include <iostream>
# include <cstring>
# include <ctime>
# include <cstdlib>

# define coinVal 2;

using namespace std;

void gameInfo(); // Takes is Game input, eg Number of coins etc
void generateGame(); // Generates the game, assigns a random index with different value
void playGame(); // The actual playing function

int coins, counterfeitCoin;
char typeOfCounterfeit; // light conterfeit coin or heavy or random ( heavy/light)

int main()
{
    char ans = 'y';
    do
    {
       gameInfo();
       generateGame();

       cout<<"\n Play again ? (Y/N) : ";
       cin>>ans;
    }while(ans=='y'||ans=='Y');
}

void gameInfo()
{
    cout<<"\n Enter number coins(max 12) : ";
    cin>>coins;

    cout<<"\n Press (H) for heavy counterfeit, (L) for light\n and (A) for computer to decide : ";
    cin>>typeOfCounterfeit;
}

void playGame(int coinTab[])
{
    cout<<"\n You will get 3 chance to identify the 'bad' coin ";

    int pan1, pan2, sum1=0, sum2=0, answer;

    for(int i=0 ; i<3 ; i++)
    {
        cout<<"\n Enter number of coins in Pan 1 : ";
        cin>>pan1;

        cout<<"\n Pan 1 = ";
        int input1[pan1];

        int j=0;

        while(j<pan1)
        {
            cin>>input1[j];
            j++;
        }

        cout<<"\n Enter number of coins in Pan 2 : ";
        cin>>pan2;

        cout<<"\n Pan 2 = ";
        int input2[pan2];

        j=0;

        while(j<pan2)
        {
            cin>>input2[j];
            j++;
        }

        sum1=0;

        for(int k=0; k<pan1; k++)
        {
            sum1 = sum1 + coinTab[input1[k]-1];
        }

        sum2=0;

        for(int k=0; k<pan2; k++)
        {
            sum2 = sum2 + coinTab[input2[k]-1];
        }

        if(sum1>sum2)
        {
            cout<<"\n Pan 1 > Pan 2";
        }

        else if( sum1<sum2)
        {
            cout<<"\n Pan 1 < Pan 2";
        }
        else
        {
            cout<<"\n Pan 1 = Pan 2";
        }
    }

    cout<<"\n Enter answer : ";
    cin>>answer;

    if((answer-1)==counterfeitCoin)
    {
        cout<<"\n Correct Answer";
    }
    else
    {
        cout<<"\n Wrong Answer";
        cout<<"\n Answer is coin number "<<counterfeitCoin+1;
    }
}

void generateGame()
{
    int *coinTable = new int[coins]; // dynamically create an int array

    for(int i=0; i<coins; i++)
    {
        coinTable[i] = coinVal; // assign them with coinVal = 2
    }

    srand ( time(NULL) );

    counterfeitCoin = rand() % coins; // selects a random index from making that counterfeit

    if(typeOfCounterfeit=='H') // heavy counterfeit coin
    {
        coinTable[counterfeitCoin] = 3;

    }

    else if(typeOfCounterfeit=='A') // random counterfeit coin
    {
        srand ( time(NULL) );

        int x = rand() % 10;

        if(x%2==0)
        {
            coinTable[counterfeitCoin] = 3;
        }
        else
        {
            coinTable[counterfeitCoin] = 3;
        }

    }

    else //light counterfeit coin
    {
        coinTable[counterfeitCoin] = 1;
    }

    playGame(coinTable);

    delete coinTable;

}
// end of code
WaltP 2,905 Posting Sage w/ dash of thyme Team Colleague

Not bad...

Here are some possible things you could consider for improvements:

------------------
Because coinval is a #define it should be in all caps. And while you're at it, define the heavy and light values too:

#define COINVAL 2
#define COINHEAVY 3
#define COINLIGHT 1

Also, make the values for typeOfCounterfeit into #defines as well:

#define TYPELIGHT 'L'
#define TYPEHEAVY 'H'
#define TYPEANY   'A'

These changes remove the need to use hard coded values in the code itself and you can make modifications very quickly and accurately by not searching through the code.

------------------
The function gameInfo() might be better named gameInitialize()

------------------
If you want to limit the number of coins to 12,
1) test for invalid values
2) don't make the array dynamic -- it's a waste of time and you won't need the delete

------------------
At the prompt "Press (H) for heavy counterfeit, (L) for light\n and (A) for computer to decide : ", what happens if you press K, or h, or a? Test for valid values.

------------------
All but the calls at the bottom of gameGenerate() could be put into gameInitialize() since it's all initialization.

------------------
The calls to srand() should ideally be placed at the top of main(), and only once.

------------------
For the test of typeOfCounterfeit you can use a switch(). It would make that section of code more compact.
Another option to testing 3 possibilities for typeOfCounterfeit is test for 'A' then use rand() to change it to 'L' or 'H', then do the test.

------------------
For 'A', why get a random number from 0-9 and test %2? Why not get a random number 0-1 (rand() % 2) and test if 0 or 1?

------------------
The calls at the bottom of gameGenerate() should be placed in main().
gameGenerate() sets up the game, so it shouldn't play the game.

------------------

In general, whitespace is your friend. Use it more. Compare these lines:

while(j<pan1)
if(sum1>sum2)
if((answer-1)==counterfeitCoin)
else if(typeOfCounterfeit=='A') // random counterfeit coin

with these:

while (j < pan1)
if (sum1 > sum2)
if ((answer - 1) == counterfeitCoin)
else if (typeOfCounterfeit == 'A')        // random counterfeit coin

Note the readability is better.

------------------

In playGame() you ask for number of coins in pan 1 and 2, then loop for inputs for unknown (to the user) reasons. You never tell us what these inputs are for. And you blindly wait and the user has no idea the program is waiting for input. We think the program crashed. Instead of:

    j=0;
    while(j<pan2)
    {
        cin>>input2[j];
        j++;
    }

You probably want something like:

    j=0;
    cout << "Which coins? " << endl ;
    while(j<pan2)
    {
        cout << "Enter coin number " << j+1 << ":" ;
        cin>>input2[j];
        j++;
    }

------------------

Just some ideas to think about.

np complete 8 Newbie Poster

Thanks waltP for reading my code and for all these suggestions. I will definitely make these changes.

np complete 8 Newbie Poster

The calls to srand() should ideally be placed at the top of main(), and only once.

Is this necessary ? I mean will my code run improperly? Would be please elaborate. Thanks.

WaltP 2,905 Posting Sage w/ dash of thyme Team Colleague

The calls to srand() should ideally be placed at the top of main(), and only once.

Is this necessary ? I mean will my code run improperly? Would be please elaborate. Thanks.

Yes. srand() initializes the random generator. It does not need to be initialized more than once. The way you have them now it's probable that the two initializations will happen within the same second. That guarantees the same random numbers.

So, if you call srand() at exactly 10:53:20 and get 10 random numbers you might get
1 5456 812 32700 1325 54 622 29953 2 9834

If all that takes less than 1 second, your next call will happen at 10:53:20 and the next 10 random numbers will be:
1 5456 812 32700 1325 54 622 29953 2 9834

Not very random, eh?
So calling srand() must be done only once at or near the beginning of the program -- at the top of main() or in an initialization function that is guaranteed to be called only when the program starts.

Try this:

#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;

int main()
{
    int rnd;
    int i;
    int j;

    for (j=0; j<4; j++)
    {
        srand(time(NULL));
        cout << "Test #" << j << ":  ";
        for (i=0; i<12; i++)
            cout << rand() << " ";
        cout << endl;    
    }

    return 0;
}

Then move the srand() outside the loop and run it again.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.