Java编程 - 国际象棋移动(基本,没有AI)

时间:2011-01-05 22:57:30

标签: java chess

我在设计国际象棋游戏时需要帮助。我已经开始了,但还没有走得太远,因为我对Java很陌生,实际上是编程新手。

无论如何,我有我的抽象类Piece和各个部分作为子类。 我有一个方法movePiece,在我的抽象类中,我想为所有子类定义。

目前所做的只是将棋子从一个方格移动到另一个方格。我有一个可以容纳Piece对象的Square类,该板由64x1 Square数组组成。

我知道碎片是如何移动的,但我如何实际编程呢? 我想尝试应用MVC模式,但这是我第一次使用模式。

基本上我正在考虑使用Graphics2D为每个Square创建一个盒子。然后,当玩家点击一块时,移动后可用作目的地的方块将以某种颜色勾勒出轮廓。玩家点击其中一个方格后,我在movePiece方法中已有的代码将会运行。

我想要做的是在Piece的每个子类中覆盖我的movePiece方法。问题是,代码如何在其中一种方法中看到?以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结合起来作为一个属性,并使它成为枚举(黑色或白色)。

如果格式不正确,请注意。

6 个答案:

答案 0 :(得分: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;
    }
}

答案 1 :(得分:2)

你描述它的方式,不仅仅是movePiece方法,你需要一个getPossibleMoves方法,它可以为你提供所有可以移动的地方。或者或另外使用moveAllowed方法来判断一件作品是否允许移动到给定位置。

您可以创建一个类来定义板中的Location,而不是使用原始(x,y)坐标。这可以为您提供将位置转换为国际象棋文献中使用的“国际象棋坐标”的方法。位置将构建为new Location(x, y)

此外,我宁愿选择代表8x8单元板的Board类,并且是片段的容器,并且可以拥有比数组更丰富的逻辑(例如,可以给你一个pathClear(from, to)告诉你是否有任何碎片阻止你从一个地方到另一个地方的通道等)

答案 2 :(得分: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;

答案 3 :(得分:1)

我将创建一个名为getValidMoves()的方法,该方法返回给定片段的所有可能移动的列表。这样你就不必遍布整个电路板来找到要突出显示的方块。我还将基类抽象化,以便这样的方法不需要基本实现。

答案 4 :(得分:0)

我刚刚完成自己的国际象棋游戏。以下是我想要分享的一些提示/要点。

请记住,Java是面向对象的语言,将游戏划分为逻辑对象并与方法交互。

让方法尽可能简单(像往常一样)。制作人类可读代码。 有时! 8种不同的方法来检查碎片(King)可用的移动更具可读性,然后一些神秘的句子试图完成所有计算工作。

你想要应用MVC模式,你可能想要认为你的gui也是你的控制器,它可以引用你的实际电路板。

Piece.java protected List allowedSquares; public abstract void calculateAllowedSquares(ChessBoard chessBoard); public void move(ChessBoard chessBoard,Square from Square,Square toSquare)

在King类中,您可能需要覆盖move-method。例如,在铸造移动中,您需要同时移动车辆。

  • 您还需要知道您要移动的位置(检查passant移动的规则) 也许您需要清除移动的“fromSquare”,因为您正在使用[] []板。

制作国际象棋游戏的整个概念中的两个主要问题是: 1.你如何消除让你自己的国王检查的动作。有时碎片根本无法移动。 2.如何让一块物品移动只是为了在检查情况下保护你的王。意思是,如果for.ex主教威胁你的国王,你可以移动一些东西阻止这种威胁,但不管其他地方。

最后,我建议你与你的逻辑一起创造你的gui。当你点击你的作品(或作品所在的正方形)时,这是一个很大的帮助,你可以立即在屏幕上看到可用的正方形。它可以节省您数小时的调试时间。

答案 5 :(得分:0)

你必须慢下来!

首先你应该为每个项目创建一个类,并为每个项目添加可能的移动,并且还实现一种方法来检查游戏中可能的移动, 然后使用Netbeans GUI并添加一些JLabel并将其颜色更改为白色和黑色,这样您就可以很好地了解整个过程。

刚开始,不要犹豫,删除旧代码并使用新的更好的代码更改它们。 这就是它的工作方式。

祝你好运。