關於srand(time(0))的使用方法

參考

關於rand()和srand()

問題

起因是想測試一下酒館戰棋十二胖頭魚大亂鬥先後手的勝率,測試代碼如下:

#include<cstdio>
#include<cstdlib>
#include<ctime>
#define TIMES 1000000
#define PRINT 0
//先手方勝負平的總場數
int win, draw, lose;
//score:先手方存活隨從數減後手方存活隨從數,1M次模擬總和
//combat:發生戰鬥的次數,1M次模擬總和
int score, combat;

//p1爲先手玩家,p2後手

//當前發動進攻的隨從編號
int p1cur, p2cur;
//剩餘隨從數
int p1rem, p2rem;
//當前所有隨從狀態,1爲有聖盾,0爲無聖盾,-1爲死亡
int p1sta[6], p2sta[6];
//將rand()的隨機數映射爲隨從編號的表格
int p1tab[6], p2tab[6];
/*
一開始從0到5一一對應,
若一方隨從只剩1、2、4號,則
tab[0] = 1; tab[1] = 2; tab[2] = 4
此時若rand()隨機結果爲1,則2號隨從參戰
*/


//true爲先手方進攻,false爲後手方進攻
void battle(bool first);
//交戰的雙方隨從編號
void battle(int p1no, int p2no);
//勝負判定
bool wlcheck();
void printcur();

int main()
{
	win = draw = lose = 0;
	score = combat = 0;
	int t = 0;
	srand(time(0));
	while (t++ < TIMES)
	{
		//千萬不要把srand(time(0))寫在這裏
		p1cur = p2cur = 5;
		p1rem = p2rem = 6;
		for (int i = 0; i < 6; i++)
		{
			p1sta[i] = p2sta[i] = 1;
			p1tab[i] = p2tab[i] = i;
		}
		while (1)
		{
			battle(1);
			if (wlcheck())break;
			printcur();
			battle(0);
			if (wlcheck())break;
			printcur();
		}
	}
	printf("先手勝率:%f%%\n後手勝率:%f%%\n平局率:%f%%\n平均存活隨從數:%f\n平均戰鬥次數:%f\n",
		(double)win * 100 / TIMES,
		(double)lose * 100 / TIMES,
		(double)draw * 100 / TIMES,
		(double)score / TIMES,
		(double)combat / TIMES);
}

void battle(bool first)
{
	if (first)
	{
		//首先找出下一個進攻隨從的編號
		do {
			if (p1cur == 5)p1cur = 0; 
			else p1cur++;
		} while (p1sta[p1cur] == -1);
		//然後令其和一個隨機敵方戰鬥
		battle(p1cur, p2tab[rand() % p2rem]);
	}
	else
	{
		do {
			if (p2cur == 5)p2cur = 0;
			else p2cur++;
		} while (p2sta[p2cur] == -1);
		battle(p1tab[rand() % p1rem], p2cur);
	}
}

void battle(int p1no, int p2no)
{
	combat++;
	//戰鬥結果判定,一方若有隨從死亡,修改存活隨從數rem,修改tab表格的對應關係
	if (--p1sta[p1no] == -1)
	{
		p1rem--;
		int i = -1;
		while (p1tab[++i] != p1no);
		while (i < p1rem) p1tab[i++] = p1tab[i + 1];
	}
	if (--p2sta[p2no] == -1)
	{
		p2rem--;
		int i = -1;
		while (p2tab[++i] != p2no);
		while (i < p2rem) p2tab[i++] = p2tab[i + 1];
	}
	//恢復其他存活隨從的聖盾
	for (int i = 0; i < 6; i++)
	{
		if (p1sta[i] == 0 && p1no != i)p1sta[i] = 1;
		if (p2sta[i] == 0 && p2no != i)p2sta[i] = 1;
	}
}

bool wlcheck()
{
	if (p1rem == 0 && p2rem == 0)
	{
		draw++; return true;
	}
	else if (p1rem == 0)
	{
		lose++; score -= p2rem; return true;
	}
	else if (p2rem == 0)
	{
		win++; score += p1rem; return true;
	}
	else return false;
}

void printcur()
{
	if (!PRINT)return;
	for (int i = 0; i < 6; i++)
		printf("%d ", p1sta[i]);
	printf("\n");
	for (int i = 0; i < 6; i++)
		printf("%d ", p2sta[i]);
	printf("\n\n");
}

結果

多次運行結果相差不大,後手勝率稍微領先一點點。
在這裏插入圖片描述

結論

使用srand(time(0))初始化隨機數發生器時一定要寫在循環之外,否則如果循環每次執行時間小於1s,則獲得的隨機數就是完全相同的一組。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章