### Not sure about the results

I'm not sure about the results to this problem

3 guys are shooting each other one has a 33% (Aaron) chance of hitting, one 50% (Bob), and one 100% (Charlie)
they shoot in order weakest to strongest shooting at the most deadly
who should win the most
looped through about a 1000 times

My Results Show:
Aaron's Wins: 362
Bob's Wins: 434
Charlie's Wins: 204

Aaron's Win Percentage: 36.2
Bob's Win Percentage: 43.4
Charlie's Win Percentage: 20.4

My Teacher's Results Show:
Aaron's Wins: 215
Bob's Wins: 340
Charlie's Wins: 445

Aaron's Win Percentage: 21.5
Bob's Win Percentage: 34
Charlie's Win Percentage: 44.5

Obviously there can be a slight variance in the results, not this great however. I've been over my code several times and tried to find a problem then showed it to my teacher. He said he did the code very differently, and did see some simple errors, but after fixing those and checking through even more I can not see what I did wrong. I'm not sure if I'm wrong or if perhaps my teacher created his code incorrectly.

Here's my code. What do you think?

 ``123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123`` `````` #include #include #include using namespace std; void shoot(bool& targetalive, double accuracy); //simulates one shot int startDuel(); // returns a winner for each iteration bool charlielive, boblive, aaronlive; //global variables for ease of use in functions double characc= 1, bobacc= 0.5, aaronacc= (1/3.0); //whether the player is alive or dead and their accuracies int main() { srand(time(0)); //seeds for the randomizer in void function double charpercent,bobpercent,aaronpercent; int charwin=0, bobwin=0,aaronwin=0,i,winner,alldead=0; for (i=1;i<=1000;i++) //loops 1000 times { charlielive=true; //resets all players as living boblive=true; aaronlive=true; winner= startDuel(); //plays one round if (winner == 1) //adds to an accumulator the winner aaronwin += 1; if (winner == 2) bobwin += 1; if (winner == 3) charwin += 1; if (winner == 4) alldead += 1; } charpercent=(charwin / 1000.0) * 100; //calculates percentage bobpercent=(bobwin / 1000.0) * 100; aaronpercent=(aaronwin / 1000.0) * 100; cout<< "Aaron's Wins: " << aaronwin << endl; //displays results cout<< "Bob's Wins: " << bobwin << endl; cout<< "Charlie's Wins: " << charwin << endl << endl; cout<< "Aaron's Win Percentage: " << aaronpercent << endl; cout<< "Bob's Win Percentage: " << bobpercent << endl; cout<< "Charlie's Win Percentage: " << charpercent << endl << endl; return 0; } int startDuel() { int result=0; //while loop checking if all or at least 2 players are alive while (((charlielive==true) && (aaronlive==true) && (boblive==true)) || ((charlielive==true) && (aaronlive==true) && (!boblive==true)) || ((aaronlive==true) && (boblive==true) && (!charlielive==true)) || ((charlielive==true) && (boblive==true) && (!aaronlive==true))) { if ((charlielive==true) && (aaronlive==true) && (boblive==true)) { shoot(charlielive, aaronacc); // if all alive aaron shoots charlie if charlie lives bob shoots charlie if aaron kills charlie if (charlielive==true) // bob shoots at aaron shoot(charlielive, bobacc); else shoot(aaronlive,bobacc); if (charlielive==true) shoot(boblive, characc); } if ((!charlielive==true) && (boblive==true) && (aaronlive==true)) { shoot(boblive, aaronacc); //for the rest if two players live than the first shoots and if (boblive==true) // if the second is alive he shoots back shoot(aaronlive, bobacc); //breaks loop if only one is alive (recently added didn't affect results) else break; } if ((charlielive==true) && (!boblive==true) && (aaronlive==true)) { shoot(charlielive, aaronacc); if (charlielive==true) shoot(aaronlive, characc); else break; } if ((charlielive) && (!aaronlive==true) && (boblive==true)) { shoot(charlielive, bobacc); if (charlielive==true) shoot(boblive, characc); else break; } } if ((!charlielive==true) && (!boblive==true) && (aaronlive==true)) result=1; else if ((!charlielive==true) && (boblive==true) && (!aaronlive==true)) result=2; else if ((charlielive==true) && (!boblive==true) && (!aaronlive==true)) result=3; return result; } void shoot(bool& targetalive, double accuracy) { double attack; attack=(rand() % 100) * .01; //picks random number between 0 and 1 if (attack < accuracy) //if attack is less than accuracy targetplayer is dead targetalive= false; } ``````
