2013-12-14 36 views
5

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

我有以下几点:

  • 我有一个实现的JPanel一个Panel类。
  • 我再有,从我的面板类扩展
  • 然后,我有我的不同的小品类的抽象类海贼王:典当,国王,主教等,从我的小品类

延伸。在我的主ChessGame类:

  • 我使用面板的阵列来存储我的板
  • 所以阵列将存储,面板对象的布局,与上没有片板的地方。
  • 它将存储时,子类,如兵,大号,毕晓普等(板地设有件)

所以,左上方(0,0)映射到MYARRAY [0] [0]

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

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

什么我问的是这种可怕的设计?我知道我应该尽量远离instanceof。 什么是更好的方法?

谢谢。

+0

你可以填写'null'来告诉没有Piece那里,或者你可以创建新的'Empty'类并继承Panel,然后是的,instanceof是很好的解决方法。 – kajacx

+0

@kajacx作出答案。这十分完美。 – DiogoSantana

+0

@kajacx感谢您的快速回复。面板对象提供了功能,它们构成了空板的位置。所以,我不确定null是否可行。我的面板类是我的空课,不是吗?它只是在棋盘上创造空位。 – user1543871

回答

0

您不必将面板拆分为8x8更小的面板,而必须在画布上绘制板和零件。随后,玩家们最终会拖着脚步移动棋子。您也可以在国际象棋比赛中寻找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; 
    } 
} 
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(对于大众)意味着此举是非法的。

4

您不应该将模型代码(Piece)与视图代码(JPanels)组合起来。如果你想改变棋盘的显示方式,你必须改变棋子的存储方式!

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

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

如果您使用的是矩阵,你可以有一个空单元格或使用Null Object模式有一个“空”的一块。

EDIT

在片矩阵中的每个单元是在所述基板上的正方形,从而piece[0][0]将是板(A8)的顶角。

要画板,你的paintComponent()方法将不得不遍历这个矩阵并适当地绘制每个单元格。有几种方法来实现这一点:

  1. 你需要做一个类似的instanceof检查,得出每种类型片的不同

  2. 创建一个新中间“涂料战略”使用的策略模式对象。这可能需要一个策略对象矩阵而不是块对象。您可能仍然需要执行检查实例,但可能只有一次才能创建策略对象。

+0

我同意,不知道我是否理解你的意思是根据方法?所以可以存储一个int或char数组,每一块都放在板上?然后添加JPanels来匹配Pieces数组的设置? – user1543871

+0

@ user1543871添加编辑 – dkatzel

+0

好的谢谢。我会放弃它。那么,你认为绘图板比使用64个JPanel更好? – user1543871

0

我会保持一个结构的碎片分开的渲染板。

例如,我会让棋子纯粹模型w/o他们被渲染的打击知识。

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

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

为了简单起见,我只是有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. 

当用户交互瓦特/你game..they单击panels..which会给你的面板坐标。您可以使用相同的坐标W /你的“公告板”,以确定哪些片is..how,它可以移动等。

类似的东西...

我只想使用对象代表游戏板。 ..为了简单。最容易理解......除此之外,现在计算机已经足够快了。

+0

是的完全同意。有关如何解决此问题的任何建议?也许一个int或字符串数​​组来存储板设置?然后将适当的JPanel匹配到数组的每个元素? – user1543871

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 { ... } 

... 

我的面板类我的空班不是吗?

不知道如果我理解你,但让我们来看看什么extends表示正好:在秀nmodel 每一块也是面板每个典当也是件,所以每一个典当能做与Piece一样的东西(例如,4是复数以及自然数或实数,所以某种意义上,可以说实数扩展复数,因为每个实数也是一个复数号码

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

0

而不是创建(我认为)每个片段(白嘴鸦,典当,女王等)几乎相同的类,你可以保留原来的Piece类,使其非抽象,并添加一个PieceType字段。 PieceType只是一个enum,它告诉什么类型的片(如果有)被放置在那里。现在您可以使用panels[i][j].getType() == PieceType.ROOK来检查,而不是使用instanceof。至少这是我在做我的实施:)

我也使用JLabel而不是JPanel为我的8x8板。

+0

这些类将不会完全相同,每个类都有用于进行移动的方法 – user1543871

+0

将UI代码与逻辑分开是最佳做法。这意味着将移动代码(和检查逻辑,en passant等)放置在面板之外,并保持面板仅用于显示任何部分(如果有)。但这取决于你。如果需要,请查看MVC(模型 - 视图 - 控制器)模式。 – async