OOP设计,Java Swing,国际象棋游戏,instanceof

时间:2013-12-14 01:21:38

标签: java swing oop instanceof

好的,我正在制作一个简单的java swing国际象棋游戏。这个问题更多的是关于OOP设计然后是Java Swing。

我有以下内容:

  • 我有一个实现JPanel的Panel类。
  • 然后我有一个从我的Panel类
  • 扩展的抽象类Piece
  • 然后我有不同作品的课程:Pawn,King,Bishop等,从我的Pieces课程延伸

在我的主要ChessGame课程中:

  • 我使用Panel数组来存储我的主板布局
  • 因此,数组将存储Panel对象,用于没有任何碎片的棋盘位置。
  • 它将存储子类,如Pawn,Queen,Bishop等(板块放置件)

因此,左上方(0,0)映射到myArray [0] [0]

我的问题是,要检查这个地方是空的还是有棋子我必须使用:

        if(panels[x][y] instanceof Piece){
            ((Piece)panels[x][y]).makeMove();
        }

我问的是这个糟糕的设计?我知道我应该试着远离实例。 什么是更好的方法?

感谢。

6 个答案:

答案 0 :(得分:4)

您不应将模型代码(Piece)与视图代码(JPanels)结合使用。如果您想要更改电路板的显示方式,您必须更改电子存储的方式!

更好的设计可能是将Piece与JPanel分开。然后,您可以使用单个JPanel显示片段矩阵:Pieces[8][8]

我的问题是,要检查这个地方是空的还是有棋子我必须使用:

如果你使用矩阵,你可以只有一个空单元格或使用Null Object模式来获得一个“空”。

修改

棋子矩阵中的每个单元格都是棋盘中的正方形,因此piece[0][0]将成为棋盘的顶角(A8)。

要绘制棋盘,您的paintComponent()方法必须迭代此矩阵并适当地绘制每个单元格。有几种方法可以实现这一点:

  1. 您需要执行类似的检查实例以不同方式绘制每种类型的作品

  2. 使用策略模式创建一个新的中间“绘制策略”对象。这可能需要策略对象矩阵而不是片段对象。您可能仍需要执行检查实例,但可能只需要创建一次策略对象。

答案 1 :(得分:0)

您必须在画布上绘制棋盘和棋子,而不是将面板拆分为8x8较小的面板。后来球员们最终会拖着船上的棋子。你也可以在国际象棋游戏中寻找Bitboard演示文稿,虽然这个演示文稿只需要能够“思考”快速计算的国际象棋引擎,但是当你必须检查该玩家试图做出的移动是否仍然有用时正确的。

Posible Bitboard:

public class BitBoard
{
    public static final int P = 0;
    public static final int N = 2;
    public static final int B = 4;
    public static final int R = 6;
    public static final int Q = 8;
    public static final int K = 10;

    public static final int p = 1;
    public static final int n = 3;
    public static final int b = 5;
    public static final int r = 7;
    public static final int q = 9;
    public static final int k = 11;

    // empty field
    public static final int empty = 12;

    // number of pieces , squares
    public static final int nPieces = 12;
    public static final int nSquares = 64;

    public static final int whitePieces = 12;
    public static final int blackPieces = 13;
    public static final int nBoards = 14;

    public static long squareBits[];

    // static member initialization
    static
    {
        squareBits = new long[64];
        long square = 1;
        square = square << 8 * 8 - 1;
        for (int i = 0; i < 64; i++) {
            squareBits[i] = square >>> i;
        }
    }

    long bitBoards[];

    public BitBoard() {
        bitBoards = new long[nBoards];
    }

    public boolean initBoard()
    {
        // Put the pieces on the board
        EmptyBoard();
        addPiece(0, r);
        addPiece(1, n);
        addPiece(2, b);
        addPiece(3, q);
        addPiece(4, k);
        addPiece(5, b);
        addPiece(6, n);
        addPiece(7, r);
        for (int i = 8; i < 16; i++) {
            addPiece(i, p);
        }

        for (int i = 48; i < 56; i++) {
            addPiece(i, P);
        }
        addPiece(56, R);
        addPiece(57, N);
        addPiece(58, B);
        addPiece(59, Q);
        addPiece(60, K);
        addPiece(61, B);
        addPiece(62, N);
        addPiece(63, R);

        return true;
    }

