public SweeperAgent( IList<IList<MINEWND>> Mines, int XNum, int YNum) { KB = new SimpleList(XNum * YNum,3); Requested = new SimpleList(XNum * YNum,2); Output = new SimpleList(XNum * YNum,2); m_uXNum = XNum; m_uYNum = YNum; m_pMines = new MINEWND[m_uXNum][]; foreach (var i in Enumerable.Range(0, m_uXNum)) m_pMines[i] = new MINEWND[m_uYNum]; foreach (var i in Enumerable.Range(0, m_uXNum)) { foreach (var j in Enumerable.Range(0, m_uYNum)) { m_pMines[i][j] = Mines[i][j]; } } //Now the m_PMines are bounded with the one in Game.cs!!! /* foreach (var i in Enumerable.Range(0, m_uXNum)) { foreach (var j in Enumerable.Range(0, m_uYNum)) { m_pMines[i][j].uAttrib = Attrib.Mine; } } * */ }
/// <summary> /// 利用深度优先,寻找所有SimpleDeduction未能发现的雷区。 /// </summary> public void DepthFirstDeductoin() { SimpleDeduction(); //初始时需要清空所有m_pMines的Temp状态 clearAllTemp(); int Depth = Requested.Count;//实际数组坐标到达Depth-1 if (Depth == 0) return; List<SimpleList> TemporaryMines = new List<SimpleList>(); //用于存储各种可能的结果,其实不用,只要最后判断整体结果合格时,将Requested中的所有点的当前值放入即可 SimpleList CountingMines = new SimpleList(Requested.Count, 4);//用于存放此归结数组 InitializeCountingMines(CountingMines); //每加一个雷,只会对周围的Num产生影响,因此只需判断此个函数 DFSMine(0,Depth, TemporaryMines); ///在此之后,无非以下情况: ///(1) 没有Solution,则智能体随机点击 /// (2) 有Solution,智能体搜索是否有存在于所有Solution中的结果,若存在,则可以判断。 /// 当然,均可以归结为对每一个需要推断的地方的出现Mine以及非Empty的和作归结。利用CountingMines /// 经过无数次Debug,总算可以确定,TemporaryMines中确实有所需要的所有正确的解。完全而且不遗漏。 /// 例如:当棋盘上只有1时,显示的解为8;只有2时,为28;当由SimpleDeduction有定解时,解为0。 /// //下面开始,对TemporaryMines中的每个值进行累加。 //找到具有最大可能性为空的,并且若该可能性为1,则标志出来为Estimation.Empty。 CountingEveryRequired(TemporaryMines, CountingMines); int HighestApp = FindHighestAppearance(CountingMines); //新建一个SimpleList,其中存放所有具有最高可能性Empty的格子的坐标 FindAllHighestEmpty(HighestApp,CountingMines,(HighestApp==TemporaryMines.Count)); }
private void InitializeCountingMines(SimpleList CountingMines) { foreach (var i in Enumerable.Range(0, Requested.Count)) { int[] b = (int[])Requested[i]; int x = b[0]; int y = b[1]; int[] c = {x,y,0,0}; CountingMines.Add(c); } }
private int FindHighestAppearance(SimpleList CountingMines) { //首先遍历,找到最大的值。分母的基数即为TemporaryMines.Count因此技术即可 int HighestApp = 0; foreach (var i in Enumerable.Range(0, CountingMines.Count)) { int a =((int[])CountingMines[i])[2]; //该位置出现Empty的次数 HighestApp = ( a > HighestApp) ? a : HighestApp; } return HighestApp; }
private void FindAllHighestEmpty(int HighestApp, SimpleList CountingMines, bool isSure) { foreach (var i in Enumerable.Range(0, CountingMines.Count)) { int[] a = (int[])CountingMines[i]; int b = a[2];//该位置出现Empty的次数 if (HighestApp == b) { int x = a[0]; int y = a[1]; if (isSure) m_pMines[x][y].uEstimation = Estimation.Empty; else m_pMines[x][y].uEstimation = Estimation.HighestEmpty; } } }
private void CountingEveryRequired(List<SimpleList> TemporaryMines, SimpleList CountingMines) { foreach (var i in Enumerable.Range(0, TemporaryMines.Count)) //对每种可能的结果进行遍历,假设他们可能性相等 { SimpleList TemporaryMine = TemporaryMines[i]; foreach (var j in Enumerable.Range(0, TemporaryMine.Count)) //首先,TemporaryMine.Count = Requested.Count; 其次,CountingMines中的顺序与下表对应应该和TemporaryMines中完全一致 { int[] a = (int[])TemporaryMine[j]; //得到了一个三个数的数组 int[] b = (int[])CountingMines[j]; if (a[2] == 0) b[2]++; if (a[2] == 1) b[3]++; } } }
private void AddToTemporaryMines(List<SimpleList> TemporaryMines) { SimpleList TemporaryMine = new SimpleList(Requested.Count,3); foreach (var i in Enumerable.Range(0, Requested.Count)) { int[] b = (int[])Requested[i]; int x = b[0]; int y = b[1]; if (m_pMines[x][y].uEstimation == Estimation.TempEmpty) { int[] c = { x, y, 0 }; TemporaryMine.Add(c); } if (m_pMines[x][y].uEstimation == Estimation.TempMine) { int[] c = { x, y, 1 }; TemporaryMine.Add(c); } } TemporaryMines.Add(TemporaryMine); }