Java图形化界面编程——五子棋游戏 笔记

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();
    }
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是Java图形化界面五子棋的实现方法: 1. 创建一个棋盘类,用于绘制棋盘和处理子事件。 ```java import java.awt.*; import java.awt.event.*; import javax.swing.*; public class ChessBoard extends JPanel implements MouseListener { private static final int ROWS = 15; private static final int COLS = 15; private static final int CELL_SIZE = 30; private static final int MARGIN = 30; private static final int GRID_SIZE = CELL_SIZE * (ROWS - 1) + MARGIN * 2; private static final int PIECE_SIZE = (int) (CELL_SIZE * 0.8); private static final int PIECE_OFFSET = (CELL_SIZE - PIECE_SIZE) / 2; private static final int[][] POSITIONS = new int[ROWS][COLS]; private static final int EMPTY = 0; private static final int BLACK = 1; private static final int WHITE = 2; private int currentPlayer = BLACK; private boolean gameOver = false; public ChessBoard() { setPreferredSize(new Dimension(GRID_SIZE, GRID_SIZE)); setBackground(Color.ORANGE); addMouseListener(this); } public void paintComponent(Graphics g) { super.paintComponent(g); for (int i = 0; i < ROWS; i++) { g.drawLine(MARGIN, MARGIN + i * CELL_SIZE, MARGIN + (COLS - 1) * CELL_SIZE, MARGIN + i * CELL_SIZE); g.drawLine(MARGIN + i * CELL_SIZE, MARGIN, MARGIN + i * CELL_SIZE, MARGIN + (ROWS - 1) * CELL_SIZE); } for (int i = 0; i < ROWS; i++) { for (int j = 0; j < COLS; j++) { if (POSITIONS[i][j] == BLACK) { g.setColor(Color.BLACK); g.fillOval(MARGIN + j * CELL_SIZE + PIECE_OFFSET, MARGIN + i * CELL_SIZE + PIECE_OFFSET, PIECE_SIZE, PIECE_SIZE); } else if (POSITIONS[i][j] == WHITE) { g.setColor(Color.WHITE); g.fillOval(MARGIN + j * CELL_SIZE + PIECE_OFFSET, MARGIN + i * CELL_SIZE + PIECE_OFFSET, PIECE_SIZE, PIECE_SIZE); } } } } public void mouseClicked(MouseEvent e) { if (gameOver) { return; } int x = e.getX(); int y = e.getY(); if (x < MARGIN - PIECE_OFFSET || x > MARGIN + (COLS - 1) * CELL_SIZE + PIECE_OFFSET || y < MARGIN - PIECE_OFFSET || y > MARGIN + (ROWS - 1) * CELL_SIZE + PIECE_OFFSET) { return; } int row = Math.round((float) (y - MARGIN) / CELL_SIZE); int col = Math.round((float) (x - MARGIN) / CELL_SIZE); if (POSITIONS[row][col] != EMPTY) { return; } POSITIONS[row][col] = currentPlayer; repaint(); if (checkWin(row, col)) { gameOver = true; JOptionPane.showMessageDialog(this, (currentPlayer == BLACK ? "Black" : "White") + " wins!"); } else if (checkDraw()) { gameOver = true; JOptionPane.showMessageDialog(this, "Draw!"); } else { currentPlayer = (currentPlayer == BLACK ? WHITE : BLACK); } } public void mousePressed(MouseEvent e) {} public void mouseReleased(MouseEvent e) {} public void mouseEntered(MouseEvent e) {} public void mouseExited(MouseEvent e) {} private boolean checkWin(int row, int col) { int count = 1; for (int i = row - 1; i >= 0 && POSITIONS[i][col] == currentPlayer; i--) { count++; } for (int i = row + 1; i < ROWS && POSITIONS[i][col] == currentPlayer; i++) { count++; } if (count >= 5) { return true; } count = 1; for (int j = col - 1; j >= 0 && POSITIONS[row][j] == currentPlayer; j--) { count++; } for (int j = col + 1; j < COLS && POSITIONS[row][j] == currentPlayer; j++) { count++; } if (count >= 5) { return true; } count = 1; for (int i = row - 1, j = col - 1; i >= 0 && j >= 0 && POSITIONS[i][j] == currentPlayer; i--, j--) { count++; } for (int i = row + 1, j = col + 1; i < ROWS && j < COLS && POSITIONS[i][j] == currentPlayer; i++, j++) { count++; } if (count >= 5) { return true; } count = 1; for (int i = row - 1, j = col + 1; i >= 0 && j < COLS && POSITIONS[i][j] == currentPlayer; i--, j++) { count++; } for (int i = row + 1, j = col - 1; i < ROWS && j >= 0 && POSITIONS[i][j] == currentPlayer; i++, j--) { count++; } if (count >= 5) { return true; } return false; } private boolean checkDraw() { for (int i = 0; i < ROWS; i++) { for (int j = 0; j < COLS; j++) { if (POSITIONS[i][j] == EMPTY) { return false; } } } return true; } } ``` 2. 创建一个主类,用于启动程序。 ```java import javax.swing.*; public class Main { public static void main(String[] args) { JFrame frame = new JFrame("Five in a Row"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.getContentPane().add(new ChessBoard()); frame.pack(); frame.setVisible(true); } } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值