好的,我正在制作一个简单的java swing国际象棋游戏。这个问题更多的是关于OOP设计然后是Java Swing。
我有以下内容:
在我的主要ChessGame课程中:
因此,左上方(0,0)映射到myArray [0] [0]
我的问题是,要检查这个地方是空的还是有棋子我必须使用:
if(panels[x][y] instanceof Piece){
((Piece)panels[x][y]).makeMove();
}
我问的是这个糟糕的设计?我知道我应该试着远离实例。 什么是更好的方法?
感谢。
答案 0 :(得分:4)
您不应将模型代码(Piece)与视图代码(JPanels)结合使用。如果您想要更改电路板的显示方式,您必须更改电子存储的方式!
更好的设计可能是将Piece与JPanel分开。然后,您可以使用单个JPanel显示片段矩阵:Pieces[8][8]
。
我的问题是,要检查这个地方是空的还是有棋子我必须使用:
如果你使用矩阵,你可以只有一个空单元格或使用Null Object
模式来获得一个“空”。
修改强>
棋子矩阵中的每个单元格都是棋盘中的正方形,因此piece[0][0]
将成为棋盘的顶角(A8)。
要绘制棋盘,您的paintComponent()
方法必须迭代此矩阵并适当地绘制每个单元格。有几种方法可以实现这一点:
您需要执行类似的检查实例以不同方式绘制每种类型的作品
使用策略模式创建一个新的中间“绘制策略”对象。这可能需要策略对象矩阵而不是片段对象。您可能仍需要执行检查实例,但可能只需要创建一次策略对象。
答案 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
。