2.8.5 五子棋
接下来,我们使用之前学习的绘图技术,做一个五子棋的游戏。
注意,这个代码只实现了五子棋的落子、删除棋子和动画等逻辑实现,并没有把五子棋的游戏逻辑编写完整,比较简单易上手。
图片素材
package Draw;
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.image.BufferedImage;
import java.io.File;
public class Gobang {
//定义五子棋游戏窗口
private JFrame jframe = new JFrame("五子棋游戏"); //改动一,使用swing中的JFrame解决画面闪烁
//声明四个BufferedImage对象,分别记录四张图片
BufferedImage table;
BufferedImage black;
BufferedImage white;
BufferedImage selected;
//声明棋盘的宽和高(与棋盘图片的宽和高一致)
private final int TABLE_WIDTH = 535;
private final int TABLE_HEIGHT = 536;
//声明棋盘横向和纵向分别可以下多少子,它们的值都为十五(多少行多少列)
final int BOARD_SIZE =15;
//声明每个棋子占用棋盘的比率
final int RATE = TABLE_WIDTH/BOARD_SIZE;
//声明变量记录棋子对于x方向和y方向的偏移量,在像素中量出来的
final int X_OFFSET = 5;
final int Y_OFFSET = 6;
//声明一个二维数组,记录当前位置棋子的状态,如果索引[i][j]的值为 0-没有棋子, 1-白棋, 2-黑棋
int[][] board = new int[BOARD_SIZE][BOARD_SIZE];
//声明红色选择框的坐标,也是二维数组中的索引
int selected_X = -1;
int selected_Y = -1;
//自定义类继承Canvas,充当画布
private class ChessBoard extends JPanel{ //改动二,继承swing中JPanel而不是Canvas,解决画面闪烁
@Override
public void paint(Graphics g) {
//绘图
//绘制棋盘
g.drawImage(table,0,0,null);
//绘制选择框
if(selected_X>0 && selected_Y>0) //判断有移动时再开始绘制
//注意索引与真实位置的转换
g.drawImage(selected,selected_X*RATE+X_OFFSET,selected_Y*RATE+Y_OFFSET,null);
//绘制棋子
for (int i = 0; i < BOARD_SIZE; i++) {
for (int j = 0; j < BOARD_SIZE; j++) {
//绘制黑棋
if(board[i][j] == 2) g.drawImage(black,i*RATE+X_OFFSET,j*RATE+Y_OFFSET,null);
//绘制白棋
if(board[i][j] == 1) g.drawImage(white,i*RATE+X_OFFSET,j*RATE+Y_OFFSET,null);
}
}
}
}
ChessBoard chessBoard = new ChessBoard();
//声明变量,记录当前下棋的颜色,1-白棋, 2-黑棋
int board_type = 2;
//声明底部需要用的组件
Panel p = new Panel();
Button whiteBtn = new Button("白棋");
Button blackBtn = new Button("黑棋");
Button deleteBtn = new Button("删除");
public void refreshBtnColor(Color whitBtnColor, Color blackBtnColor, Color deleteBtnColor) { //用来刷新按钮的颜色
whiteBtn.setBackground(whitBtnColor); //setBackground来设置按钮(背景)颜色
blackBtn.setBackground(blackBtnColor);
deleteBtn.setBackground(deleteBtnColor);
}
public void init() throws Exception{
//组装视图,编写逻辑
//编写白棋按钮的逻辑
whiteBtn.addActionListener(e->{
//修改当前要下的棋子的标志为1,对应下白棋。
board_type = 1;
//刷新按钮的颜色
refreshBtnColor(Color.GREEN,Color.GRAY,Color.GRAY);
});
//黑棋和清除按钮的逻辑
blackBtn.addActionListener(e->{
//修改当前要下的棋子的标志为2,对应下黑棋。
board_type = 2;
//刷新按钮的颜色
refreshBtnColor(Color.GRAY,Color.GREEN,Color.GRAY);
});
deleteBtn.addActionListener(e->{
//修改当前要下的棋子的标志为0,对应着删除
board_type = 0;
//刷新按钮的颜色
refreshBtnColor(Color.GRAY,Color.GRAY,Color.GREEN);
});
//将按钮添加到面板中
p.add(whiteBtn);
p.add(blackBtn);
p.add(deleteBtn);
//将面板添加到frame的南部区域
jframe.add(p,BorderLayout.SOUTH);
//组装棋盘
//初始化图片
//这里保存图片时需要在项目里建立一个文件夹,来存放图片,不然放在其他地方好像都读不到。。
table = ImageIO.read(new File("E:\\java_untitled\\calculatoe\\img\\table.jpg"));
black = ImageIO.read(new File("E:\\java_untitled\\calculatoe\\img\\black.gif"));
white = ImageIO.read(new File("E:\\java_untitled\\calculatoe\\img\\white.gif"));
selected = ImageIO.read(new File("E:\\java_untitled\\calculatoe\\img\\selected.gif"));
//处理棋盘的游戏逻辑,如红色选择框随鼠标移动,鼠标点击便下子
//处理鼠标移动
chessBoard.addMouseMotionListener(new MouseMotionAdapter() {
//当鼠标移动时会调用该方法
@Override
public void mouseMoved(MouseEvent e) {
selected_X = (e.getX()-X_OFFSET)/RATE;//获取此时鼠标的坐标-偏移量/比率,就能得到下棋子的坐标
selected_Y = (e.getY()-Y_OFFSET)/RATE;
chessBoard.repaint();
}
});
//处理鼠标点击
chessBoard.addMouseListener(new MouseAdapter() {
//当鼠标被点击后会调用该方法
@Override
public void mouseClicked(MouseEvent e) {
int xPos = (e.getX()-X_OFFSET)/RATE;//跟上面一样得到真实坐标
int yPos = (e.getY()-Y_OFFSET)/RATE;
board[xPos][yPos] = board_type;//更新坐标中的标记意味已经下子了
chessBoard.repaint();
}
//当鼠标退出区域时,重置界面,使selected_X和selected_Y为-1
@Override
public void mouseExited(MouseEvent e) {
selected_X = -1;
selected_Y = -1;
chessBoard.repaint();
}
});
chessBoard.setPreferredSize(new Dimension(TABLE_WIDTH,TABLE_HEIGHT));//设置画布
jframe.add(chessBoard);
//设置frame最佳大小并可见
jframe.pack();
jframe.setVisible(true);
}
public static void main(String[] args) throws Exception {
new Gobang().init();
}
}