10

チェス ゲームの設計について助けが必要です。私はすでに始めていますが、私は Java にかなり慣れていないため、実際にはまったくプログラミングに慣れていません。

とにかく、抽象クラス Piece とサブクラスとしてのさまざまな部分があります。すべてのサブクラスに対して定義したい抽象クラスにメソッド movePiece があります。

現在行われているのは、駒をある正方形から別の正方形に移動することだけです。Piece オブジェクトを保持できる Square クラスがあり、ボードは 64x1 Square 配列で構成されています。

駒の動きは分かったけど、プログラミングはどうやってするの?MVC パターンを適用してみたいと思っていますが、パターンを使用するのはこれが初めてです。

基本的に、Graphics2D を使用して、各 Square のボックスを作成することを考えていました。次に、プレーヤーが駒をクリックすると、移動後に移動先として使用できる正方形が色で囲まれます。プレーヤーがこれらの四角形の 1 つをクリックすると、movePiece メソッドに既にあるコードが実行されます。

私がやりたいことは、Piece の各サブクラスで movePiece メソッドをオーバーライドすることです。問題は、これらのメソッドの 1 つでコードがどのように見えるかということです。たとえば、Pawn サブクラスを取り上げます。

コピー/貼り付けするコードを求めているのではなく、これを行う方法についてのいくつかの指針、最終的にはいくつかのサンプル コードを求めています。

ありがとう!

public class Game {


@SuppressWarnings("unused")
public static void main(String[] args){
    Board board = new Board();
} }

public class Board {

Square[] grid;

public Board(){
    grid = new Square[64];
}   
public Square getSquare(int i){
    return grid[i];
}   
public void setDefault(){

}   
public Boolean isMoveValid(){
    return null;    
} }

public class Square {

private Piece piece;

public void addPiece(Piece pieceType, String pieceColour, String pieceOwner) 
        throws ClassNotFoundException, InstantiationException, IllegalAccessException{

    PieceFactory factory = new PieceFactory();
    Piece piece = factory.createPiece(pieceType);

    piece.setColour(pieceColour);
    piece.setOwner(pieceOwner);

    this.piece = piece; 
}
public void addPiece(Piece pieceType){ 
    this.piece = pieceType; 
}
public void removePiece(){  
    piece = null;
}
public Piece getPiece(){
    return piece;       
}

class PieceFactory {     
     @SuppressWarnings("rawtypes")
     public Piece createPiece(Piece pieceType) 
            throws ClassNotFoundException, InstantiationException, IllegalAccessException{
         Class pieceClass = Class.forName(pieceType.toString());
         Piece piece = (Piece) pieceClass.newInstance();

         return piece;       
     } }

public void setColour(String colour){

} }

public abstract class Piece {

Board board;

public void setColour(String pieceColour) {
}

public void setOwner(String pieceOwner) {
}

public String getColour() {
    return "";
}

public String getOwner() {
    return "";      
}
public void movePiece(int oldIndex, int newIndex){
    board.getSquare(oldIndex).removePiece();
    board.getSquare(newIndex).addPiece(this);
}
public String toString(){
    return this.getClass().getSimpleName();
} }

あなたは私が知っている非常に基本的なコードを見たいと思っていました。[64] を [8][8] に変更します。必要以上に難しくしないようにしています。おそらく、Color と Owner を属性として組み合わせて、列挙型 (BLACK または WHITE) にすることができます。

フォーメーションが良くない場合は申し訳ありません。

4

6 に答える 6

18

ソフトウェアを設計するときは、メソッドをどのように使用するかを考えてから、メソッドのシグネチャ (およびテスト駆動開発を行う場合は単体テスト) を書き留めてから、それをどのように実装するかを考えると役立つと思います。

ここでこれを行うと、要件が

次に、プレーヤーが駒をクリックすると、移動後に移動先として使用できる正方形が色で囲まれます。

のような方法で満足することは不可能です

void move(Square destination);

実際にそれらを作成することなく、可能な動きを見つける方法がないからです。正方形を強調表示するには、次のような方法があればおそらく最適です。

Collection<Square> getPossibleMoves();

そして、実装できます

