前言
lab2的P3部分相比于前两P,更有点软件的味道,在这一部分里面,我们需要自己设计ADT,并使用这些ADT作出一个棋类游戏的软件(没有加入行棋规则,但有基础的吃,移动,拿走等回合制)。我们不再像前两部分一样仅仅只是设计了一个或者两个比较简单的ADT,这一部分最有考验的地方应该就是如何去设计这些ADT,并且将其组装起来。
任务很明确,ADT在实验指导书上都有给出来,很明显我们需要做两个棋盘,一个是象棋的,一个是围棋的,由于象棋和围棋的行棋规则并不完全相同,我们还要区分不同的下棋规则。然后就是需要实验各个具体的ADT,关于ADT设计的方面我确实没有太多的可以分享的,每个人都有自己的方式和想法,那我就着重讲一下如何去建立可视化的棋盘。
预备知识
首先我们要了解一定的GUI的知识,java中GUI实现大体分为两种,我使用的一种是java Swing图形开发,这里给大家推荐一位大神做的十分详细的关于Swing图形界面开发的目录:Java Swing 图形界面开发,里面各种各样的知识都有,我就是靠这个活下来的[doge][doge]
象棋的可视化
我们先来分析一下象棋棋盘的特征,长宽高什么的就不说了,比较显著的特征就是它的棋的落子地方是一个个颜色交替的方块,重点是方块,所以在Swing布局里头有一个特别合适的布局就是网格布局,简直是完美契合象棋棋盘,网格布局,顾名思义就是整个页面被分割成大小均匀的网格,所以我们在建立可视化界面的时候,对JPanel的布局可以选择网格布局(GridLayout)
private JPanel panel = new JPanel(new GridLayout(8, 8));
我选择对每一个都加入一个组件(JLabel),我们可以建立一个二维数组,对应棋盘的坐标
private JLabel[][] labels = new JLabel[8][8];
接下来就是初始化棋盘,我们首先要对棋盘进行上色,就是对组件的背景设置颜色,颜色是黑白间隔的
//创建棋盘
for (int i = 0; i < m; i++) {
for (int j = 0; j < m; j++) {
labels[i][j] = new JLabel();
if ((i + j + 7) % 2 == 0) {
labels[i][j].setBackground(Color.black);
}
else {
labels[i][j].setBackground(Color.white);
labels[i][j].setOpaque(true);
}
labels[i][j].setBorder(BorderFactory.createLineBorder(Color.BLACK));
panel.add(labels[i][j]);
}
}
然后就是摆放棋子,我建立了一个函数,专门放棋子的,其实就是等于在相应位置上的组件中插入图片,首先要先准备好各个棋子的图片,这个我也是在网上找的,大家也可以上网找找。我们在给定的位置插入图片就行。插入图片就需要用到Image的功能,代码如下:
ImageIcon image = null;
image = new ImageIcon("picture/P1.png");//导入图片
Image imgImage = image.getImage();//创建Image
imgImage = imgImage.getScaledInstance(100, 100, Image.SCALE_DEFAULT);//设置图片参数
image.setImage(imgImage);//设置图片
labels[piece.getPosition().x()][piece.getPosition().y()].setIcon(image);//将image插入到对应组件中
下面是演示效果:
怎么移动棋子呢?其实也很简单,我之前使用二维数组也是为了能偷个懒,我们直接更新对应组件的图片就行了。
//变化棋子位置,直接清空旧位置的棋子图片,然后在新位置重新添加
labels[x1][y1].setIcon(null);
GUIchess(piece);//这个是我自己写的函数,专门更新棋子的,方法是上述插入图片的方法
围棋的可视化
围棋的格子虽然也是一块一块的,但是围棋和象棋棋子落点是不一样的,象棋是落在格子里面,而围棋是落在交叉线上,所以如果简单的使用网格布局的话,其实达不到比较好的效果,那么我们可以选择另一种方式,就是我们仔细研究JPanel,发现它其实是有画布的,也就是有一个paint函数,这个函数是用来对整个面板进行绘制的,默认情况下是什么也没有,那么我们可以在这个画板上加上线条,把整个围棋棋盘在上面画出来。想仔细了解paint函数重写的小伙伴可以移步到我上面发的链接java Swing中,里面有十分详细的使用教程和例子。
既然棋盘可以画,那么棋子自然也可以画,就是画一个圆,然后对这个圆的位置稍作调整,并且对圆的颜色进行填充。我这里选择的是比较笨重的方法,直接遍历整个棋盘,对整个棋盘的棋子进行更新,因为我们其实不知道围棋一次提子会提多少个,所以就选择直接遍历整个棋盘了。
panel = new JPanel() {
private static final long serialVersionUID = 1L;
@Override
public void paint(Graphics graphics) {
super.paint(graphics);
//设置背景颜色
graphics.setColor(new Color(255, 215, 0));
graphics.fillRect(0, 0, 945, 945);
//绘制线段,每个线段相距50
graphics.setColor(Color.BLACK);
for (int i = 0; i < 19; i++ ) {
graphics.drawLine(20, 20+50 * i, 920, 20+i * 50);
graphics.drawLine(20+i * 50, 20, 20+i * 50, 920);
}
//画棋子
for ( int i = 0 ; i < 19 ; i++ )
for (int j = 0 ; j < 19 ; j++ ) {
Piece piece = board.getPieceOnBoard(i, j);//获取棋盘上的棋子
if (piece == null)
continue;
if ( piece.getColor().equals("black")) {
graphics.setColor(Color.black);
graphics.fillOval(5+i*50, 5+j*50, 30, 30);
}
else {
graphics.setColor(Color.white);
graphics.fillOval(5+i*50, 5+j*50, 30, 30);
}
}
//棋盘中的9个星位,半径为8
graphics.setColor(Color.black);
for (int i = 0; i < 3; i++ )
for (int j = 0; j < 3; j++ ) {
graphics.fillOval(162 + i * 300, 162 + j * 300, 16, 16);
}
}
而需要对棋盘进行变化的时候,那就直接更新这个画布就行
panel.updateUI();
效果如下:
对于初学者我再次强烈推荐@xietansheng这位大佬关于java Swing图像界面开发的博客:https://blog.youkuaiyun.com/xietansheng/article/details/72814492