#include <string>
#include <iostream>
#include <iomanip>
#include <ctime>
#include <cstdlib>
struct shooter
{
std::string name ;
double accuracy ;
bool alive ;
};
void shoot(const shooter& source, shooter& target) ;
void resurrect(shooter[], unsigned) ;
unsigned duel(shooter[], unsigned) ;
int main()
{
std::srand(static_cast<unsigned>(std::time(0))) ;
const unsigned trials = 100000 ;
// The order of shooters is important. It determines the sequence of attempts at shooting.
// lowest index goes first.
shooter shooters[] =
{
// {"Sue", 0.20, true},
{"Aaron", 0.33, true},
{"Bob", 0.50, true},
{"Charlie", 1.0, true}
};
const unsigned nShooters = sizeof(shooters) / sizeof(shooters[0]) ;
unsigned wins[nShooters] = {} ;
for ( unsigned i=0; i<trials; ++i )
{
resurrect(shooters, nShooters) ;
++wins[duel(shooters,nShooters)] ;
}
for ( unsigned i=0; i<nShooters; ++i )
{
std::cout << std::left << std::setw(10) << shooters[i].name
<< std::right << std::setw(6) << wins[i] << " ("
<< std::fixed << std::setprecision(1) << std::setw(4)
<< (wins[i] / static_cast<double>(trials))*100 << "%)\n" ;
}
}
void shoot(const shooter& source, shooter& target)
{
if ( ((std::rand() % 100) * 0.01 ) < source.accuracy )
target.alive = false ;
}
void resurrect(shooter shooters[], unsigned size)
{
for ( unsigned i=0; i<size; ++i )
shooters[i].alive = true ;
}
bool onlyOneAlive(shooter shooters[], unsigned size)
{
unsigned alive = 0 ;
for ( unsigned i=0; i<size; ++i )
if ( shooters[i].alive )
++alive ;
return alive == 1 ;
}
// PRE: size is greater than 0.
// At least two of shooters[i].alive are true.
unsigned findTarget(shooter shooters[], unsigned size, const shooter& source)
{
unsigned index = 0 ;
while ( !shooters[index].alive || shooters[index].name == source.name )
++index ;
unsigned target = index ;
while ( ++index < size )
{
if ( shooters[index].alive && shooters[index].name != source.name )
if ( shooters[index].accuracy > shooters[target].accuracy )
target = index ;
}
return target ;
}
// PRE: size is greater than 0.
// Exactly one of shooters[i].alive is true.
unsigned winner(shooter shooters[], unsigned size)
{
for ( unsigned i=0; i<size; ++i )
if ( shooters[i].alive )
return i ;
return size ; // to quell a compiler warning.
}
// PRE: size is greater than 0.
// At least one of shooters[i].alive is true.
unsigned nextAlive(shooter shooters[], unsigned size, unsigned index)
{
do
{
index = (index+1) % size ;
} while (!shooters[index].alive) ;
return index ;
}
// PRE: size is greater than 0.
// At least one of shooters[i].alive is true.
unsigned duel(shooter shooters[], unsigned size)
{
unsigned turn = 0 ;
while (!onlyOneAlive(shooters,size))
{
unsigned targetIndex = findTarget(shooters, size, shooters[turn]) ;
shoot(shooters[turn], shooters[targetIndex]) ;
turn = nextAlive(shooters, size, turn) ;
}
return winner(shooters, size) ;
}