Giao diện tương tác là phần không thể thiếu trong game,phần nầy giúp người chơi tương tác với game,các chức năng trong game.Trong game này phần giao diện tương tác có các form,menu và các MessegerBox dùng để tương tác trực tiếp với người chơi.
• Form frmMain: Form chính, dùng cho 2 người chơi tương tác với các chức
năng của game như các menu để thực hiện các chức năng chơi trên new game,máy đơn,chơi mạng……đồng thời form này cũng là nơi 2 người chơi tương tác vơi vơi game khi chơi trên máy đơn.Khi thực hiện chơi trên máy đơn form hiện thi thời gian còn lại của 2 đối thủ.
• Form frmLanGame Dùng cho 2 người chơi trên máy đơn tương tác với
game trên mạng, hiển thị tên người chơi, thời gian còn lại của từng người chơi.Các nút button thực hiện các chức năng đuổi,xin đi lại,xin hòa,chịu thua, chơi lại exit.Trong quá trình chơi người chơi có thể trò chuyện thông qua chức năng chat.
• Form frmSelectGame: Form có chức năng hỗ trợ cài đặt thơi gian cho việc
chơi trên máy đơn
• Form frmFindGame: Form này có chức năng đưa ra danh sách các phòng game đã có.Đồng thơi nó còn có chức năng tạo phòng chơi giúp người chơi chủ động hơn trong việc chơi cờ.
• Form frmGameOptions: Form này có tác dụng hỗ trợ người chơi trên mạng cài đặt phong
chơi của mình như thời gian chơi,lựa chọn quân cờ,số lượt đi……
3.3.2.Nhóm class lưu trữ dữ liệu
• Để quản lí tốt ván cờ ta xây dựng cách quản lí sao cho hiệu quả nhất.
Lớp UcChessBoard.cs dùng để ghi nhận trạng thái của bàn cờ , thông tin, trạng thái các quân cờ của người chơi.
Thuộc tính
public int[,] _BoardState = new int[8,8] Lưu trạng thái bàn cờ1 ô cờ, gồm có: Hàng, Cột, Trống
public UcChessCell[,] arrChessCell = new UcChessCell[8, 8]
Mảng các ô cờ,mảng lưu 64 vị trí, tương ứng với [8x8] vị trí trên bàn cờ, mỗi phần tử của mảng là 1 ô cờ
public enum ChessSide public enum ChessPieceType public enum GameStatus
Quy định phe người chơi Quy định các quân cờ
Quy định tên phe thăng thua
Phương thức
private void InitBoardState() Đặt quân cờ lên bàn cờ với các quy ước cụ thể
public void CreateChessBoard()
Tạo ô cờ đen trắng từ trên xuông dưới từ trái sang phải.
public void DoMove(UcChessPiece Piece, clsMove move)
Kiểm tra quân cờ có thể di chuyển từ vị trí cũ đến vị trí mới hay không,cập nhật vị trí quân cờ mới,xóa vị trí quân cờ cũ….
3.3.3.Nhóm class quân cờ:
Gồm có clsRook, clsQueen, clsPawn, clsKnight, clsKing, clsBishop chứa các thuộc tính thiết lập thông tin về quân cờ và các phương thức của quân cờ đó
Thuộc tính
public int Hang Giá trị Hàng của quân cờ
public int Cot Giá trị Cột của quân cờ
public string Ten Tên quân cờ
public int Phe Phe 1 hoặc 2
Phương thức
public static bool
Promotion(UcChessPiece UcPawn, ChessPieceType PromoteTo)
Kiểm tra phong cấp cho tốt nhập thành
public static ArrayList
FindAllPossibleMove(int[,] State, Point pos)
Tìm tất cả các vị trí trên bàn cờ mà quân cờ có thể di chuyển được
CapturedPiece.Hide() Xoá quân cờ tại ô di chuyển đến(quân cờ bị ăn) ct.ChessPiece = Piece Đặt quân cờ tại vị trí mới Piece.PositionX = NewPos.X;
Piece.PositionY = NewPos.Y Gán tọa độ mới cho quân cờ public static void AddCastlingPoint(int[,]
State, ChessSide eSide, ArrayList arrMoves)
Kiểm tra nhập thành public static bool IsChecked(int[,]
arrState, ChessSide eSide, Point pos)
Kiểm tra tướng có bị chiếu hay không
3.3.4.Quản lý chung:
Gồm các chứa các thuộc tính và các phương thức được thiết lập thông số cho một ván cờ như bộ đếm thời gian mỗi nước đi,đếm ngược thời gian còn lại của các đối thủ…và các phương thức kiểm tra, thông báo các trạng thái của ván cờ như
mất kết nối,xin đi lai,xin hòa,xin thua, kiểm tra hết co.Lớp này được kế thừa từ các lớp cơ sở
Thuộc tính
public static NguoiChoi[] NguoiChoi=new NguoiChoi[2]
Tạo ra 2 người chơi: NguoiChoi[0] và NguoiChoi[1]
public static string TenNguoiChoi1 Tên NguoiChoi[0] public static string TenNguoiChoi2 Tên NguoiChoi[1] public static PictureBox
ThongBaoChieuTuong = new PictureBox()
PictureBox chứa picture thông báo tướng đang bị chiếu
public static Panel KetQua = new
Panel() Panel thông báo kết quả của ván cờ, bao gồm Label NguoiThang ghi tên của người thắng, 2 picturebox con có nhiệm vụ như 2 button là
ChoiLai(Chơi lại) và Thoat(thoát)
public static int LuotDi
Kiểm tra đến lượt đi của
NguoiChoi[0] hay NguoiChoi[1] (lượt đi của NguoiChoi[0] => LuotDi=0)
public static int winner
Xác định người thắng ván cờ (NguoiChoi[0] thắng => winner=0, NguoiChoi[1] thắng => winner=1), nếu chưa có người nào thắng thì winner=2
public static bool TinhThoiGian Thiết lập chức năng tính thời gian cho ván cờ (TinhThoiGian=True)
Phương thức
public static void DRAW Gửi yêu cầu xin hòa public static void DoiLuotDi()
Đổi lượt đi của người chơi bằng cách Khóa tất cả các quân cờ của phe vừa đi, mở Khóa tất cả các quân cờ của phe chuẩn bị đi
public static void Undo() Thực hiện thao tác Undo lại nước cờ gần nhất trong ván cờ đó public static void LOSE () Thông báo kết thúc ván cờ
public static void OCoTrong(int i, int
j) Trả về ô cờ trống cho vị trí [i,j] bằng cách reset các giá trị của struct ô cờ public static void DatQuanCo(Object
sender, QuanCo q, int i, int j)
Đặt quân cờ q vào vị trí [i,j]
public static bool IsChecked(int[,] arrState, ChessSide eSide, Point pos)
Kiểm tra và thông báo quân tướng phe nào bị chiếu nếu là nước đi chiếu tướng
3.4Sơ đồ luồng dữ liệu và một số biểu đồ
a.Vào nước đi
Vào nước đi :
• Nhận B1 từ người dùng.
• Đọc B2 tương ứng từ bộ nhớ chính.
• Kiểm tra quy định ghi nhận nước đi.
• Nếu hợp lệ :
o Ghi B3 vào bộ nhớ chính (Ghi nhận nước đi). if (clsChessEngine.CanMove(arrMove, NewPos) == true) {
UnHighlightLastMove(); PushState();
string strLastCell = Convert.ToChar(CurPos.X + 64) + CurPos.Y.ToString(); string strNewCell = Convert.ToChar(NewPos.X + 64) + NewPos.Y.ToString(); this._BoardState[CurPos.X, CurPos.Y] = 0;//Đánh dấu vị trí cũ không chứa quân cờ
this._BoardState[NewPos.X, NewPos.Y] = (int)Piece.Type * 10 + (int)Piece.Side;
//Kiểm tra xem quân vua có bị chiếu không bool bCapture = false;
//Lấy vị trí Bắt tôt qua đường nếu có if (Piece.Type == ChessPieceType.Pawn) {
if (Math.Abs(NewPos.Y - CurPos.Y) == 2) {
B1: thông tin về nước đi. (vị trí cũ, vị trí mới).
B2 : thông tin để kiểm tra quy định ghi nhận bước đi (tình trạng và vị trí của tất cả quân cờ trên bàn cờ).
B3 : tình trạng và vị trí mới của tất cả các quân cờ trên bàn cờ.
người chơi cờ
vào nước đi B1
B3 B2
_EnPassantPoint = clsPawn.GetEnPassantPoint(this._BoardState, NewPos);
}
else if (CurPos.X == NewPos.X) {
_EnPassantPoint = new Point(); }
//Thực hiện nước bắt tốt qua đường if (NewPos == _EnPassantPoint) {
Point CapturedPoint;
if (Piece.Side == ChessSide.White)
CapturedPoint = new Point(_EnPassantPoint.X, _EnPassantPoint.Y - 1);
else
CapturedPoint = new Point(_EnPassantPoint.X, _EnPassantPoint.Y + 1);
UcChessCell bt = arrChessCell[CapturedPoint.X, CapturedPoint.Y]; this._BoardState[CapturedPoint.X, CapturedPoint.Y] = 0;//Đánh dấu vị trí cũ không chứa quân cờ
stkCapturedPieces.Push(bt.ChessPiece); bt.ChessPiece.Hide();
bt.ChessPiece = null;
_EnPassantPoint = new Point(); bCapture = true;
} } else {
_EnPassantPoint = new Point(); }
if (ct.ChessPiece != null && ct.ChessPiece.Side != Piece.Side)//Nếu đã có quân cờ đặt tại ô đến
{
UcChessPiece CapturedPiece = ct.ChessPiece; stkCapturedPieces.Push(CapturedPiece);
CapturedPiece.Hide();//Xóa quân cờ tại ô Di chuyển đến if (CapturedPiece.Type == ChessPieceType.Rook) {
if (CapturedPiece.Side == ChessSide.White) {
if (CapturedPiece.PositionX == 1) QUEENsideCastling = false; if (CapturedPiece.PositionX == 8) KINGsideCastling = false; } else { if (CapturedPiece.PositionX == 1) queensideCastling = false; if (CapturedPiece.PositionX == 8) kingsideCastling = false; } } ct.ChessPiece = null; bCapture = true; }
Piece.UConCell.ChessPiece = null;//Ô cờ trước đó ko còn chứa quân cờ này nữa
//Dat Quan Co Tai Vi Tri Moi ct.ChessPiece = Piece;
Piece.UConCell = ct;
//Gán tọa độ mới cho quân cờ Piece.PositionX = NewPos.X; Piece.PositionY = NewPos.Y; string strPromote = "";
if (Piece.Type == ChessPieceType.Pawn) {
if (clsPawn.Promotion(Piece, move.PromoteTo) == true) {
this._BoardState[Piece.PositionX, Piece.PositionY] = (int)Piece.Type * 10 + (int)Piece.Side;
switch (Piece.Type) {
case ChessPieceType.Bishop: strPromote = "=B"; break;
case ChessPieceType.Knight: strPromote = "=N"; break;
case ChessPieceType.Rook: strPromote = "=R"; break;
case ChessPieceType.Queen: strPromote = "=Q"; break;
}
move.PromoteTo = Piece.Type; }
if (bCapture == true) {
PushMove(Piece.Side, strLastCell + "X" + strNewCell + strPromote); OnPieceCaptured(EventArgs.Empty);
PlayMusic(CapturedSound); }
else {
PushMove(Piece.Side, strLastCell + "-" + strNewCell + strPromote); PlayMusic(MovedSound); } //Cập Nhật trạng thái nhập thành if (Piece.Type == ChessPieceType.Rook) { if (Piece.Side == ChessSide.White) { if (Piece.PositionX == 1) QUEENsideCastling = false; if (Piece.PositionX == 8) KINGsideCastling = false; } else { if (Piece.PositionX == 1) queensideCastling = false; if (Piece.PositionX == 8) kingsideCastling = false; } } if (Piece.Type == ChessPieceType.King) { if (Piece.Side == ChessSide.White) { QUEENsideCastling = false; KINGsideCastling = false; } else { queensideCastling = false; kingsideCastling = false; } if (Math.Abs(NewPos.X - CurPos.X) == 2)//Nhập Thành {
if (NewPos.X == 3) {
UcChessCell OldRookCell = (UcChessCell)this.arrChessCell[1, NewPos.Y];
UcChessCell NewRookCell = (UcChessCell)this.arrChessCell[4, NewPos.Y];
this._BoardState[1, NewPos.Y] = 0;//Đánh dấu quân xe không còn ở vị trí cũ
this._BoardState[4, NewPos.Y] = 40 + (int)Piece.Side;//Đặt quân xe tại vị trí mới NewRookCell.ChessPiece = OldRookCell.ChessPiece; OldRookCell.ChessPiece = null; NewRookCell.ChessPiece.UConCell = NewRookCell; NewRookCell.ChessPiece.PositionX = NewRookCell.PositionX; NewRookCell.ChessPiece.PositionY = NewRookCell.PositionY; } else {
UcChessCell OldRookCell = (UcChessCell)this.arrChessCell[8, NewPos.Y]; UcChessCell NewRookCell = (UcChessCell)this.arrChessCell[6, NewPos.Y]; this._BoardState[8, NewPos.Y] = 0;//Đánh dấu quân xe không còn ở vị trí cũ this._BoardState[6, NewPos.Y] = 40 + (int)Piece.Side;//Đặt quân xe tại vị trí mới NewRookCell.ChessPiece = OldRookCell.ChessPiece; OldRookCell.ChessPiece = null; NewRookCell.ChessPiece.UConCell = NewRookCell; NewRookCell.ChessPiece.PositionX = NewRookCell.PositionX; NewRookCell.ChessPiece.PositionY = NewRookCell.PositionY; } } } arrFEN.Add(clsFEN.GetPiecePlacementString(this._BoardState)); this._GameStatus = clsChessEngine.GetGameStatus(this._BoardState, arrFEN, Piece.Side); if (this._GameStatus == GameStatus.BlackWin) { PlayMusic(CheckMatedSound); DisplayMessage("Quân Đen Thắng !");
} if (this._GameStatus == GameStatus.WhiteWin) { PlayMusic(CheckMatedSound); DisplayMessage("Quân Trắng Thắng !"); } if (this._GameStatus == GameStatus.Draw) { if (clsChessEngine.CheckThreefoldRepetition(arrFEN)) DisplayMessage("Ván cờ Hòa do \"Bất Biến 3 Lần\"");
else if (clsChessEngine.CheckInsufficientMaterial(this._BoardState, Piece.Side))
DisplayMessage("Ván cờ Hòa do cả 2 bên không đủ quân chiếu bí đối phương"); else
DisplayMessage("Ván cờ Hòa do không còn nước đi hợp lệ"); }
if (this._GameStatus == GameStatus.NowPlaying && (clsKing.IsChecked(this._BoardState, ChessSide.Black) == true || clsKing.IsChecked(this._BoardState, ChessSide.White) == true)) {
PlayMusic(CheckedSound);
if ((this._OwnSide == ChessSide.White && this._WhiteToMove == false) || (this._OwnSide == ChessSide.Black && this._WhiteToMove == true)) DisplayMessage("Chiếu !"); } if (Piece.Side == this._OwnSide) { AlreadyMakeMove = true; }
//Chuyển lượt đi cho đối phương if (Piece.Side == ChessSide.Black) this.WhiteToMove = true;
else
LastMove = move; HighlightLastMove(); OnMoveMaked(EventArgs.Empty); } else {
Piece.UConCell.ChessPiece = Piece;// tra về ô cũ }