Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
逆鱗マラソンのシミュレーション
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
public class RandomGekirinMarathon : MonoBehaviour {
// サイコロの目を定義
int[] dice = new int[] {1, 2, 3, 4, 5, 6};
// 結果を記録するジャグ配列
int[][] results = new int[userNum][];
// ユーザー数
const int userNum = 10000;
// 最小値を保持
int sampleNumMin;
// 最大値を保持
int sampleNumMax;
// 試行回数の合計を保持
int sampleNumSum;
// 試行回数の分布確認用辞書
Dictionary<int, int> resultDistribution = new Dictionary<int, int>();
void Start(){
OutputDiceResultsWithAllType();
}
// 出るまで頑張る逆鱗マラソン
void OutputDiceResultsWithAllType(){
// 処理開始のメッセージ
Debug.Log("***** 出るまで頑張る逆鱗マラソンを開始 *****");
// CSVファイルのヘッダを出力
StreamWriter sw;
FileInfo fi;
string fineName = Application.dataPath + "/Resources/Csv/RandomLessSample/dice_all_output.csv";
fi = new FileInfo(fineName);
sw = fi.CreateText();
for (int userIndex = 0; userIndex < results.Length; userIndex++){
// 出たサイコロの目を記録するリスト
List<int> rollList = new List<int>();
// 達成状況確認の辞書
Dictionary<int, bool> achievedDict = new Dictionary<int, bool>();
foreach (int pips in dice){
achievedDict.Add(pips, false);
}
while (true){
int pips = RollADice();
rollList.Add(pips);
if (CheckAllTypeAchieved(rollList, achievedDict)){
break;
}
}
// 作成されたリストを配列に変換してジャグ配列にセット
int[] userResultsArray = rollList.ToArray();
results[userIndex] = userResultsArray;
// 結果の文字列を出力
sw.WriteLine(OutPutLineAllType(userIndex));
// 最小値、最大値、試行回数の記録
RecordStats(userIndex);
}
// Streamを閉じて書き込み
sw.Flush();
sw.Close();
fineName = Application.dataPath + "/Resources/Csv/RandomLessSample/dice_all_output_summary.csv";
fi = new FileInfo(fineName);
sw = fi.CreateText();
// 平均を算出
float average = 1.0f * sampleNumSum / userNum;
// 達成人数を出力
sw.WriteLine("***** summary *****");
sw.WriteLine("平均, 最小値, 最大値");
System.Text.StringBuilder sb = new System.Text.StringBuilder();
sb.Append(average).Append(",").Append(sampleNumMin).Append(",").Append(sampleNumMax);
sw.WriteLine(sb.ToString());
sw.WriteLine("分布確認用データ");
sb = new System.Text.StringBuilder();
System.Text.StringBuilder distSb = new System.Text.StringBuilder();
for (int i = 1; i <= sampleNumMax; i++){
// 分布のラベル
sb.Append(i).Append(",");
// ラベルに対応する人数
if (resultDistribution.ContainsKey(i)){
distSb.Append(resultDistribution[i]).Append(",");
} else {
distSb.Append("0,");
}
}
// 分布を出力
sw.WriteLine(sb.ToString());
sw.WriteLine(distSb.ToString());
// Streamを閉じて書き込み
sw.Flush();
sw.Close();
// 処理開始のメッセージ
Debug.Log("***** 出るまで頑張る逆鱗マラソンを終了 *****");
}
int RollADice(){
// 乱数の範囲指定で配列のインデックスを取得する
int index = Random.Range(0, dice.Length);
// サイコロの目を取得する
int pips = dice[index];
return pips;
}
bool CheckAllTypeAchieved(List<int> rollList, Dictionary<int, bool> achievedDict){
bool isAchieved = false;
// 辞書に結果を格納
foreach (int pips in rollList){
// 各ユーザーの配列を確認し、辞書内で出た目に一致するキーの値をtrueにする
achievedDict[pips] = true;
}
// 辞書内全てのキーの値がtrueなら達成
int trueCount = 0;
foreach (KeyValuePair<int, bool> pair in achievedDict){
if (pair.Value){
trueCount++;
}
}
if (trueCount == dice.Length){
isAchieved = true;
}
return isAchieved;
}
string OutPutLineAllType(int userIndex){
// 各ユーザーの結果を出力する
System.Text.StringBuilder sb = new System.Text.StringBuilder();
sb.Append(userIndex).Append(",");
// 結果の数だけループ
for (int i = 0; i < results[userIndex].Length; i++){
int pips = results[userIndex][i];
sb.Append(pips).Append(",");
}
sb.Append("finished.");
return sb.ToString();
}
void RecordStats(int userIndex){
int length = results[userIndex].Length;
// 最小値の記録
if (sampleNumMin > length || sampleNumMin == 0){
sampleNumMin = length;
}
// 最大値の記録
if (sampleNumMax < length){
sampleNumMax = length;
}
// 試行回数の記録
sampleNumSum += length;
// 分布の記録
if (resultDistribution.ContainsKey(length)){
resultDistribution[length]++;
} else {
resultDistribution.Add(length, 1);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.