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?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123

#include <iostream>
#include <ctime>
#include <cstdlib>
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
1
2
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:

1
2
3
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 :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
#include <stdlib.h>
#include <time.h>
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.