void move(Square destination) {
    if (!getPossibleMoves().contains(destination) {
        throw new IllegalMoveException();
    }

    this.location.occupyingPiece = null;
    this.location = destination;
    this.location.occupyingPiece = this;
}

getPossibleMoves の実装に関しては:

class Pawn extends Piece {
    @Override Collection<Square> getPossibleMoves() {
        List<Square> possibleMoves = new ArrayList<Square>();
        int dy = color == Color.white ? 1 : -1;
        Square ahead = location.neighbour(0, dy);
        if (ahead.occupyingPiece == null) {
            possibleMoves.add(ahead);
        }
        Square aheadLeft = location.neighbour(-1, dy);
        if (aheadLeft != null && aheadLeft.occupyingPiece != null && aheadLeft.occupyingPiece.color != color) {
            possibleMoves.add(aheadLeft);
        }
        Square aheadRight = location.neighbour(1, dy);
        if (aheadRight != null && aheadRight.occupyingPiece != null && aheadRight.occupyingPiece.color != color) {
            possibleMoves.add(aheadRight);
        }
        return possibleMoves;
    }
}

編集

class Knight extends Piece {
    @Override Collection<Square> getPossibleMoves() {
        List<Square> possibleMoves = new ArrayList<Square>();
        int[][] offsets = {
            {-2, 1},
            {-1, 2},
            {1, 2},
            {2, 1},
            {2, -1},
            {1, -2},
            {-1, -2},
            {-2, -1}
        };
        for (int[] o : offsets) {
            Square candidate = location.neighbour(o[0], o[1]);
            if (candidate != null && (candidate.occupyingPiece == null || candidate.occupyingPiece.color != color)) {
                possibleMoves.add(candidate);
            }
        }
        return possibleMoves;
    }
}
于 2011-01-05T23:18:26.503 に答える
2

あなたが説明したように、movePiece メソッド以上に、getPossibleMoves移動できるすべての場所を提供するメソッドが必要です。代わりに、または追加で、moveAllowed特定の場所へのピースの移動が許可されているかどうかを示すピースのメソッド。

Location生の (x,y) 座標を使用する代わりに、ボードでを定義するクラスを作成できます。これにより、チェスの文献で使用されているように、場所を「チェス座標」に変換する方法が提供されます。Location は として構築されnew Location(x, y)ます。

また、8x8 のセル ボードを表し、ピースのコンテナーであり、単なる配列よりも豊富なロジックを持つことができるクラスを使用したいと思います (たとえば、ブロックしているピースがないかどうかをBoard示す を与えることができます)。pathClear(from, to)ある場所から別の場所への移動など)

于 2011-01-05T23:12:42.490 に答える
1

与えられたピースのすべての可能な動きのリストを返す getValidMoves() というメソッドを作成します。そうすれば、ハイライトする四角形を見つけるためにボード全体をループする必要がなくなります。また、このようなメソッドが基本実装を必要としないように、基本クラスを抽象化します。

于 2011-01-05T23:15:46.557 に答える
1

私は isValidMove(Board boardState, int square) 抽象メソッドを実行します。これは各ピースでオーバーライドされ、有効な動きを強調表示するために呼び出されます (各描画反復で)。この同じメソッドが movePiece(int square) で呼び出され、移動が有効かどうかを確認し、有効な場合は移動を実行します。実際には、movePiece メソッドは Board 自体に属します (チェックするために Piece.isValidMove(...) を呼び出します)。

Pawn の isValidMove は次のようになります (これは疑似コードであることに注意してください)。

if ( boardState.getSquare(square).isFree() && square == this.square+ONE_FILE)
    return true;
else
    return false;
于 2011-01-05T23:04:12.350 に答える
0

私は自分のチェスゲームを終えたところです。ここに私が共有したいあなたのためのいくつかのヒント/ポイントがあります.

Java はオブジェクト指向言語であり、ゲームを論理オブジェクトに分割し、メソッドと対話することを忘れないでください。

(いつものように) メソッドをできるだけシンプルに保ちます。人間が読めるコードを作成します。時々!ピース (キング) 利用可能な動きをチェックする 8 つの異なる方法は、そのすべての計算作業を実行しようとするいくつかの不可解な for-sentence よりも読みやすいです。

MVC パターンを適用したい場合は、GUI を実際のボードへの参照を持つコントローラーと見なすこともできます。

Piece.java 保護された List allowedSquares; public abstract void calculateAllowedSquares(ChessBoard chessBoard); public void move(ChessBoard chessBoard, Square fromSquare, Square toSquare)

King クラスでは、move メソッドをオーバーライドする必要がある場合があります。たとえば、キャスリングの移動では、ルークを同時に移動する必要があります。

  • また、[][] ボードを使用しているため、どこから移動しているかを知る必要があります (passant move のルールを確認してください)。

チェス ゲームを作成する全体のコンセプトにおける 2 つの主要な問題は次のとおりです。駒がまったく動かないことがあります。2. チェック状況でキングを保護するためだけに駒を動かす方法。つまり、for.ex ビショップがあなたのキングを脅かしており、その脅威をブロックするために駒を動かすことができますが、それ以外の場所には移動できません。

そして最後に、ロジックと連携して GUI を作成することをお勧めします。ピース (またはピースがある正方形) をクリックすると、画面上で使用可能な正方形がすぐにわかります。何時間ものデバッグ時間を節約できます。

于 2011-01-27T22:30:46.477 に答える