2012-03-24 20 views
0

Ich habe versucht, ein einfaches Monte-Carlo-Simulationsprogramm zu schreiben. Um genau zu sein, wollte ich die Kampfergebnisse in Abhängigkeit von den unterschiedlichen Armeegrößen sowohl auf Angriff und Verteidigung analysieren - etwas in der Melodie dieses: http://en.wikipedia.org/wiki/Risk_(game)#Dice_probabilitiesZugriffsverletzung?

Jetzt ... Risk II Gleiche Zeit Regel bietet verschiedene Art von Herausforderung: variierend Armeegröße bedeutet eine andere Farbe der Würfel (was eine andere Verteilungsfunktion für die Zahlen bedeutet). Kurz gesagt, je kleiner die Größe deiner Armee ist, desto wahrscheinlicher wirst du mit 1s enden, während die Größe deiner Armee größer ist, Je größer die Wahrscheinlichkeit ist, dass Sie eine höhere Anzahl von Rollen erhalten.

Da die Verwendung von if-Anweisungen für alle möglichen Bedingungen eine kolossale Dummheit vom Feinsten war, tabellierte ich alle möglichen rollenden Ergebnisse im 5x12-Array. (12 Seiten in allen Würfeln, und 5 variierende Stärke, so erhalten Sie 5x12)

Ich dachte an die Durchführung von 10000 Simulationen für jede Kombination Offensiv/Verteidigung, aber sobald ich erkannte, dass würde über 9 Millionen Berechnungen bedeuten, entschied ich um es auf 100 pro Kombination kurz zu schneiden.

Folgendes ist der Code; Sobald ich es ausführe, gibt es mir den Zugriffsverletzungsfehler. Ich weiß nicht, wo ich einen Fehler gemacht habe. Wenn es einen Rat gibt, den Sie anbieten können, würde ich das auch schätzen. Danke im Voraus.

/* Risk II Combat Result Table 

For starter, we shall consider one-direction attack in RISK II 
and generate the combat table for use. 

Machine: Pentium Dual Core E6600 
Ram: 6G 
OS: Windows 7 
Compiler: Visual Studio 2010 

Jimmy Smith, 24-March-2012 

*/ 

#include <cstdio> 
#include <cstdlib> 
#include <cmath> 

#include <iostream> 
#include <algorithm> 
using namespace std; 

/* Initializing: 

    Range legend: 

White = 1 ~ 6 
Yellow = 7 ~ 12 
Orange = 13 ~ 20 
Red = 21 ~ 30 
Black = 31 ~ 

First row of Dice array corresponds to white dice, and so on. 

*/ 

int Dice[5][12] = { {1, 1, 1, 1, 2, 2, 2, 3, 3, 4, 5, 6}, 
        {1, 1, 2, 2, 2, 2, 3, 3, 4, 4, 5, 6}, 
        {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6}, 
        {1, 2, 3, 3, 4, 4, 5, 5, 5, 5, 6, 6}, 
        {1, 2, 3, 4, 4, 5, 5, 5, 6, 6, 6, 6} }; 

int Roll_Index [30]= {0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4}; 


int main() { 

float Table[30][30]; 

for (int i = 0; i < 30; i ++) 
    for (int j = 0; j < 30; j ++) 
     Table [i][j] = 0.0; 

int Result[100]; 

for (int i = 0; i < 100; i++) Result[i] = 0;  

float prob = 0.0; 

int Atk = 0; 
int Def = 0; //Number of attackers and defenders 


int A_Ind = 0; 
int D_Ind = 0; //Dice side index 

int A_Roll_Index = 0; 
int D_Roll_Index = 0; //Roll index on both sides 

int A_Dice = 0; 
int D_Dice = 0; //Roll result 

int Damage = 0; 

int Sum = 0; //Internal sum 

FILE* fp; 


//Time for hard core Monte-Carlo shit! 100 simulation for each situation 

for (Atk = 0; Atk<30; Atk++) { 

    for (Def = 0; Def < 30; Def++) { 

     for (int i = 0; i < 100; i++) { 

      int Attacker = Atk +1; 
      int Defender = Def +1; 

      while((Attacker>0)&&(Defender>0)) { 

       A_Ind = (int)(rand()*12); 
       D_Ind = (int)(rand()*12); //The die is cast! 

       A_Roll_Index = Roll_Index[Attacker-1]; 
       D_Roll_Index = Roll_Index[Defender-1]; 

       A_Dice = Dice[A_Roll_Index][A_Ind]; 
       D_Dice = Dice[D_Roll_Index][D_Ind]; 

       Damage = min(A_Roll_Index, D_Roll_Index) + 1; 

       if (A_Dice >= D_Dice) { 
        Defender -= Damage; 
        if (Defender == 0) Result[i] = 1; 
       } 
       else { 
        Attacker -= Damage; 
        if (Attacker == 0) Result[i] = 0; 
       } 
      } 
     } 

    for (int i = 0; i < 100; i++) Sum+=Result[i]; 

    prob = (float)(Sum/100); 

    Table[Atk][Def] = prob; 

    } 
} 
/* open new file for output and write a title */ 

fp = fopen("Combat.dat", "w+"); 

if(NULL == fp) { 
    printf("cannot open file\n"); 
    return(0); 
} 

for (Atk = 0; Atk < 30; Atk++){ 
    for (Def = 0; Def < 30; Def++) 
     fprintf(fp, "%16.8f", Table[Atk][Def]); 
    fprintf (fp, "\n"); 
} 
fclose(fp); 

return(EXIT_SUCCESS); 

}

+4

Sie sollten dies im Debugger ausführen. Dadurch wird festgestellt, welche Codezeile den Fehler verursacht. –

+0

int Ergebnis [100]; für (int i = 0; i <10000; i ++) Ergebnis [i] = 0; ? – inf

+1

Jetzt ist dies hier ein echter Hard-Core-Monte-Carlo Scheiße. @bamboon, jetzt hast du den ganzen Debugging-Spaß verdorben. :( – bzlm

Antwort

0

Ihr Code

A_Ind = (int)(rand()*12); 
D_Ind = (int)(rand()*12); 

zeigt an, dass Sie scheinen zu glauben, dass rand() eine Zahl im Bereich liefert [0,1), was nicht der Fall ist. Stattdessen int gibt eine integer im Bereich [0, RAND_MAX], so brauchen Sie so etwas wie:

A_Ind = rand() * 12.0/RAND_MAX; 

Wenn Sie eine Simulation hat statistisch genau zu sein, sind Sie wahrscheinlich besser dran mit einem Zufallszahlengenerator aus der <random> Bibliothek:

#include <random> 

typedef std::mt19937 rng_type; 
std::uniform_int_distribution<std::size_t> udist(0, 11); 

rng_type rng; 

// ... 

// seed rng first: 
rng.seed(some_seed_value); 

// roll dice 
std_size_t A_Ind = udist(rng), D_Ind = udist(rng); 
+0

Was für eine Überraschung. A_Ind war schließlich der Schuldige. Danke für die Hilfe. * Das habe ich nicht wirklich erwartet * –