anyone?
I have one suggestion on line 60-62 couldn't you just put
 ``12`` ``````while(charlielive || arronlive || boblive){ //does loop as long as one of them is alive ``````

I haven't tried it but it seems like that is what you are trying to do.

ps when you are doing if and other statements with a boolean you can just put the variable name like `if(charlielive) //do stuff; ` if you want to know if it is true you don't have to put == true. Oh and I would probably use a switch or a few switches instead of using all the if/else if statements but that's just how I would do it. Other than that I am not sure exactly the problem. sorry
What about an unsigned NumAlive variable? Initialise it to 3, then decrement it when someone dies, then have:

 ``123`` ``````while ( NumAlive >= 2 ) { //your code }``````

What giblit is saying about bool variables is right, you would either have `if (MyBool)` or `if ( !MyBool )` or `if (conditional expression)` or `if ( !conditional expression)`

@giblit switches only work for constant integral values like int or char - there is no point in having them for bool types or conditionals because there are only 2 options.

@Rogge

Try to avoid using global variables - declare them in main() & send references to which ever function needs them.

So lines 63 - 72 are when all 3 are alive and lines 74 - 101 are if 1 is dead --> 1 if else statement.

For the else part you can now have 3 separate tests like this because :
 ``123456789101112131415`` ``````if ( !charlielive ) { //do charlie's stuff } else if ( !arronlive) { //do arronlive's stuff } else if ( !boblive) { //do boblive's stuff } else { //some error }``````

With lines 103 - 110 - these can be put into the relevant parts above as single return statements - no conditional needed because it's already in a conditional.

You have an alldead variable that is not used.
Thank you for all your replies. I originally did have (boolean) for my if statements, but when my code didn't work I wondered if it was something like why you don't do if (variable = 4) then I just never bothered to change it back because it didn't affect it. I also did use switch statements, but again it didn't affect the result so I didn't bother to change it back.

I like the Numalive idea, but I think it would just make my code look cleaner, and not affect the result as much. I'm basically saying the same thing just being more explicit.

Changing the if statements in 74-101 didn't change my results.

You're right about 103-110, but again it just cleans up my code.

The alldead variable was one of my debugging variables I forgot to take out.
Cleaning up your code has more value than you think - making the code simpler & better makes logical errors simpler & easier to figure out.

One should always strive to have elegant code.

So you are objecting to changing lines 60 -61 to ` while ( NumAlive >= 2 )` ?

Another thought I had was to either use a debugger, or set the number of iterations to something much smaller (5 say), cout all the intermediate values so you can see what's going on & working as expected.

Good Luck !!
I would say your teacher's code is off.

Charlie only survives the first round 1 in 3 times, which means his win rate must be less than 33% on average.
I'm getting the percentages as
 ``` Aaron: 49.99% Bob: 16.67% Charlie: 33.34%```

(with my own code, written from scratch).

I don't know whether that's correct, but mathematically it has a nice sort of feel to it.
Again, Charlie can only survive the first round 1 in 3 times.

First shot is fired by Aaron. Charlie's chances of living are 2 out of 3. Bob shoots next. If Charlie is alive Bob shoots at Charlie. Charlie survives 1 out of 2 times.

That completes the first round as far as Charlie's chances of surviving:

He survives 2/3 * 1/2 = 1/3 of the time.

If Charlie is alive at the end of round 1, one of the other players will be also, and whichever it is will get to shoot at him before he gets to shoot at them. Averaged between the two, he should survive (ie. win) 2 out of 3 times that he survives round 1.

So his average win percentage should be 2/3 * 1/2 * 2/3: which is 2 out of 9 times or 22.2%

http://ideone.com/xyWcNJ
Last edited on
Charlie's chance should be easy to calculate, since everybody targets him unless he's dead, and there is only one scenario in which he wins.

Step 1: Aaron shoots at Charlie -> 1/3 chance of dying.
Step 2: If Charlie survived, Bob shoots at Charlie -> 1/2 chance of dying.
Step 3: If Charlie survived, he shoots and kills Bob.
Step 4: Aaron shoots at Charlie -> 1/3 chance of dying.
Step 5: If Charlie survived, he shoots and kills Aaron.
Step 6: Only Charlie left, Charlie wins.

That is the only scenario in which he wins and we can calculate the chance of occurence.

Chance of dying in step 1: 1/3.
Chance of dying in step 2: 1/2 IFF alive after step 1 (1 - 1/3 = 2/3) = 2/3*1/2 = 1/3.
Chance of dying in step 4: 1/3 IFF alive after step 2 (1 - 1/3 - 1/3 = 1/3) = 1/3*1/3 = 1/9.

So, in total, his chance to die before the end of the game is 1/3 + 1/3 + 1/9 = 7/9 = 77.778.

So his chance to win is 2/9 = 22.22..%.

(EDIT: use that to see if your results are correct. Your teacher is pretty close; increasing it over 1k iterations should get closer to 22.22%.)
Last edited on
Yes, that makes sense. I made two mistakes, one was mathematical, the other was understanding/implementing the rules of the game.
Last edited on
I put together something and I got similar results to what you go
try this
 ``12345678910111213141516171819202122`` ``````#include #include #include int main() { bool aaron, bob, charlie; unsigned int awin = 0, bwin = 0, cwin = 0, shoot; srand(time(0)); for(unsigned int i = 0; i<10000; i++){ aaron = true; bob = true; charlie = true; while((aaron && bob) || (aaron && charlie) || (bob && charlie)){ shoot = rand() % 3 + 1; if(aaron && charlie && shoot == 1) charlie = false; else if(aaron && !charlie && shoot == 1) bob = false; shoot = rand() %2 + 1; if(bob && charlie && shoot == 1) charlie = false; else if(bob && !charlie && shoot == 1) aaron = false; if(charlie && bob) bob = false; else if(charlie && !bob) aaron = false; } if(aaron) ++awin; if(bob) ++bwin; if(charlie) ++cwin; } std::cout << "aaron: " << awin <<"\nbob: " << bwin << "\ncharlie: " << cwin << std::flush; std::cout << "\naaron win %: " << std::setprecision(25) << (double)awin/(1000000000)*100 << "\nbob win %: " << std::setprecision(25) << (double)bwin/(1000000000)*100 << "\ncharlie win %: " << std::setprecision(25) << (double)cwin/(1000000000)*100 << std::endl; }``````

I could be wrong though I quickly put it together because I have to go to class now so I am not late =p

EDIT: After running my program for a loop of 1EE9(Giga/Billion) I got this as an ouput:
 ```aaron: 361114792 bob: 416621968 charlie: 222263240 arron win %: 36.11147919999999800211299 bob win %: 41.66219679999999669917088 charlie win %: 22.22632400000000174600245```
Last edited on
Looks correct according to how I understand the assignment. The teacher's results are pretty far off though.
Topic archived. No new replies allowed.