/// <summary> /// 由1个 RandomPlayer 进行多次自我随机对弈训练 /// </summary> /// <param name="path">训练数据路径</param> /// <param name="trainNums">训练次数</param> public static void RandomTrain(string path = "randomData.txt", int trainNums = 1000) { Records records; if (File.Exists(path)) { records = Records.LoadFromText(File.ReadAllText(path)); } else { records = new Records(); } Logger.Clear(); Logger.IsEnabled = false; int maxStep = 120;//单次训练允许的最大回合,一般1000次训练中单词最大回合数小于100 Console.CursorVisible = false; for (int trainIndex = 0; trainIndex < trainNums; trainIndex++) { Console.SetCursorPosition(0, Console.CursorTop); Console.Write($"{trainIndex + 1}/{trainNums}"); GCase c = new GCase(); RandomPlayer player = new RandomPlayer(); List <string> cases = new List <string>(); List <int> methods = new List <int>(); for (int i = 0; i < maxStep; i++) { if (c.GState != GState.Playing) { //Console.WriteLine(i); break; } else { Logger.WriteLine("---"); Logger.WriteLine(c); cases.Add(c.ToString()); int method = player.GetAddMethod(c.Nums); Logger.WriteLine(method); c.RunMethod(method); methods.Add(method); Logger.WriteLine(c); c.Reserve(); Logger.WriteLine("Reserve"); Logger.WriteLine(c); } Logger.WriteLine("---"); Logger.WriteLine(); } Logger.WriteLine("GameOver"); Logger.WriteLine(""); for (int i = cases.Count - 1; i >= 0; i--)//倒序 { var state = c.GState; string gcase = cases[i]; int method = methods[i]; Logger.WriteLine(gcase + " " + method.ToString()); switch (state) { case GState.Playing: records.Add(gcase, method, CaseResult.Loop); break; case GState.AWin: throw new Exception("不对劲"); case GState.BWin: //倒数第一个胜利 //倒数第二个失败 //倒数第三个胜利 //.... int j = cases.Count - 1 - i; if (j % 2 == 0) { records.Add(gcase, method, CaseResult.Win); } else { records.Add(gcase, method, CaseResult.Fail); } break; } } Logger.WriteLine(); } Console.CursorVisible = true; Logger.IsEnabled = true; Logger.WriteLine(records, path); }
public override int GetAddMethod(int[] nums) { if (nums.Length != 4) { throw new ArgumentException(); } Dictionary <int, string> next = new Dictionary <int, string>(); for (int i = 0; i < 4; i++) { GCase current = new GCase(); for (int j = 0; j < 4; j++) { current.Nums[j] = nums[j]; } if (GCase.IsVaildAddMethod(nums, i)) { current.RunMethod(i); current.Reserve(); string s = ""; foreach (var c in current.Nums) { s += c; } next.Add(i, s); } } foreach (var item in next) { GameLog(item); } int result = -1; //如果下一步是对手的必败策略,则这一步是自己的必胜策略 foreach (var item in next) { string value = item.Value; string newValue = $"{value[1]}{value[0]}{value[3]}{value[2]}"; if (fail.Contains(newValue)) { GameLog($"Found {item.Key} {item.Value} SUCCESS"); result = item.Key; break; } } //如果下一步是对手的必胜策略,则这一步是自己的必败策略 //如果没有自己的必胜策略,则选择不是必败的策略 foreach (var item in next) { string value = item.Value; string newValue = $"{value[1]}{value[0]}{value[3]}{value[2]}"; if (success.Contains(newValue)) { GameLog($"Found {item.Key} {item.Value} FAIL"); } else { result = item.Key; break; } } if (result == -1) { GameLog("必败!!!"); result = 0; } return(result); }
/// <summary> /// 开始游戏 /// </summary> public void Start() { GCase = new GCase(); List <string> cases = new List <string>(); List <int> methods = new List <int>(); for (Step = 0; Step < maxStep; Step++) { if (GCase.GState != GState.Playing) { if (Step % 2 == 0) { GState = GState.BWin; GameLog("Player1 Win"); } else { GState = GState.AWin; GameLog("Player0 Win"); } break; } int method; if (Step % 2 == 0) { GameLog("--- Player0 ---"); method = Players[0].GetAddMethod(GCase.Nums); GameLog("--- end ---"); GameLog(); } else { GameLog("--- PLayer1 ---"); method = Players[1].GetAddMethod(GCase.Nums); GameLog("--- end ---"); GameLog(); } if (IsTrainMode) { cases.Add(GCase.ToString()); methods.Add(method); } GameLog("------"); GameLog(GCase); GameLog(method); GCase.RunMethod(method); GameLog(GCase); GCase.Reserve(); GameLog(GCase); GameLog("------"); GameLog(); } if (IsTrainMode) { for (int i = cases.Count - 1; i >= 0; i--)//倒序 { var state = GCase.GState; string gcase = cases[i]; int method = methods[i]; switch (state) { case GState.Playing: Records.Add(gcase, method, CaseResult.Loop); break; case GState.AWin: throw new Exception("不对劲"); case GState.BWin: //倒数第一个胜利 //倒数第二个失败 //倒数第三个胜利 //.... int j = cases.Count - 1 - i; if (j % 2 == 0) { Records.Add(gcase, method, CaseResult.Win); } else { Records.Add(gcase, method, CaseResult.Fail); } break; } } } }