忍者ブログ

はしりがき

ガラパゴスへよおこそ。

[PR]

×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。

正式版コードver1.2くらい

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
//hit条件
#define hit_condition groupcount[0]+groupcount[3]+groupcount[4]+groupcount[6]>0 && groupcount[1]+groupcount[3]+groupcount[5]+groupcount[6]>0 && groupcount[2]+groupcount[4]+groupcount[5]+groupcount[6]>0
#define exception 0                                        //例外条件
#define sizeof_cardset 8                                   //cardset[]の要素数
#define sizeof_hand 8                                      //手札枚数

int main(void){
    int trynum = 30000;                                         //試行回数
    int cardset[sizeof_cardset] = {4,6,12,2,1,2,0,40};          //扱うカードの、種類ごとの枚数
    int cardtype[sizeof_cardset] = {0,0,0,1,1,1,1,0};           //カードの属性。現状レインボー(1)or単色(0)のみ
    int groupcount[sizeof_cardset];                             //グループカウンタ。要素数をcardset[]に追従して、手札中に種類Aのカードが1枚あれば同じ位置の要素をインクリメント
    int hand[sizeof_hand];                                      //手札[手札枚数]
    int i,k,j,l,m,n,p,q;                                        //forループ用変数
    int duplcount,siev,groupnum,try;                            //重複判定用カウンタ、ふるい分け用変数、手札種類保存用変数、試行番号
    int hitcount = 0;                                           //条件を満たした試行の回数を数えるカウンタ
    int shuffle = 0;                                            //乱数調整用変数
    double probability;                                         //確率
   
    //「それ以外」の枚数設定
    for(m=0; m<sizeof_cardset-1; m++){
        cardset[sizeof_cardset-1] = cardset[sizeof_cardset-1]-cardset[m];
    }
    for(try=0; try<trynum; try++){

        //グループカウンタのリセット
        for(l=0; l<sizeof_hand; l++){
            groupcount[l] = 0;
        }
        //手札生成
        //過去のカードとの被り番号をチェックするのがforループ[k]
        //被らないような番号になるまで乱数を作り直すのがdo-whileループ
        //以上の操作を手札枚数分繰り返すのがforループ[i]
        for(i=0; i<sizeof_hand; i++){
            do{
                duplcount = 0;
                srand(try + i + shuffle + (unsigned int)time(NULL));
                hand[i] = rand()%40;
                for(k=0; k<i; k++){
                    if(hand[k] == hand[i]) duplcount++;
                }
                shuffle++;
            }while(duplcount > 0);
        }
        //ふるい分け
        //「カードに割り振った番号」を「カードの種類」に変換する
        //変数sievに、cardset[]の値を番号の若いほうから加算していく
        //siev>hand[n]となったときのjをgroupnumに保存しておき、ループ脱出後にこの位置の要素をインクリメント+hand[n]の値をgroupnumに置き換える
        for(n=0; n<sizeof_hand; n++){
            siev = 0;
            for(j=0; j<sizeof_cardset; j++){
                siev = siev + cardset[j];
                groupnum = j;
                if(siev > hand[n]) break;
            }
            hand[n] = groupnum;
            if(exception){
                hand[n] = sizeof_cardset-1;
            }else{
                groupcount[groupnum]++;
            }
        }
        //条件判定
        //hithit_conditionはヘッダで定義する
        if(hit_condition) hitcount++;

        //動作確認用
        printf("%d and %d\n", hitcount, try);
        for(p=0; p<sizeof_cardset-1; p++){
            printf("%d,", groupcount[p]);
        }
        printf("%d\n", groupcount[sizeof_cardset-1]);
       
        for(q=0; q<sizeof_hand-1; q++){
            printf("%d,", hand[q]);
        }
        printf("%d\n", hand[sizeof_hand-1]);
           
    }
    //確率計算
    probability = 100.0*hitcount/trynum;
    printf("P = %f\n", probability);
    return 0;
}


解説書いた。汎用性もうpした。
必要に応じて"conditon","exception","sizeof_hand",''cardset[]","cardtype[]","sizeof_cardset","trynum"を調整してください。
for(int i = 0; i<N; i++)とかはやってないのでC90でもいけます。
計算速度は飛躍的にうp。一瞬で計算できます。
ただ乱数に偏りがあるっぽいのでそこが課題。具体的に言うと、秒が変わらない限り計算結果も同じになる。
頻繁に書き換えます。

PR

comment

お名前
タイトル
E-MAIL
URL
コメント
パスワード

trackback

この記事にトラックバックする:

TemplateDesign by KARMA7

忍者ブログ [PR]