Helpex - Trao đổi & giúp đỡ Đăng nhập
84

Tôi đang cố gắng để có được cảm giác về cách thiết kế và suy nghĩ theo cách hướng đối tượng và muốn nhận được một số phản hồi từ cộng đồng về chủ đề này. Sau đây là một ví dụ về một trò chơi cờ vua mà tôi muốn thiết kế theo cách OO. Đây là một thiết kế rất rộng và trọng tâm của tôi ở giai đoạn này chỉ là xác định ai chịu trách nhiệm về những thông điệp nào và cách các đối tượng tương tác với nhau để mô phỏng trò chơi. Vui lòng chỉ ra nếu có các yếu tố của thiết kế xấu (khớp nối cao, độ gắn kết xấu, v.v.) và cách cải thiện chúng.

Trò chơi cờ vua có các lớp sau

  • Bảng
  • Người chơi
  • Cái
  • Quảng trường
  • Trò chơi cờ vua

Board được tạo thành từ các hình vuông và do đó Board có thể chịu trách nhiệm tạo và quản lý các đối tượng Square. Mỗi mảnh cũng nằm trên một hình vuông nên mỗi mảnh cũng có một tham chiếu đến hình vuông nó đang ở. (Điều này có nghĩa không?). Mỗi mảnh sau đó có trách nhiệm tự di chuyển từ hình vuông này sang hình vuông khác. Lớp người chơi giữ các tham chiếu đến tất cả các mảnh mà anh ta sở hữu và cũng chịu trách nhiệm cho việc tạo của họ (Người chơi có nên tạo ra các mảnh không?). Người chơi có một phương thức TakeTurn, lần lượt gọi một phương thức movePiece thuộc về Class mảnh thay đổi vị trí của quân cờ từ vị trí hiện tại của nó sang vị trí khác. Bây giờ tôi bối rối về chính xác những gì Hội đồng quản trị phải chịu trách nhiệm. Tôi cho rằng cần phải xác định trạng thái hiện tại của trò chơi và biết khi nào trò chơi kết thúc. Nhưng khi một mảnh thay đổi nó ' Vị trí của bảng nên được cập nhật như thế nào? nó có nên duy trì một mảng các ô vuông riêng biệt trên những mảnh nào tồn tại và được cập nhật khi các mảnh di chuyển không?

Ngoài ra, ChessGame tạo ra các đối tượng Board và người chơi lần lượt tạo ra các hình vuông và mảnh tương ứng và bắt đầu mô phỏng. Tóm lại, đây có thể là mã trong ChessGame có thể trông như thế nào

Player p1 =new Player();
Player p2 = new Player();

Board b = new Board();

while(b.isGameOver())
{
  p1.takeTurn(); // calls movePiece on the Piece object
  p2.takeTurn();

}

Tôi không rõ làm thế nào để trạng thái của hội đồng quản trị sẽ được cập nhật. Mảnh nên có một tài liệu tham khảo để hội đồng quản trị? Đâu là trách nhiệm nằm? Ai giữ tài liệu tham khảo? Xin hãy giúp tôi với đầu vào của bạn và chỉ ra các vấn đề trong thiết kế này. Tôi cố tình không tập trung vào bất kỳ thuật toán hoặc chi tiết nào khác về chơi trò chơi vì tôi chỉ quan tâm đến khía cạnh thiết kế. Tôi hy vọng cộng đồng này có thể cung cấp những hiểu biết có giá trị.

84 hữu ích 3 bình luận 70k xem chia sẻ
53

Tôi thực sự chỉ viết một bản triển khai C # đầy đủ của một bàn cờ, quân cờ, luật lệ, v.v ... Đây là cách tôi mô hình hóa nó (thực hiện loại bỏ thực tế vì tôi không muốn lấy hết niềm vui ra khỏi mã hóa của bạn):

public enum PieceType {
    None, Pawn, Knight, Bishop, Rook, Queen, King
}

public enum PieceColor {
    White, Black
}

public struct Piece {
    public PieceType Type { get; set; }
    public PieceColor Color { get; set; }
}

public struct Square {
    public int X { get; set; }
    public int Y { get; set; }

