public void ComputerMove(int player, int difficulty) //máy đánh ( có thể đánh cho người hoặc đánh cho máy) { if (_StackMoves.Count == 0) //khi máy đánh trước(chưa có quân nào trên bàn cờ) thì đánh vào giữa bàn cờ { int L = _CaroBoard.LineAmount / 2, C = _CaroBoard.ColumnAmount / 2; _Nodes[L, C].NStatus = player; _Nodes[L, C].PaintNewNode(); //tô màu cho nước mới đánh cho dễ thấy _Nodes[L, C].Draw(); _Player = -player; _StackMoves.Push(_Nodes[L, C]); return; } VMove Move = new VMove();; switch (difficulty) //tìm kiếm nước đi tùy theo độ khó đã chọn { case 1: Move = FindCMove(1, 1, 1, player, -10, 10); break; //dễ case 2: Move = FindCMove(3, 2, 2, player, -10, 10); break; //thường case 3: Move = FindCMove(5, 3, 3, player, -10, 10); break; //khó case 4: Move = FindCMove(8, 3, 3, player, -10, 10); break; //rất khó } _Nodes[Move.x, Move.y].NStatus = player; //set trạng thái _Nodes[Move.x, Move.y].PaintNewNode(); //tô màu và vẽ quân cờ _Nodes[Move.x, Move.y].Draw(); _StackMoves.Peek().Del(); //xóa màu của nước trước _StackMoves.Peek().Draw(); _Player = -player; //nhường lượt chơi lại _StackMoves.Push(_Nodes[Move.x, Move.y]); //lưu vào stack }
private List <VMove> EValue(int player) //lượng giá các nước đi trong khu vực tìm kiếm { List <VMove> ValueBoard = new List <VMove>(); //mảng lưu các nước đi đã được lượng giá List <CaroNode> search = SearchArea(2); // khu vực tìm kiếm foreach (CaroNode a in search) //lượng giá { long AttackPoint = AttackPointHorizontal(a.Line, a.Column, player) + AttackPointVertical(a.Line, a.Column, player) + AttackPointDiagonalL(a.Line, a.Column, player) + AttackPointDiagonalR(a.Line, a.Column, player); long DefendPoint = DefendPointHorizontal(a.Line, a.Column, player) + DefendPointVertical(a.Line, a.Column, player) + DefendPointDiagonalL(a.Line, a.Column, player) + DefendPointDiagonalR(a.Line, a.Column, player); if (AttackPoint >= DefendPoint) //Nếu điểm tấn công lớn hơn { VMove b = new VMove(AttackPoint, DefendPoint); //khởi tạo và thêm vào list điểm chính là tấn công b.x = a.Line; b.y = a.Column; ValueBoard.Add(b); } else { VMove b = new VMove(DefendPoint, AttackPoint); //nếu không thì điểm chính là phòng ngư b.x = a.Line; b.y = a.Column; ValueBoard.Add(b); } } return(ValueBoard); }
private VMove VlMaxPos(List <VMove> ValueBoard) //lấy ra nước đi có giá trị lớn nhất { long temp = long.MinValue; VMove rs = new VMove(); int max = 0; for (int i = 0; i < ValueBoard.Count; i++) //lấy ra nước có điểm cao nhất , nếu bằng thì so sánh điểm phụ { if (ValueBoard[i].value > temp || (ValueBoard[i].value == temp && ValueBoard[i].subvalue > ValueBoard[max].subvalue)) { rs.x = ValueBoard[i].x; rs.y = ValueBoard[i].y; temp = ValueBoard[i].value; max = i; } } ValueBoard[max] = new VMove(rs.x, rs.y, long.MinValue, 0); //set giá tri xuống để không bị lấy ra lần nữa return(rs); }
private VMove FindCMove(int depth, int cmoveamount, int hmoveamount, int player, long alpha, long beta) { if (WinCheck(false) == true) //kiểm tra thắng thua nhưng không vẽ đường chiến thắng { if (_Result == -1) { return(new VMove(1, depth)); //nếu máy thắng thì trả về -1 và độ sâu } else if (_Result == 1) { return(new VMove(-1, depth)); // thua thì tra về 1 và độ sâu } else { return(new VMove(0, 0)); //hòa thì trả về 0 } } if (depth == 0) { return(new VMove(0, 0)); //độ sâu giới hạn thì trả về 0 } VMove temp; //nước đi tạm VMove rs = new VMove(); //nước đi kết quả if (player == 1) //nếu là lượt người chơi { List <VMove> vb = EValue(1); //lượng giá các nước đi của người chơi //hmoveamount = vb.Count(); VMove Bm = new VMove(2, 10); //nước đi tôt nhất VMove[] hMove = new VMove[hmoveamount]; //mảng lưu các nước đi tiềm năng for (int i = 0; i < hmoveamount; i++) //lấy hmoveamount nước đi tốt nhất từ mảng lượng giá { hMove[i] = VlMaxPos(vb); } for (int i = 0; i < hmoveamount; i++) { _Nodes[hMove[i].x, hMove[i].y].NStatus = 1; //đi nước đi này _StackMoves.Push(_Nodes[hMove[i].x, hMove[i].y]); temp = FindCMove(depth - 1, cmoveamount, hmoveamount, -1, alpha, beta); //Phát triển đến độ sâu tiếp theo và trả vê giá trị if (Bm.value > temp.value || (Bm.value == 1 && temp.value == 1 && Bm.depth > temp.depth) || (Bm.value == -1 && temp.value == -1 && Bm.depth < temp.depth)) { //lấy nước đi có giá trị nhỏ nhất ( nếu 2 nước đi dẫn đến chiến thăng (-1) thì depth cao nhất ngược lại dẫn đên thua (1) chon depth thấp nhất rs.value = Bm.value = temp.value; rs.depth = Bm.depth = temp.depth; rs.x = hMove[i].x; rs.y = hMove[i].y; } _StackMoves.Pop(); //trả lại nguyên trạng _Nodes[hMove[i].x, hMove[i].y].NStatus = 0; if (beta > Bm.value) { beta = Bm.value; //cắt tỉa alphabeta } if (beta <= alpha) { break; } } return(rs); } else { //nếu là lượt của máy } { List <VMove> vb = EValue(-1); //lượng giá các nước đi của người chơi //cmoveamount = vb.Count(); VMove Bm = new VMove(-2, -1); //nước đi tôt nhất VMove[] cMove = new VMove[cmoveamount]; //mảng lưu các nước đi tiềm năng for (int i = 0; i < cmoveamount; i++) //lấy cmoveamount nước đi tốt nhất từ mảng lượng giá { cMove[i] = VlMaxPos(vb); } for (int i = 0; i < cmoveamount; i++) { _Nodes[cMove[i].x, cMove[i].y].NStatus = -1; _StackMoves.Push(_Nodes[cMove[i].x, cMove[i].y]); //đi nước đi này temp = FindCMove(depth - 1, cmoveamount, hmoveamount, 1, alpha, beta); //Phát triển đến độ sâu tiếp theo và trả vê giá trị if (Bm.value < temp.value || (Bm.value == 1 && temp.value == 1 && Bm.depth < temp.depth) || (Bm.value == -1 && temp.value == -1 && Bm.depth > temp.depth)) { //lấy nước đi có giá trị nhỏ nhất ( nếu 2 nước đi dẫn đến chiến thăng (1) thì depth cao nhất ngược lại dẫn đên thua (-1) chon depth thấp nhất rs.value = Bm.value = temp.value; rs.depth = Bm.depth = temp.depth; rs.x = cMove[i].x; rs.y = cMove[i].y; } _StackMoves.Pop(); //trả về nguyên trạng _Nodes[cMove[i].x, cMove[i].y].NStatus = 0; if (beta < Bm.value) { beta = Bm.value; //cắt tỉa alphabeta } if (beta <= alpha) { break; } } return(rs); // trả về nước đi tốt nhất } }