    public boolean addPiece(int whichSquare, int whichPiece)
    {
        bitBoards[whichPiece] |= squareBits[whichSquare];
        bitBoards[nPieces + (whichPiece % 2)] |= squareBits[whichSquare];
        return true;
    }

    private boolean removePiece(int whichSquare, int whichPiece)
    {
        bitBoards[whichPiece] ^= squareBits[whichSquare];
        bitBoards[nPieces + (whichPiece % 2)] ^= squareBits[whichSquare];
        return true;
    }

    private boolean EmptyBoard()
    {
        for (int i = 0; i < nBoards; i++)
        {
            bitBoards[i] = 0;
        }
        return true;
    }
}

答案 2 :(得分:0)

在考虑了您的问题并了解问题域后,我实际上会建议以下内容......

在您的班级Panel中实施一项功能int hasMass(),如下所示......

public int hasMass() {
  return 0;
}

在您的班级Piece中覆盖该功能,如下所示......

public int hasMass() {
  if (isWhite()) // white pieces are negative. 
    return -1;
  return 1; // black pieces positive.
}

现在你可以检查方块是否有一块,是否有另一块给定的...(因为它们的极性相反)......质量+质量== 0表示捕获,!= 0表示面板为空。当然,绝对值2(对于质量)意味着此举是非法的。

答案 3 :(得分:0)

我会将这些碎片的结构与渲染板分开。

例如,我会使棋子成为纯粹的模型,而不知道它们被渲染的知识。

Pieces (baseclass)
 +- Pawn
 +- Knight
 +- King
 +- Queen
 +- ..etc

这将允许您仅保留一个Pieces数组,其中空方块为空。

为简单起见,我只有一个peices矩阵:

Peices[][] board = new Pieces[8][8];

(当然是一种初始化方法来遍历你的'董事会'并填充董事会的初始职位)

然后我会看到一块由JPanel构成的可见板;一个叫做“国际象棋”的班级来管理游戏;以及移动功能中瓷砖/面板的实际渲染。想象:

// what a move might look like when initializing your panels
piece = board [0][0];
Chess.move(piece, 0 ,0);  //responsible for clearing the old panel and rendering the panel at target location.

当用户与您的游戏进行互动时......他们点击您的面板......它将为您提供面板坐标。你使用相同的坐标w /你的'板'来确定这件作品是什么......它可以移动等等。

像这样......

为了简单起见,我只想使用对象代表游戏板。最容易理解......此外,现在计算机速度很快。

答案 4 :(得分:0)

好的,开始时抛弃设置null的选项以指示该地方为空(你可以这样做但是使用Empty类只是在某种程度上“更好”。)

因此,假设您有一组Panel代表您的游戏板:

Panel[][] board;

现在进行ilustration,您的类层次结构如何:

abstract class Panel extends JPanel { ... }

class Empty extends Panel { ... }

abstract class Piece extends Panel { ... }

class Pawn extends Piece { ... }

...
  

我的Panel类是我的空类,不是吗?

不确定我是否了解你,但让我们看一下extends究竟意味着什么:在节目中nmodel 每件也是一个小组每个Pawn也是一块,所以每个Pawn可以做与Piece相同的事情(例如,4是复数,自然数或实数,所以在某种程度上,你可以说实数扩展复数,因为每个实数也是一个复数

所以现在你可以在getTexture()类和所有Panel子类中实现的Empty中声明一些很好的抽象Piece方法,并且在绘制{{1}时},你不需要看它是否为空。

答案 5 :(得分:0)

不是创建(我假设)每个部分几乎相同的类(Rook,Pawn,Queen等),你可以保留原始的Piece类,使其不抽象并添加{{1} }字段到它。 PieceType只是一个PieceType,它告诉我们放置了什么类型的作品(如果有的话)。现在,您可以使用enum进行检查,而不是使用instanceof。至少那是我在实施中所做的:)

对于我的8x8主板,我也使用panels[i][j].getType() == PieceType.ROOK代替JLabel