    public static implicit operator Square(string str) {
        // Parses strings like "a1" so you can write "a1" in code instead
        // of new Square(0, 0)
    }
}

public class Board {
    private Piece[,] board;

    public Piece this[Square square] { get; set; }

    public Board Clone() { ... }
}

public class Move {
    public Square From { get; }
    public Square To { get; }
    public Piece PieceMoved { get; }
    public Piece PieceCaptured { get; }
    public PieceType Promotion { get; }
    public string AlgebraicNotation { get; }
}

public class Game {
    public Board Board { get; }
    public IList<Move> Movelist { get; }
    public PieceType Turn { get; set; }
    public Square? DoublePawnPush { get; set; } // Used for tracking valid en passant captures
    public int Halfmoves { get; set; }

    public bool CanWhiteCastleA { get; set; }
    public bool CanWhiteCastleH { get; set; }
    public bool CanBlackCastleA { get; set; }
    public bool CanBlackCastleH { get; set; }
}

public interface IGameRules {
    // ....
}

Ý tưởng cơ bản là Game / Board / etc chỉ đơn giản là lưu trữ trạng thái của trò chơi. Bạn có thể thao tác chúng để thiết lập một vị trí, nếu đó là điều bạn muốn. Tôi có một lớp thực hiện giao diện IGameRules chịu trách nhiệm:

  • Xác định những gì di chuyển là hợp lệ, bao gồm cả castling và en passant.
  • Xác định nếu một động thái cụ thể là hợp lệ.
  • Xác định khi nào người chơi ở trong kiểm tra / checkmate / bế tắc.
  • Thực hiện các động tác.

Tách các quy tắc khỏi các lớp trò chơi / bảng cũng có nghĩa là bạn có thể thực hiện các biến thể tương đối dễ dàng. Tất cả các phương thức của giao diện quy tắc đều lấy một Gameđối tượng mà chúng có thể kiểm tra để xác định di chuyển nào là hợp lệ.

Lưu ý rằng tôi không lưu trữ thông tin người chơi trên Game. Tôi có một lớp riêng Tablechịu trách nhiệm lưu trữ siêu dữ liệu trò chơi như ai đang chơi, khi trò chơi diễn ra, v.v.

EDIT: Lưu ý rằng mục đích của câu trả lời này không thực sự cung cấp cho bạn mã mẫu mà bạn có thể điền - mã của tôi thực sự có thêm một chút thông tin được lưu trữ trên mỗi mục, nhiều phương thức, v.v ... Mục đích là để hướng dẫn bạn hướng tới mục tiêu bạn đang cố gắng để đạt được.

53 hữu ích 5 bình luận chia sẻ
4

Đây là ý tưởng của tôi, cho một ván cờ khá cơ bản:

class GameBoard {
 IPiece config[8][8];  

 init {
  createAndPlacePieces("Black");
  createAndPlacePieces("White");
  setTurn("Black");

 }

 createAndPlacePieces(color) {
   //generate pieces using a factory method
   //for e.g. config[1][0] = PieceFactory("Pawn",color);
 }

 setTurn(color) {
   turn = color;
 }

 move(fromPt,toPt) {
  if(getPcAt(fromPt).color == turn) {
    toPtHasOppositeColorPiece = getPcAt(toPt) != null && getPcAt(toPt).color != turn;
    possiblePath = getPcAt(fromPt).generatePossiblePath(fromPt,toPt,toPtHasOppositeColorPiece);
   if(possiblePath != NULL) {
      traversePath();
      changeTurn();
   }
  }
 } 

}

Interface IPiece {
  function generatePossiblePath(fromPt,toPt,toPtHasEnemy);
}

class PawnPiece implements IPiece{
  function generatePossiblePath(fromPt,toPt,toPtHasEnemy) {
    return an array of points if such a path is possible
    else return null;
  }
}

class ElephantPiece implements IPiece {....}
4 hữu ích 0 bình luận chia sẻ
loading
Không tìm thấy câu trả lời bạn tìm kiếm? Duyệt qua các câu hỏi được gắn thẻ chess oop , hoặc hỏi câu hỏi của bạn.

Có thể bạn quan tâm

loading