static private int player() { Console.WriteLine("input position:"); String input = Console.ReadLine(); Console.WriteLine(""); Console.WriteLine(""); String[] axis = input.Split(' '); int x; if (axis[0][0] >= 'a' && axis[0][0] <= 'z') { x = axis[0][0] - 'a'; } else { x = axis[0][0] - 'A'; } int y = int.Parse(axis[1]) - 1; if (!(x < 15 && x >= 0 && y < 15 && y >= 0)) { Console.WriteLine("Invalid input, type again."); Console.WriteLine(); return(player()); } else if (GlobleVar.chessboard[x, y] == GlobleVar.PLAYER || GlobleVar.chessboard[x, y] == GlobleVar.AI) { Console.WriteLine("Already has a piece, change a place."); Console.WriteLine(); return(player()); } int choice = x * 15 + y; GlobleVar.chessboard[x, y] = GlobleVar.AI; TreeNode root = new TreeNode(choice, null); //root.turn = 3 - root.turn; root.eval(false); GlobleVar.findChoices(choice, GlobleVar.chessboard, GlobleVar.choices); GlobleVar.preValue = root.tempValue; return(choice); }
public void friendMove(int position) { pictureBox1.MouseClick += pictureBox1_MouseClick; GlobleVar.AI = 3 - GlobleVar.AI; GlobleVar.PLAYER = 3 - GlobleVar.PLAYER; GlobleVar.preValue = 0 - GlobleVar.preValue; GlobleVar.nodeCount = 0; //GlobleVar.STEPS = 3; //GlobleVar.EMPTY_3 = param; GlobleVar.choice = position; GlobleVar.chessboard[position / 15, position % 15] = GlobleVar.AI; Display_GUI(GlobleVar.choice); TreeNode root = new TreeNode(GlobleVar.choice, null); //root.turn = 3 - root.turn; root.eval(false); GlobleVar.findChoices(GlobleVar.choice, GlobleVar.chessboard, GlobleVar.choices); GlobleVar.preValue = root.tempValue; GlobleVar.posHistory += GlobleVar.choice.ToString() + " "; if (GlobleVar.MostSeq[GlobleVar.AI] >= 5) { pictureBox1.MouseClick -= pictureBox1_MouseClick; GlobleVar.sh.sendMessage("position", "-1"); MessageBox.Show("Your friend wins!"); pvp = false; return; } GlobleVar.round++; }
static public int agent(int playerChoice) { /* * if (GlobleVar.round == 3 && GlobleVar.AI == 1) * GlobleVar.TEST = true; * else * GlobleVar.TEST = false; */ if (playerChoice == -1) { GlobleVar.chessboard[7, 7] = GlobleVar.AI; GlobleVar.preValue = 200; GlobleVar.MostSeq[GlobleVar.AI] = 1; GlobleVar.AiBestChoice = null; GlobleVar.findChoices(112, GlobleVar.chessboard, GlobleVar.choices); return(112); } GlobleVar.handledNode = 0; GlobleVar.possibleNode = 0; ArrayList tempChoices = new ArrayList(); tempChoices = (ArrayList)(GlobleVar.choices.Clone()); GlobleVar.possibleNode = (GlobleVar.choices.Count) * (GlobleVar.choices.Count + 3) * (GlobleVar.choices.Count + 6); Stack <TreeNode> st = new Stack <TreeNode>(); TreeNode root = new TreeNode(playerChoice, null); TreeNode temp; st.Push(root); while (st.Count != 0) { temp = st.Peek(); if (GlobleVar.TEST) { Console.WriteLine("----------------------------------------------------------"); Console.WriteLine(); Console.WriteLine("NEW LOOP:\n"); Console.WriteLine("Stack:"); foreach (TreeNode stackTemp in st) { if (stackTemp.turn == GlobleVar.AI) { Console.Write("choice={0}, Max, ", stackTemp.choice); } else { Console.Write("choice={0}, Min, ", stackTemp.choice); } if (stackTemp.valueNotEmpty) { Console.Write(stackTemp.value); } //Console.WriteLine("tempV={0} value={1} children:", stackTemp.tempValue, stackTemp.value); //for (int j = 0; j < stackTemp.children.Count; j++) // Console.Write("{0}({1}),", ((TreeNode)(stackTemp.children[j])).choice,((TreeNode)(stackTemp.children[j])).tempValue); Console.WriteLine(); } Console.WriteLine(); } if (temp.depth == GlobleVar.STEPS || temp.winningPoint == 1) { temp.value = temp.tempValue; } //if temp node has been expanded or it's a leaf node //which means value for this node has been set //check if the value of it's parent need to be updated //take alpha-beta pruning if (temp.expanded || temp.depth == GlobleVar.STEPS || temp.winningPoint == 1) { GlobleVar.handledNode++; if (GlobleVar.TEST) { Console.WriteLine("handling:"); if (temp.parent == null) { Console.WriteLine("choice={0} depth={1} parent={2} tempValue={3} value={4}\n", temp.choice, temp.depth, 0, temp.tempValue, temp.value); } else { Console.WriteLine("choice={0} depth={1} parent={2} tempValue={3} value={4}\n", temp.choice, temp.depth, temp.parent.id, temp.tempValue, temp.value); } } st.Pop(); if (temp.parent == null) { break; } bool parentValueAltered = false; //check if the value of it's parent need to be updated if (temp.parent.valueNotEmpty == false) { temp.parent.value = temp.value; temp.parent.valueNotEmpty = true; parentValueAltered = true; if (GlobleVar.TEST) { Console.WriteLine("update parent value\n"); } temp.parent.bestChoice = temp; } else if (temp.turn == GlobleVar.AI) { if (temp.value < temp.parent.value) { temp.parent.value = temp.value; parentValueAltered = true; if (GlobleVar.TEST) { Console.WriteLine("update parent value\n"); } } } else { if (temp.value > temp.parent.value) { temp.parent.value = temp.value; parentValueAltered = true; if (GlobleVar.TEST) { Console.WriteLine("update parent value\n"); } //update the best choice for AI's turn temp.parent.bestChoice = temp; } } //if temp.parent.parent and temp.parent.value has been altered, try pruning if (temp.depth > 1 && temp.parent.parent.valueNotEmpty && parentValueAltered) { if (temp.turn == GlobleVar.AI) { //alpha pruning //prune the subtree rooted from it's parent //push it's parent's next into stack if (temp.parent.value <= temp.parent.parent.value) { st.Pop(); if (temp.parent.next != null) { st.Push(temp.parent.next); } if (GlobleVar.TEST) { Console.WriteLine("alpha pruning\n"); } } else if (temp.next != null) { st.Push(temp.next); } } else { //beta pruning //prune the subtree rooted from it's parent //push it's parent's next into stack if (temp.parent.value >= temp.parent.parent.value) { st.Pop(); if (temp.parent.next != null) { st.Push(temp.parent.next); } if (GlobleVar.TEST) { Console.WriteLine("beta pruning\n"); } } else if (temp.next != null) { st.Push(temp.next); } } } //push next sibling into stack else if (temp.next != null) { st.Push(temp.next); } //Console.WriteLine("\n"); } //if temp node has not been expanded //create all children and put first child into stack else { temp.expanded = true; ArrayList children = new ArrayList(); //use the possible choices to create children for (int i = 0; i < temp.tempChoices.Count; i++) { children.Add(new TreeNode((int)(temp.tempChoices[i]), temp)); } if (temp.possibleWinP == 1) { if (temp.parent == null) { return(-1); } temp.tempValue *= 2; temp.winningPoint = 1; continue; } if (GlobleVar.winChoice[GlobleVar.AI] > -1) { GlobleVar.chessboard[GlobleVar.winChoice[GlobleVar.AI] / 15, GlobleVar.winChoice[GlobleVar.AI] % 15] = GlobleVar.AI; return(GlobleVar.winChoice[GlobleVar.AI]); } //sort children tnMax tnMaxCompare = new tnMax(); tnMin tnMinCompare = new tnMin(); if (temp.turn == GlobleVar.AI) { children.Sort(tnMaxCompare); } else { children.Sort(tnMinCompare); } TreeNode tempChild; TreeNode pre = null; if (GlobleVar.TEST) { Console.WriteLine(); Console.WriteLine("expand:"); Console.Write(temp.choice); if (temp.turn == GlobleVar.AI) { Console.Write("(Max): "); } else { Console.Write("(Min): "); } for (int i = 0; i < children.Count; i++) { Console.Write("{0}({1}),", ((TreeNode)(children[i])).choice, ((TreeNode)(children[i])).tempValue); } Console.WriteLine(); Console.WriteLine(); Console.WriteLine(); } //put the first child into stack if (children.Count > 0) { tempChild = (TreeNode)(children[0]); st.Push(tempChild); pre = tempChild; } //link all the children by a chain if (children.Count > 1) { for (int i = 0; i < children.Count; i++) { tempChild = (TreeNode)(children[i]); pre.next = tempChild; pre = tempChild; } } } } GlobleVar.chessboard[root.bestChoice.choice / 15, root.bestChoice.choice % 15] = GlobleVar.AI; GlobleVar.preValue = root.bestChoice.tempValue; if (root.bestChoice.seq > GlobleVar.MostSeq[GlobleVar.AI]) { GlobleVar.MostSeq[GlobleVar.AI] = root.bestChoice.seq; } GlobleVar.AiBestChoice = root.bestChoice; GlobleVar.findChoices(root.bestChoice.choice, GlobleVar.chessboard, GlobleVar.choices); return(root.bestChoice.choice); }
//evaluation function public void eval(bool reverse) { int[,] tempChessboard = (int[, ])(GlobleVar.chessboard.Clone()); int i; //display(); //update tempChessboard only used for eval() function for (i = 0; i < depth; i++) { if (GlobleVar.AI == 2) { tempChessboard[choiceHistory[i] / 15, choiceHistory[i] % 15] = 2 - (i % 2); } else { tempChessboard[choiceHistory[i] / 15, choiceHistory[i] % 15] = 1 + (i % 2); } } //display(); //update tempChoices GlobleVar.findChoices(choice, tempChessboard, tempChoices); int[] left = new int[3]; int[] right = new int[3]; int[] all = new int[3]; if (parent != null) { tempValue = parent.tempValue; } int maxSeq = 0; for (int direction = 0; direction < 4; direction++) { all[0] = 1; all[1] = 0; all[2] = GlobleVar.PLAYER; left = layout(direction, choice, tempChessboard, reverse); right = layout(direction + 4, choice, tempChessboard, reverse); tempValue -= valueMap(left); tempValue -= valueMap(right); if (left[2] == 0) { all[1]++; } else if (left[2] == GlobleVar.AI) { all[1]++; left[1]++; tempValue += valueMap(left); } else { all[0] += left[0]; all[1] += left[1]; } if (right[2] == 0) { all[1]++; } else if (right[2] == GlobleVar.AI) { all[1]++; right[1]++; tempValue += valueMap(right); } else { all[0] += right[0]; all[1] += right[1]; } if (all[0] > maxSeq) { maxSeq = all[0]; } int newValue = valueMap(all); if (newValue == 500000 || newValue == -500000) { tempValue = newValue; possibleWinP = 1; } else if (newValue == 1000000 || newValue == -1000000) { tempValue = newValue; winningPoint = 1; if (parent != null && parent.possibleWinP == 1) { parent.possibleWinP = 0; } break; } else { tempValue += newValue; } } if (parent == null && maxSeq > GlobleVar.MostSeq[GlobleVar.AI]) { GlobleVar.MostSeq[GlobleVar.AI] = maxSeq; } if (depth == 1) { seq = maxSeq; if (maxSeq >= 5) { GlobleVar.winChoice[GlobleVar.AI] = choice; GlobleVar.MostSeq[GlobleVar.AI] = maxSeq; } } }
//put a piece private void pictureBox1_MouseClick(object sender, MouseEventArgs e) { //int param = 3600; GlobleVar.AI = 3 - GlobleVar.AI; GlobleVar.PLAYER = 3 - GlobleVar.PLAYER; GlobleVar.preValue = 0 - GlobleVar.preValue; GlobleVar.nodeCount = 0; //GlobleVar.STEPS = 3; //GlobleVar.EMPTY_3 = param; int x = (e.X - 5) / 35; int y = (e.Y - 5) / 35; if (GlobleVar.chessboard[x, y] == GlobleVar.PLAYER || GlobleVar.chessboard[x, y] == GlobleVar.AI) { //Console.WriteLine("Already has a piece, change a place."); //Console.WriteLine(); pictureBox1.MouseClick += pictureBox1_MouseClick; return; } GlobleVar.choice = x * 15 + y; GlobleVar.chessboard[x, y] = GlobleVar.AI; Display_GUI(GlobleVar.choice); pictureBox1.Update(); pictureBox1.MouseClick -= pictureBox1_MouseClick; GlobleVar.posHistory += GlobleVar.choice.ToString() + " "; TreeNode root = new TreeNode(GlobleVar.choice, null); //root.turn = 3 - root.turn; root.eval(false); GlobleVar.findChoices(GlobleVar.choice, GlobleVar.chessboard, GlobleVar.choices); GlobleVar.preValue = root.tempValue; if (pvp) { GlobleVar.sh.sendMessage("position", GlobleVar.choice.ToString()); } if (GlobleVar.MostSeq[GlobleVar.AI] >= 5) { pictureBox1.MouseClick -= pictureBox1_MouseClick; MessageBox.Show("You win!"); //Console.WriteLine("Congratulations! You Win!\n\n"); TimeSpan ts = DateTime.Now - GlobleVar.startTime; int level = GlobleVar.STEPS - 2; if (pvp) { level = 0; } if (GlobleVar.sh != null && radioButton1.Checked) { GlobleVar.sh.record(level, first, second, GlobleVar.user, Convert.ToInt32(ts.TotalSeconds), (moveCount + 1) / 2, GlobleVar.posHistory); } //GlobleVar.mysql.insert(0, GlobleVar.user, "AI", GlobleVar.user, Convert.ToInt32(ts.TotalSeconds), GlobleVar.round, GlobleVar.posHistory); //Console.ReadLine(); pvp = false; return; } if (!pvp) { AIMove(); } }