访问违规

Access violation?

本文关键字:访问      更新时间:2023-10-16

我试图编写一个简单的蒙特卡罗模拟程序。确切地说,我想根据军队在进攻和防守方面的不同规模来分析战斗结果——与此相一致:http://en.wikipedia.org/wiki/Risk_(游戏)#Dice_probabilities

现在。。。风险II同一时间规则提供了不同类型的挑战:不同的军队规模意味着不同颜色的骰子(这意味着数字的分布函数不同)简而言之,你的军队规模越小,你最终获得1的可能性就越大,而你的军队越大,你最终的掷骰子次数就越高。

由于对所有可能的条件使用if语句充其量是一种巨大的愚蠢,所以我将所有可能的滚动结果制成5x12数组。(所有骰子中有12个面,5个不同的强度,所以你得到5x12)

我曾想过对每个进攻/防守组合进行10000次模拟,但一旦我意识到这意味着要进行900多万次计算,我决定将其缩短为每个组合100次。

以下是代码;一旦我运行它,它就会给我访问违规错误。我不知道我在哪里犯了错误。如果你能提供什么建议,我也很感激。提前谢谢。

/* 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 filen" );
    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);

}

您的代码

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

表示您似乎认为rand()返回[0,1)范围内的数字,但事实并非如此。相反,int返回[0, RAND_MAX]范围内的整数,因此您需要类似以下内容:

A_Ind = rand() * 12.0 / RAND_MAX;

如果你的模拟必须在统计上准确,那么你最好使用<random>库中的随机数生成器:

#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);