//到达末端结点则进行一次终盘模拟 private void simulate(nodes node, int currentside, int firstplayer) { //叶子结点为最终节点 if (checkboard(node.board) != -1)//即游戏已结束 { if (checkboard(node.board) == 1) { node.sim_Num++; node.win_Num++; } else if (checkboard(node.board) == 0) { node.sim_Num++;//模拟数+1 } else { node.sim_Num++; node.win_Num += 0.5; } } else//游戏没结束则扩展节点 { expand(node);//扩展末端节点,被扩展的子节点内只有Move int temp = rand.Next(node.child.Count); //随机选择一个末端子节点 simap board2 = node.child[temp].board.createDeepClone(); //复制末端子节点的地图 while (checkboard(board2) == -1) //循环进行模拟直到终局 { doRandomMove(board2); } //更新末端节点胜利数与模拟数 if (checkboard(board2) == 1) //终局模拟返回为胜 { node.win_Num++; //末端子节点胜利数+1 node.sim_Num++; //末端子节点模拟数+1 } else if (checkboard(board2) == 0.5) { node.win_Num += 0.5; node.sim_Num++; } else { node.sim_Num++; } } }
private double cal_flipping(nodes node) { double point = 0; if ((node.board.currentside == 0) && (node.board.firstplayer == 0) || (node.board.currentside == 1) && (node.board.firstplayer == 1))//现在先手且先手为红或者现在后手且先手为蓝 { point = (1) * (node.board.Prjiang * 20 + node.board.Prshi * node.board.Prxiang * 6 + node.board.Prche * 4 + node.board.Prma * 3 + node.board.Przu * 2 + node.board.Prpao * 6) + (-1) * (node.board.Pbjiang * 20 + node.board.Pbshi * node.board.Pbxiang * 6 + node.board.Pbche * 4 + node.board.Pbma * 3 + node.board.Pbzu * 2 + node.board.Pbpao * 6); } else if ((node.board.currentside == 1) && (node.board.firstplayer == 0) || (node.board.currentside == 0) && (node.board.firstplayer == 1))//现在后手且先手为红或者现在先手且先手为蓝 { point = (-1) * (node.board.Prjiang * 20 + node.board.Prshi * node.board.Prxiang * 6 + node.board.Prche * 4 + node.board.Prma * 3 + node.board.Przu * 2 + node.board.Prpao * 6) + (1) * (node.board.Pbjiang * 20 + node.board.Pbshi * node.board.Pbxiang * 6 + node.board.Pbche * 4 + node.board.Pbma * 3 + node.board.Pbzu * 2 + node.board.Pbpao * 6); } return(point); }
public nodes(nodes parent)//创造节点的方法 { this.parent = parent; ucb = 10; //初始化UCB值为10 sim_Num = 0; //初始化节点模拟数为零 win_Num = 0; //初始化结点胜利数为零 child = new List <nodes>(); //创造出子节点序列 Move movtion = new CDC.Move(); win_ratio = 0;//胜率 turn = 0; visit = 0; alpha = -1000; beta = 1000; remain_flip_number = 0; resign = -1; }
//得到最大UCB值节点,并通过常数控制保证没被模拟过的节点仍会被选择到 private Move best_move(nodes rootnode) { double maxwin_ratio = -1; nodes bestnode = new nodes(); rand = new Random(); for (int i = 0; i < rootnode.child.Count; i++) { if (rootnode.child[i].win_ratio > maxwin_ratio) { maxwin_ratio = rootnode.child[i].win_ratio; max_child = i; bestnode = rootnode.child[i]; } } return(bestnode.movtion); }
//到达末端结点则进行一次终盘模拟 private void simulate(nodes node, int currentside, int firstplayer) { block[][] matrix = node.board;//末端节点的地图信息 //叶子结点为最终节点 if (checkboard(node.board, currentside, firstplayer) != -1)//即游戏已结束 { if (checkboard(node.board, node.side, firstplayer) == 1) { node.sim_Num++; node.win_Num++; } else { node.sim_Num++;//模拟数+1 } } else//游戏没结束则扩展节点 { expand(node);//扩展末端节点,被扩展的子节点内只有Move int tempNodeNum = rand.Next(node.child.Count); //随机选择一个子节点 int nowside; block[][] board2 = node.child[tempNodeNum].board; //创造末端子节点的地图 //循环进行模拟直到终局 for (int k = board2.getTurnCount(); k < board2.getTurnLimit() && checkboard(board2, 0) == -1; k++) { doOneTurnMove(board2, nowside++ % 2); } //更新末端节点胜利数与模拟数 if (checkboard(board2, node.side, firstplayer) == 1) //终局模拟返回为胜 { node.win_Num++; //末端子节点胜利数+1 node.sim_Num++; //末端子节点模拟数+1 } else { node.sim_Num++; } } }
//得到最大UCB值节点,并通过常数控制保证没被模拟过的节点仍会被选择到 private Move best_move(nodes rootnode) { int temp; double maxucb = -1; nodes bestnode = new nodes(); rand = new Random(); for (int i = 0; i < rootnode.child.Count; i++) { if (rootnode.child[i].ucb > maxucb) { maxucb = rootnode.child[i].ucb; max_child = i; bestnode = rootnode.child[max_child]; } } if (maxucb == 10) { temp = rand.Next(rootnode.child.Count); bestnode = rootnode.child[temp]; } return(bestnode.movtion); }
private bool deloop(nodes node, Map map) { bool value = false; int n = 0; if (map.Plyr_move.Count >= 6) { for (int i = map.Plyr_move.Count - 6; i < map.Plyr_move.Count - 1; i++)//重复度检查 { if (map.Plyr_move[i].movtion.froX == node.movtion.froX && map.Plyr_move[i].movtion.froY == node.movtion.froY && map.Plyr_move[i].movtion.desX == node.movtion.desX && map.Plyr_move[i].movtion.desY == node.movtion.desY) { n += 1; } } } if (n >= 3)//多次重复 { value = true; Console.WriteLine("Repeation Draw!!!!"); } return(value); }
private bool deloop(nodes node, Map map) { bool value = false; if (map.currentside == 0)//为先手方时调用先手方历史纪录 { int n = 0; if (map.Plyr1move.Count <= 6) { for (int i = 0; i < map.Plyr1move.Count - 1; i++)//重复度检查 { if (map.Plyr1move[i].movtion.froX == node.movtion.froX && map.Plyr1move[i].movtion.froY == node.movtion.froY && map.Plyr1move[i].movtion.desX == node.movtion.desX && map.Plyr1move[i].movtion.desY == node.movtion.desY) { n += 1; } } } else { for (int i = map.Plyr1move.Count - 6; i < map.Plyr1move.Count - 1; i++)//重复度检查 { if (map.Plyr1move[i].movtion.froX == node.movtion.froX && map.Plyr1move[i].movtion.froY == node.movtion.froY && map.Plyr1move[i].movtion.desX == node.movtion.desX && map.Plyr1move[i].movtion.desY == node.movtion.desY) { n += 1; } } } if (n >= 3)//多次重复 { value = true; Console.WriteLine("Found Repeat!"); } } else if (map.currentside == 1)//为后手方时调用后手方历史纪录 { int m = 0; if (map.Plyr2move.Count <= 6) { for (int i = 0; i < map.Plyr2move.Count - 1; i++)//重复度检查 { if (map.Plyr2move[i].movtion.froX == node.movtion.froX && map.Plyr2move[i].movtion.froY == node.movtion.froY && map.Plyr2move[i].movtion.desX == node.movtion.desX && map.Plyr2move[i].movtion.desY == node.movtion.desY) { m += 1; } } } else { for (int i = map.Plyr2move.Count - 6; i < map.Plyr2move.Count - 1; i++)//重复度检查 { if (map.Plyr2move[i].movtion.froX == node.movtion.froX && map.Plyr2move[i].movtion.froY == node.movtion.froY && map.Plyr2move[i].movtion.desX == node.movtion.desX && map.Plyr2move[i].movtion.desY == node.movtion.desY) { m += 1; } } } if (m >= 3)//多次重复 { value = true; Console.WriteLine("Found Repeat!"); } } return(value); }
public nodes subAI_Evaluate(Map map) { simap map2 = new CDC.simap(); map2 = map2.createDeepClone(map); //复制一下地图 List <Move> movtionlist = new List <Move>(); //移动指令表 List <Move> fliplist = new List <Move>(); //翻棋指令表 List <Move> Alllist = new List <Move>(); //翻棋指令表 Move bestmove = new CDC.Move(); //最佳动作 Move bestflip = new Move(); //最佳翻棋 Move startflip = new Move(); //起始翻棋 nodes bestnode = new nodes(); if (map2.turncount == 1) //一局开始 { fliplist = AI_tools.getallfliplist(map2); //可翻行动列表 startflip = fliplist[rand.Next(fliplist.Count)]; //起始翻 map2.firstplayer = map.Matrix[startflip.froX, startflip.froY].item.side; //第一个棋子即为第一玩家的颜色 map2.secondplayer = (map.Matrix[startflip.froX, startflip.froY].item.side + 1) % 2; //第二玩家为另一颜色 map2.currentside = map2.firstplayer; bestnode.movtion.froX = startflip.froX; bestnode.movtion.froY = startflip.froY; bestnode.movtion.desX = startflip.desX; bestnode.movtion.desY = startflip.desY; return(bestnode); } else//非开局 { int point; int Maxpoint = 0; movtionlist = AI_tools.getallmove(map2); //获取所有可行指令 foreach (Move movtion in movtionlist) //遍历进攻选项 { point = AI_tools.point_Evaluate(map2, movtion); //计算进攻选项得点 if (point > Maxpoint) //判断得点最大 { Maxpoint = point; bestmove = movtion; bestnode.movtion.froX = bestmove.froX; bestnode.movtion.froY = bestmove.froY; bestnode.movtion.desX = bestmove.desX; bestnode.movtion.desY = bestmove.desY; return(bestnode); } } if (Maxpoint == 0)//为移动指令时 { if (movtionlist.Count != 0) { bestmove = getnear(map2, map2.currentside); } Alllist = AI_tools.getmovflip(map2); if (Alllist.Count == 0) { checkboard(map2); } bestmove = Alllist[rand.Next(Alllist.Count)];//无有效步的时候生成随机步数 } } bestnode.movtion.froX = bestmove.froX; bestnode.movtion.froY = bestmove.froY; bestnode.movtion.desX = bestmove.desX; bestnode.movtion.desY = bestmove.desY; return(bestnode); }
private double score(nodes node) { List <Move> flippingList = new List <Move>(); flippingList = AI_tools.getallfliplist(node.board); double point = 0; double score = 0; for (int i = 0; i < 4; i++) { for (int j = 0; j < 8; j++) { if ((node.board.Matrix[i, j].item.side == node.board.firstplayer && currentside == 0 && node.board.Matrix[i, j].flip == 1) || (node.board.Matrix[i, j].item.side == node.board.secondplayer && currentside == 1 && node.board.Matrix[i, j].flip == 1)) //针对根结点行动方的估值 //确保在相同手时使用最大值,对方手时使用最小值 { switch (node.board.Matrix[i, j].item.type) { case chesstype.jiang: point = 20; break; case chesstype.shi: point = 10; break; case chesstype.xiang: point = 6; break; case chesstype.che: point = 4; break; case chesstype.ma: point = 3; break; case chesstype.zu: point = 2; break; case chesstype.pao: point = 6; break; case chesstype.blank: //移动 point = 0; break; } } if ((node.board.Matrix[i, j].item.side == node.board.firstplayer && currentside == 1 && node.board.Matrix[i, j].flip == 1) || (node.board.Matrix[i, j].item.side == node.board.secondplayer && currentside == 0 && node.board.Matrix[i, j].flip == 1)) { switch (node.board.Matrix[i, j].item.type) { case chesstype.jiang: point = -20; break; case chesstype.shi: point = -10; break; case chesstype.xiang: point = -6; break; case chesstype.che: point = -4; break; case chesstype.ma: point = -3; break; case chesstype.zu: point = -2; break; case chesstype.pao: point = -6; break; case chesstype.blank: //移动 point = 0; break; } } if (node.board.Matrix[i, j].item.side == 2) { point = 0; } for (int b = 0; b < 4; b++) { for (int a = 0; a < 8; a++) { if (((Math.Abs(b - i) <= 1) && (Math.Abs(a - j) <= 1)) && node.board.Matrix[b, a].flip == 1 && node.board.Matrix[b, a].item.side != 2) { Move movtion = new Move(); Move movtion2 = new Move(); movtion.froX = i; movtion.froY = j; movtion.desX = b; movtion.desY = a; if (GameController.checkmove(node.board, movtion) == true) { point = point * 1.25; } movtion2.froX = b; movtion2.froY = a; movtion2.desX = i; movtion2.desY = j; if (GameController.checkmove(node.board, movtion2) == true) { point = point * 0.75; } } } } score += point; } } if (node.movtion.desX == -1 && node.movtion.desY == -1 && node.movtion.froX != -1 && node.movtion.froY != -1)//节点为翻棋面节点时 { point = cal_flipping(node); for (int b = 0; b < 4; b++) { for (int a = 0; a < 8; a++) { if (((Math.Abs(b - node.movtion.froX) <= 1) && (Math.Abs(a - node.movtion.froY) <= 1)) && node.board.Matrix[b, a].flip == 1 && node.board.Matrix[b, a].item.side != 2) { Move movtion = new Move(); Move movtion2 = new Move(); movtion.froX = node.movtion.froX; movtion.froY = node.movtion.froY; movtion.desX = b; movtion.desY = a; if (GameController.checkmove(node.board, movtion) == true) { point = point * 1.25; } movtion2.froX = b; movtion2.froY = a; movtion2.desX = node.movtion.froX; movtion2.desY = node.movtion.froY; if (GameController.checkmove(node.board, movtion2) == true) { point = point * 0.75; } } } } score += point; } return(score); }
private nodes smartflipping(nodes rootnode, Map map) { int flippedpiece = 0; double temp_value = 0; double min_risk = 100; int mark = 0; nodes nodesmove = new nodes(); List <Move> flippingList = new List <Move>(); flippingList = AI_tools.getallfliplist(rootnode.board); Map mapasses = new Map(); mapasses = map.createDeepClone(); for (int i = 0; i < 4; i++) { for (int j = 0; j < 8; j++) { if (rootnode.board.Matrix[i, j].flip == 1) { flippedpiece += 1; } } } //第一阶段,只要相邻格有敌方棋子则不翻 for (int i = 0; i < flippingList.Count; i++) { for (int a = 0; a < 4; a++) { for (int b = 0; b < 8; b++) { if ((((Math.Abs(a - flippingList[i].froX) == 0) && (Math.Abs(b - flippingList[i].froY) == 1)) || ((Math.Abs(a - flippingList[i].froX) == 1) && (Math.Abs(b - flippingList[i].froY) == 0))) && //与翻棋坐标相邻的 ((rootnode.board.Matrix[a, b].flip == 1 && rootnode.board.Matrix[a, b].item.side == rootnode.board.firstplayer && rootnode.board.currentside == 1) || (rootnode.board.Matrix[a, b].flip == 1 && rootnode.board.Matrix[a, b].item.side == rootnode.board.secondplayer && rootnode.board.currentside == 0))) //周围的非己方棋子 { mark++; } } } if (mark != 0) { flippingList.Remove(flippingList[i]); //则去掉这样一个元素 mark = 0; //清除 continue; } } if (flippingList.Count != 0)//存在保守翻棋策略 { nodesmove.remain_flip_number = flippingList.Count; nodesmove.movtion.froX = flippingList[rand.Next(flippingList.Count)].froX; nodesmove.movtion.froY = flippingList[rand.Next(flippingList.Count)].froY; } //第二阶段,不存在完全保守的策略时 else if (flippingList.Count == 0) //不存在保守翻棋策略 { flippingList = AI_tools.getallfliplist(rootnode.board); //重新刷进flippinglist mark = 0; //清除mark for (int i = 0; i < flippingList.Count; i++) { for (int a = 0; a < 4; a++) { for (int b = 0; b < 8; b++) { if ((((Math.Abs(a - flippingList[i].froX) == 0) && (Math.Abs(b - flippingList[i].froY) == 1)) || ((Math.Abs(a - flippingList[i].froX) == 1) && (Math.Abs(b - flippingList[i].froY) == 0))) && //与翻棋坐标相邻的 ((rootnode.board.Matrix[a, b].flip == 1 && rootnode.board.Matrix[a, b].item.side == rootnode.board.firstplayer && rootnode.board.currentside == 1) || (rootnode.board.Matrix[a, b].flip == 1 && rootnode.board.Matrix[a, b].item.side == rootnode.board.secondplayer && rootnode.board.currentside == 0))) //周围的已经翻开的非己方棋子 { temp_value = cal_risk(a, b, map); if (temp_value == -1000)//绝对会被吃掉的情况 { mark++; } else { flippingList[i].risk += cal_risk(a, b, map); } } } } if (mark != 0) { flippingList.Remove(flippingList[i]); //则去掉这样一个元素 mark = 0; //清除 continue; } } for (int i = 0; i < flippingList.Count; i++) //选择威胁值最小的翻棋步骤 { if (flippingList[i].risk <= min_risk) //越高的正值 { nodesmove.remain_flip_number = flippingList.Count; nodesmove.movtion.froX = flippingList[i].froX; nodesmove.movtion.froY = flippingList[i].froY; } } } return(nodesmove); }
public nodes alpha_Beta(Map map) { //start rootnode; nodes rootnode = new nodes(); simap board = new simap(); nodes bestnode = new nodes(); List <Move> atkmovtion = new List <Move>(); List <Move> allmovtion = new List <Move>(); double maxscore = -1000; board = board.createDeepClone(map); rootnode.board = board; rootnode.depth = 0;//根节点的深度为零 currentside = rootnode.board.currentside; atkmovtion = AI_tools.getallatk(board); allmovtion = AI_tools.getallmove(board); alphabeta(rootnode); Console.WriteLine("CUT:" + cut + "\r\n\r\n\r\n"); foreach (nodes child in rootnode.child) { if (child.visit == 0) { continue; } else if (maxscore <= child.beta) { maxscore = child.beta; bestnode = child; } } if (deloop(bestnode, map) == true)//6步里2步以上重复 且为bestnode 则跳出 { rootnode.child.Remove(bestnode); if (map.unflipped > 0) { bestnode = smartflipping(rootnode, map); } else if (map.unflipped == 0 && rootnode.child.Count != 0) { foreach (nodes achild in rootnode.child) { if (maxscore <= achild.beta) { maxscore = achild.beta; bestnode = achild; } } } else if (map.unflipped == 0 && rootnode.child.Count == 0) { bestnode = subAI_Evaluate(map); } } if (bestnode.movtion.desX == -1 && bestnode.movtion.desY == -1) { bestnode = smartflipping(rootnode, map); } return(bestnode); }
private double alphabeta(nodes node) { loop_number++; double rvalue = 0; if (node.depth < limitdepth && node.visit == 0) { atk_expand(node); if (node.depth != 0) { if (node.depth % 2 == 0)//极大结点继承上界 { node.beta = node.parent.beta; } else//极小结点继承下界 { node.alpha = node.parent.alpha; } } } if (node.depth == limitdepth || (node.visit == 1 && node.child.Count == 0) || (node.visit == -3))//最终结点 { rvalue = score(node); if (node.depth % 2 == 0)//MAX { node.alpha = rvalue; } else//MIN { node.beta = rvalue; } if (node.depth != 0) { nodes temp = node; temp.child = null; temp = null; } return(rvalue); } if (node.depth % 2 == 0)// 极大节点 { foreach (nodes child in node.child) { double temp = alphabeta(child); if (temp >= node.alpha) { node.alpha = temp; } if (node.beta <= node.alpha) // 该极大节点的值>=α>=β,该极大节点后面的搜索到的值肯定会大于β,因此不会被其上层的极小节点所选用了。对于根节点,β为正无穷 { cut++; break; } } //子节点循环完毕 rvalue = node.alpha; if (node.depth != 0) { nodes temp = node; temp.child = null; temp = null; } } else// 极小节点 { foreach (nodes child in node.child) // 极大节点 { double temp = alphabeta(child); if (temp <= node.beta) { node.beta = temp; } if (node.beta <= node.alpha) // 该极大节点的值<=β<=α,该极小节点后面的搜索到的值肯定会小于α,因此不会被其上层的极大节点所选用了。对于根节点,α为负无穷 { cut++; break; } } rvalue = node.beta; if (node.depth != 0) { nodes temp = node; temp.child = null; temp = null; } } return(rvalue); }
private void atkandmove(Map map, nodes node) { #region Branching Factor Part List <Move> flipList = new List <Move>(); List <Move> movelist = new List <Move>(); simap map2 = new CDC.simap(); map2 = map2.createDeepClone(vmap); int branchingF = 0; int flipList_num = 0; int e_flip = AI_tools.getallfliplist(map2).Count; if ((map.currentside == 0 && map.firstplayer == 0) || (map.currentside == 1 && map.firstplayer == 1))//Red { e_flip = (e_flip - map.unflipp_blue); } else if ((map.currentside == 0 && map.firstplayer == 1) || (map.currentside == 1 && map.firstplayer == 0))//Blue { e_flip = (e_flip - map.unflipp_red); } flipList_num = e_flip;//从缩减后改为毫无缩减的状况 movelist = AI_tools.getallmove(map2); flipList = AI_tools.getallfliplist(map2); branchingF = movelist.Count + flipList.Count; allB.Add(branchingF); #endregion Move use = new CDC.Move(); use.froX = node.movtion.froX; use.froY = node.movtion.froY; use.desX = node.movtion.desX; use.desY = node.movtion.desY; //避免将原数据消除 if (use.desX == -1 && use.desY == -1 && use.froX != -1 && use.froY != -1) //AI给出的行动为翻棋 { flipchess(map, use.froX, use.froY); } if (use.froX != -1 && use.froY != -1 && use.desX != -1 && use.desY != -1)//都选定的情况 { if (GameController.checkmove(map, use) == true) { setmove(map, use); } else { use.froX = -1; use.froY = -1; use.desX = -1; use.desY = -1; } } if (map.currentside == 0) { label1.Text = "Current Player: First Player"; } if (map.currentside == 1) { label1.Text = "Current Player: Second Player"; } if ((vmap.currentside + 1) % 2 == 0) //已经实行的那一步的实施方(因为再flpchess和setmove中改变了currentside的值)属于先手或者后手 { vmap.Plyr1move.Add(node); //movtion存入先手List vmap.Plyr_move.Add(node); } else if (((vmap.currentside + 1) % 2 == 1)) { vmap.Plyr2move.Add(node);//movtion存入后手List vmap.Plyr_move.Add(node); } double displayturn = map.turncount - 1; use.froX = -1; use.froY = -1; use.desX = -1; use.desY = -1; }
private int checkboard(nodes node, Map map) { int flag = 0;//0为游戏未结束, 1为游戏结束 int redCount = 0; int blueCount = 0; for (int i = 0; i < 4; i++) { for (int j = 0; j < 8; j++) { if (map.Matrix[i, j].item.side == 0) //为红方 { redCount++; //红加1 } if (map.Matrix[i, j].item.side == 1) //为蓝方 { blueCount++; //蓝加1 } } } if (node.resign == 1) { if ((map.currentside == 0 && map.firstplayer == 0) || (map.currentside == 1 && map.firstplayer == 1)) { flag = 1; Console.WriteLine(map.turncount); textBox1.AppendText("Blue Win !" + "\r\n"); } else if ((map.currentside == 1 && map.firstplayer == 0) || (map.currentside == 0 && map.firstplayer == 1)) { flag = 2; Console.WriteLine(map.turncount); textBox1.AppendText("Red Win !" + "\r\n"); } } if (redCount == 0)//Blue win! { flag = 1; Console.WriteLine(map.turncount); textBox1.AppendText("Blue Win !" + "\r\n"); } else if (blueCount == 0)//Red win! { flag = 2; Console.WriteLine(map.turncount); textBox1.AppendText("Red Win !" + "\r\n"); } else if (deloop(node, map) == true) { flag = 3; textBox1.AppendText("Draw" + "\r\n"); } else if (map.turncount >= 150) { flag = 4; textBox1.AppendText("Draw" + "\r\n"); } else { flag = Judge_system(map); }//采用最终结束式 textBox1.AppendText("Turn Count: " + (map.turncount - 1) + "\r\n"); textBox1.AppendText("Red Jiang Remains: " + map.redjiang + "\r\n"); textBox1.AppendText("Red Shi Remains: " + map.redshi + "\r\n"); textBox1.AppendText("Red Che Remains: " + map.redche + "\r\n"); textBox1.AppendText("Red Ma Remains: " + map.redma + "\r\n"); textBox1.AppendText("Red Pao Remains: " + map.redpao + "\r\n"); textBox1.AppendText("Red Zu Remains: " + map.redzu + "\r\n"); textBox1.AppendText("Red Xiang Remians: " + map.redxiang + "\r\n"); textBox1.AppendText("Blue Jiang Remains: " + map.bluejiang + "\r\n"); textBox1.AppendText("Blue Shi Remains: " + map.blueshi + "\r\n"); textBox1.AppendText("Blue Che Remains: " + map.blueche + "\r\n"); textBox1.AppendText("Blue Ma Remains: " + map.bluema + "\r\n"); textBox1.AppendText("Blue Pao Remains: " + map.bluepao + "\r\n"); textBox1.AppendText("Blue Zu Remains: " + map.bluezu + "\r\n"); textBox1.AppendText("Blue Xiang Remians: " + map.bluexiang + "\r\n"); textBox1.AppendText("Red Pieces Remaining: " + map.redremain + "\r\n"); textBox1.AppendText("Blue Pieces Remaining: " + map.blueremain + "\r\n"); textBox1.AppendText("\r\n"); textBox1.AppendText("\r\n"); if (flag == 1)//蓝方胜 { lose_jiang.Add(map.redjiang); lose_zu.Add(map.redzu); lose_pao.Add(map.redpao); } else if (flag == 2)//红方胜 { win_jiang.Add(map.redjiang); win_zu.Add(map.redzu); win_pao.Add(map.redpao); } return(flag); }