从无开始的JAVA程序五子棋的实现

五子棋开发思路及步骤

当开始实现五子棋程序时,首先想要应该有哪些步骤,我们要知道五子棋程序中要实现的部分

我们需要实现的部分

一,拥有五子棋的游玩页面或叫做操作窗体

二,对五子棋玩法的基本实现

三,对五子棋一些功能按键的创建和实现

第一部分的实现思路

·基础的界面棋盘开发

1: 创建一个窗体 (窗体需要继承JFrame 重写paint方法)

GoFrame gf = new GoFrame();//创建窗体
        //设置各种设置
        gf.setTitle("五子棋");
        gf.setSize(1000, 900);
        gf.setLocation(500, 300);
        gf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        gf.setLayout(null);// 无布局

2: 创建一个监听器类 实现鼠标监听器 在按下中获取坐标用于下棋

GoListener gl = new GoListener();

  注意:此监听器要创建于你的显示类的外部,不然内部无法引用

gf.addMouseListener(gl);// 鼠标监听器
gl.g = gf.getGraphics();// 画笔

注意:此监听器要创建于你的显示类的内部,用以引用

3: 创建一个GoUtils类 用于设定棋盘的固定数据 ,定义绘制棋盘网格的方法

package yjh1206;

import java.awt.*;
import javax.swing.*;

public class GoUtils {
    

}

以上是一个刚创建好的GoUtils类,首先你要定义棋盘绘制的方法

首先我们思考,关于棋盘,其所有的数据都是一个定值无论是格子数还是各行各列之间的间距,若不是这样,创建出来的棋盘必然是一个千奇百怪的样子,却唯独不是我们想要的棋盘,于是乎,你需要定义棋盘的静态参数,用以维持棋盘的协调性

  3.1 以下是我的棋盘数据

// 静态常量 static(静态-唯一-使用类名调用) final(最终的 - 不可变)
    // 棋盘的左上角坐标
    public static final int X = 50;
    public static final int Y = 75;
    // 棋盘的格子列数行数
    public static final int COL = 15;
    public static final int ROW = 15;
    // 每个格子的大小 棋子的尺寸
    public static final int SIZE = 50;
    // 棋子状态
    public static final int EMPTY = 0; // 空
    public static final int BLACK_CHESS = 1;
    public static final int WHITE_CHESS = 2;

  因为后续需要对棋子进行操作,我们可以用一个二维数组去表示整个棋盘上的数据以及棋子的顺序情况

public static int[][] chessPad = new int[ROW + 1][COL + 1];//棋盘上的棋子状况表示
    public static int[][] chessIndexArr = new int[256][2];//下棋的顺序情况

  3.2 除此之外,要想完成棋盘的绘制还需要在类中定义棋盘的绘制方法

public static void drawChessPad(Graphics g) {

        g.setColor(new Color(81, 142, 80));//添加背景
        g.fillRect(X - SIZE / 2, Y - SIZE / 2, (COL + 1) * SIZE, (ROW + 1) * SIZE);
        g.setColor(Color.BLACK);

        for (int i = 0; i <= COL; i++) {
            g.drawLine(X, Y + i * SIZE, X + COL * SIZE, Y + i * SIZE);// 横线
            g.drawLine(X + i * SIZE, Y, X + i * SIZE, Y + ROW * SIZE);// 纵线

        }
    }

  当然以上方法中为了棋盘的美观,利用画笔给棋盘添加了一块绿色的背景

4: 在paint方法中使用GoUtils 直接调用绘制棋盘的方法

package yjh1206;

import java.awt.*;
import javax.swing.*;

public class GoFrame extends JFrame {

    @Override
    public void paint(Graphics g) {
        super.paint(g);//调用父类保证基本的绘制

        GoUtils.drawChessPad(g);// 绘制棋盘
        GoUtils.drawAllChess(g);// 绘制棋子

    }
}

此时我们的第一部分已经完成,我们已经完成对棋盘的绘制,接下来,我们将完成第二部分

即对五子棋玩法的基本实现。五子棋的基本玩法即是下棋

第二部分的实现思路

·落子

1: 给窗体添加鼠标监听器 ,获取窗体的画笔对象 传给监听器

首先创建监听器类,并获取点击位置的坐标

package yjh1206;

import java.awt.*;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

public class GoListener extends GoUtils implements ActionListener, MouseListener {
    Graphics g;
    
    public void actionPerformed(ActionEvent e) {
        
    }

    @Override
    public void mousePressed(MouseEvent e) {

        int x = e.getX();
        int y = e.getY();

        if (check(x, y)) {// 检查落子条件
            pvpPlayer(x, y, g);// 落子 保存数据 绘制棋子
        }

    }

    @Override
    public void mouseClicked(MouseEvent e) {
    }

    @Override
    public void mouseReleased(MouseEvent e) {
    }

    @Override
    public void mouseEntered(MouseEvent e) {
    }

    @Override
    public void mouseExited(MouseEvent e) {
    }
}

其中pvpplayer是一个方法,了简化代码的复杂程度,此方法内包含了棋子数据存储,棋子绘制,棋子坐标换算,输赢判断 

2: 在按下方法,转换坐标为行列值,判断落子范围

public static void drawIndexStr(int x, int y, int chessIndex, Graphics g) {
        int c = (x - X + SIZE / 2) / SIZE;
        int r = (y - Y + SIZE / 2) / SIZE;
        int chessX = c * SIZE + X - SIZE / 2;
        int chessY = r * SIZE + Y - SIZE / 2;
    }

3:设置棋子标识用于设置黑白颜色实现交替落子

public void drawChess(int x, int y, Graphics g) {
        int c = (x - X + SIZE / 2) / SIZE;
        int r = (y - Y + SIZE / 2) / SIZE;
        // 颜色交替
        if (chessType == BLACK_CHESS) {
            g.setColor(Color.BLACK);
            chessType = WHITE_CHESS;
        } else if (chessType == WHITE_CHESS) {
            g.setColor(Color.WHITE);
            chessType = BLACK_CHESS;
        }
    }

 注:上述行为可以将方法集中到一个方法中去调用以减少代码的繁复

public void pvpPlayer(int x, int y, Graphics g) {
        drawChess(x, y, g);
        drawIndexStr(x, y, chessIndex, g);
    }

4:根据行列值还原标准坐标,将棋子绘制在交叉点上

int chessX = c * SIZE + X - SIZE / 2;
        int chessY = r * SIZE + Y - SIZE / 2;
        g.fillOval(chessX, chessY, SIZE, SIZE);

可以将这段代码插入颜色改变代码中构成一个整体

 public void drawChess(int x, int y, Graphics g) {
        int c = (x - X + SIZE / 2) / SIZE;
        int r = (y - Y + SIZE / 2) / SIZE;
        // 颜色交替
        if (chessType == BLACK_CHESS) {
            g.setColor(Color.BLACK);
            chessType = WHITE_CHESS;
        } else if (chessType == WHITE_CHESS) {
            g.setColor(Color.WHITE);
            chessType = BLACK_CHESS;
        }
        int chessX = c * SIZE + X - SIZE / 2;
        int chessY = r * SIZE + Y - SIZE / 2;
        g.fillOval(chessX, chessY, SIZE, SIZE);
    }

·问题及解决

以上下棋的步骤已经结束,但是我们在运行中还会出现一些问题,比如

1,棋子会放出界外

2,原本放置过棋子的位置还能再添加棋子,并且覆盖原来的棋子

3,游戏没有输赢

接下来我们就要解决这些问题

首先是棋子出界和新棋子会覆盖老棋子的问题,因为已经创建过表示棋盘的二维数组chesspad,于是可以通过这个二维数组来解决此问题。

,先将棋盘上的棋子放入数组中(0表示空 1表示黑 2表示白)

public static void saveData(int x, int y) {
        int c = (x - X + SIZE / 2) / SIZE;
        int r = (y - Y + SIZE / 2) / SIZE;
        chessPad[r][c] = chessType;
        chessIndexArr[chessIndex][0] = r;
        chessIndexArr[chessIndex][1] = c;
        chessIndex++;
    }

,并将其添加入玩法方法(pvpplayer)

public void pvpPlayer(int x, int y, Graphics g) {
        saveData(x, y);
        drawChess(x, y, g);
        drawIndexStr(x, y, chessIndex, g);
    }

,创立一个方法check用以判断,判断是否出现问题

public boolean check(int x, int y) {
        int c = (x - X + SIZE / 2) / SIZE;
        int r = (y - Y + SIZE / 2) / SIZE;

        if (c > ROW || r > COL || x < X - SIZE / 2 || y < Y - SIZE / 2) {
            JOptionPane.showMessageDialog(null, "请在棋盘内落子");
            return false;
        }

        if (chessPad[r][c] != 0) {
            JOptionPane.showMessageDialog(null, "该位置已有棋子");
            return false;
        }

        return true;
    }

接下来就是游戏的输赢判断,关于输赢判断,五子棋的规则是首先横竖斜三个方向上出现五个连成一条直线的一方获得胜利,因此我们可以再每次下完一颗棋子时都进行一次判断,在三个方向上是否出现五颗棋子相同的情况,下面是判断的逻辑

private static int row(int[][] chessPad, int r, int c) {

            int count = 1; // 包括刚放下的棋子
            int player = chessPad[r][c];

            // 检查右侧连续棋子
            for (int i = 1; i < chessPad.length; i++) {
                int nextCol = c + i;
                if (nextCol >= chessPad.length)
                    break; // 超出棋盘范围
                if (chessPad[r][nextCol] == player) {
                    count++;
                    if (count == 5)
                        return count; // 已经找到五个连续棋子
                } else {
                    break; // 遇到不同颜色的棋子,停止检查
                }
            }

            // 检查左侧连续棋子
            for (int i = 1; i < chessPad.length; i++) {
                int prevCol = c - i;
                if (prevCol < 0)
                    break; // 超出棋盘范围
                if (chessPad[r][prevCol] == player) {
                    count++;
                    if (count == 5)
                        return count; // 已经找到五个连续棋子
                } else {
                    break; // 遇到不同颜色的棋子,停止检查
                }
            }

            return count; // 返回连续棋子的数量,可能小于5

    }

    private static int col(int[][] chessPad, int r, int c) {

            int count = 1; // 包括刚放下的棋子
            int player = chessPad[r][c];

            // 检查下方连续棋子
            for (int i = 1; i < chessPad.length; i++) {
                int nextRow = r + i;
                if (nextRow >= chessPad.length)
                    break; // 超出棋盘范围
                if (chessPad[nextRow][c] == player) {
                    count++;
                    if (count == 5)
                        return count; // 已经找到五个连续棋子
                } else {
                    break; // 遇到不同颜色的棋子,停止检查
                }
            }

            // 检查上方连续棋子
            for (int i = 1; i < chessPad.length; i++) {
                int prevRow = r - i;
                if (prevRow < 0)
                    break; // 超出棋盘范围
                if (chessPad[prevRow][c] == player) {
                    count++;
                    if (count == 5)
                        return count; // 已经找到五个连续棋子
                } else {
                    break; // 遇到不同颜色的棋子,停止检查
                }
            }
            return count; // 返回连续棋子的数量,可能小于5
    }

    private static int left(int[][] chessPad, int r, int c) {

            int count = 1; // 包括刚放下的棋子
            int player = chessPad[r][c];

            // 检查左上到右下对角线方向连续棋子
            for (int i = 1; i < chessPad.length; i++) {
                int nextR = r - i;
                int nextC = c + i;
                if (nextR < 0 || nextC >= chessPad.length)
                    break; // 超出棋盘范围
                if (chessPad[nextR][nextC] == player) {
                    count++;
                    if (count == 5)
                        return count; // 已经找到五个连续棋子
                } else {
                    break; // 遇到不同颜色的棋子,停止检查
                }
            }

            for (int i = 1; i < chessPad.length; i++) {
                int prevR = r + i;
                int prevC = c - i;
                if (prevR >= chessPad.length || prevC < 0)
                    break; // 超出棋盘范围
                if (chessPad[prevR][prevC] == player) {
                    count++;
                    if (count == 5)
                        return count; // 已经找到五个连续棋子
                } else {
                    break; // 遇到不同颜色的棋子,停止检查
                }
            }
            return count; // 返回连续棋子的数量,可能小于5
    }

    private static int right(int[][] chessPad, int r, int c) {

            int count = 1; // 包括刚放下的棋子
            int player = chessPad[r][c];

            // 检查右上到左下对角线方向连续棋子
            for (int i = 1; i < chessPad.length; i++) {
                int nextR = r - i;
                int nextC = c - i;
                if (nextR < 0 || nextC < 0)
                    break; // 超出棋盘范围
                if (chessPad[nextR][nextC] == player) {
                    count++;
                    if (count == 5)
                        return count; // 已经找到五个连续棋子
                } else {
                    break; // 遇到不同颜色的棋子,停止检查
                }
            }

            for (int i = 1; i < chessPad.length; i++) {
                int prevR = r + i;
                int prevC = c + i;
                if (prevR >= chessPad.length || prevC >= chessPad.length)
                    break; // 超出棋盘范围
                if (chessPad[prevR][prevC] == player) {
                    count++;
                    if (count == 5)
                        return count; // 已经找到五个连续棋子
                } else {
                    break; // 遇到不同颜色的棋子,停止检查
                }
            }
            return count; // 返回连续棋子的数量,可能小于5
    }

然后为了代码简洁和逻辑分明,用一个判断方法将四种判断全部放入

public static void isWin(int[][] chessPad, int x, int y) {
        int c = (x - X + SIZE / 2) / SIZE;
        int r = (y - Y + SIZE / 2) / SIZE;
        int rn = row(chessPad, r, c);// 横向 行不变列变
        int cn = col(chessPad, r, c);// 纵向 行变列变
        int lun = left(chessPad, r, c);// 左上-右下
        int run = right(chessPad, r, c);// 右上-左下

        if (rn >= 5|| cn >= 5 || lun >= 5 || run >= 5) {
            System.out.println("游戏结束了");

            chessType = 0;//用以说明棋局已经结束

            if (chessPad[r][c] == 1) {
                JOptionPane.showMessageDialog(null, "黑棋赢了");

            } else {
                JOptionPane.showMessageDialog(null, "白棋赢了");
            }
        }

    }

并将获胜条件加入玩法方法(pvpplayer)类中,以确保每次下棋都能调用

public void pvpPlayer(int x, int y, Graphics g) {
        saveData(x, y);
        drawChess(x, y, g);
        drawIndexStr(x, y, chessIndex, g);
        isWin(chessPad,x,y);
    }

以上,第二部分已经完全实现,接下来就是对五子棋一些功能按键的创建和实现

第三部分的实现思路

·功能按键的创建与实现

对于五子棋,常见的功能按键有悔棋,重开。我们就来实现这两种按钮和功能

1,悔棋

在此之前我们已经创建过表示棋子顺序的二维数组ChessIndexArr,于是可以通过这个二维数组来实现这个功能。

,首先要再窗体上创建悔棋的按钮

JButton rebBtn = new JButton("悔棋");//创建一个按钮
        //按钮属性
        rebBtn.setBounds(850, 50, 100, 35);
        rebBtn.setBackground(Color.WHITE);
        rebBtn.setFont(new Font("宋体", Font.BOLD, 20));//设置字体
        rebBtn.addActionListener(gl);//添加
        gf.add(rebBtn);

,因为是点击操作,并不涉及图形的绘制,需要在事件监听器中监听此事件

public void actionPerformed(ActionEvent e) {
        String ac = e.getActionCommand();//获取所点击按钮的内容
        //比对内容
        if (ac.equals("悔棋")) {
            reBackChess(g);//触发悔棋的逻辑体,并传给其画笔
        } 
    }

,在GoUtils中编写悔棋的逻辑

//判断悔棋是否可行
    public static void reBackChess(Graphics g) {
        if (chessIndex <= 0) {
            JOptionPane.showMessageDialog(null, "没有可悔棋的棋子");
            return;
        }
        if (chessType == 0){
            JOptionPane.showMessageDialog(null, "本局已结束,无法悔棋");
            return;
        }

        // 悔棋的逻辑
        /* 根据最后一颗棋子的行列值
           取出棋盘数组中的颜色编号
           删除棋盘数组中的数据 
           索引-1 刷新页面
        */
        int r = chessIndexArr[chessIndex - 1][0];
        int c = chessIndexArr[chessIndex - 1][1];

        chessType = chessPad[r][c];
        chessPad[r][c] = EMPTY;// 清除棋盘数组中的数据
        chessIndex--;
        drawChessPad(g);
        drawAllChess(g);

    }

2,重开

,首先要再窗体上创建重开的按钮

JButton reStart = new JButton("重开");//创建一个按钮
        //按钮属性
        reStart.setBounds(850, 100, 100, 35);
        reStart.setBackground(Color.WHITE);
        reStart.setFont(new Font("宋体", Font.BOLD, 20));//设置字体
        reStart.addActionListener(gl);//添加
        gf.add(reStart);

,因为是点击操作,并不涉及图形的绘制,需要在事件监听器中监听此事件

public void actionPerformed(ActionEvent e) {
        String ac = e.getActionCommand();

        if (ac.equals("悔棋")) {
            reBackChess(g);
        } else if (ac.equals("重开")) {
            reBoard(g);
        }
    }

,在GoUtils中编写重开的逻辑

public void reBoard(Graphics g){
        //清除二维数组“棋盘”中的数据
        for (int i = 0; i <= ROW ; i++){
            for (int j = 0; j <= COL; j++){
                chessPad[i][j] = 0;
            }
        }
        chessIndex = 0;//清除下棋顺序
        drawChessPad(g);
        chessType = 1;
    }

 以上就是五子棋的三部分实现,已经成功做出来了一个完整的五子棋程序

但是,想要其运行起来还差一点

我们在页面UI类中还差一些代码用以显示自己的UI

        gf.setVisible(true);//显示

同时在运行代码中创建实例用以运行自己的程序

public static void main(String[] args) {

        GoBangUI gui = new GoBangUI();
        gui.showUI();

    }

以上即五子棋的创建与运行的全部步骤

全程序代码

以下是本程序全部代码

UI类

package yjh1206;

import java.awt.*;
import javax.swing.*;

public class GoBangUI {

    GoListener gl = new GoListener();

    public void showUI() {

        GoFrame gf = new GoFrame();//创建窗体
        //设置各种设置
        gf.setTitle("五子棋");
        gf.setSize(1000, 900);
        gf.setLocation(500, 300);
        gf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        gf.setLayout(null);// 无布局

        JButton rebBtn = new JButton("悔棋");//创建一个按钮
        //按钮属性
        rebBtn.setBounds(850, 50, 100, 35);
        rebBtn.setBackground(Color.WHITE);
        rebBtn.setFont(new Font("宋体", Font.BOLD, 20));//设置字体
        rebBtn.addActionListener(gl);//添加
        gf.add(rebBtn);

        JButton reStart = new JButton("重开");//创建一个按钮
        //按钮属性
        reStart.setBounds(850, 100, 100, 35);
        reStart.setBackground(Color.WHITE);
        reStart.setFont(new Font("宋体", Font.BOLD, 20));//设置字体
        reStart.addActionListener(gl);//添加
        gf.add(reStart);

        gf.setVisible(true);//显示
        gf.addMouseListener(gl);// 鼠标监听器
        gl.g = gf.getGraphics();// 画笔

    }
    public static void main(String[] args) {

        GoBangUI gui = new GoBangUI();
        gui.showUI();

    }
}

监听器类

package yjh1206;

import java.awt.*;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

public class GoListener extends GoUtils implements ActionListener, MouseListener {
    Graphics g;
    int a,b;
    public void actionPerformed(ActionEvent e) {
        String ac = e.getActionCommand();

        if (ac.equals("悔棋")) {
            reBackChess(g);
        } else if (ac.equals("重开")) {
            reBoard(g);
        }
    }

    @Override
    public void mousePressed(MouseEvent e) {

        int x = e.getX();
        int y = e.getY();

        a = x;
        b = y;

        if (check(x, y)) {// 检查落子条件
            pvpPlayer(x, y, g);// 落子 保存数据 绘制棋子
        }

    }

    @Override
    public void mouseClicked(MouseEvent e) {
    }

    @Override
    public void mouseReleased(MouseEvent e) {
    }

    @Override
    public void mouseEntered(MouseEvent e) {
    }

    @Override
    public void mouseExited(MouseEvent e) {
    }
}

GoUtils类

package yjh1206;

import java.awt.*;
import javax.swing.*;

public class GoUtils {
    // 静态常量 static(静态-唯一-使用类名调用) final(最终的 - 不可变)
    // 棋盘的左上角坐标
    public static final int X = 50;
    public static final int Y = 75;
    // 棋盘的格子列数行数
    public static final int COL = 15;
    public static final int ROW = 15;
    // 每个格子的大小 棋子的尺寸
    public static final int SIZE = 50;
    // 棋子状态
    public static final int EMPTY = 0; // 空
    public static final int BLACK_CHESS = 1;
    public static final int WHITE_CHESS = 2;
    //创建二维数组,用以模拟棋盘
    public static int[][] chessPad = new int[ROW + 1][COL + 1];
    public static int[][] chessIndexArr = new int[256][2];

    public static int chessIndex = 0;
    public static int chessType = BLACK_CHESS;

    public static void drawChessPad(Graphics g) {

        g.setColor(new Color(81, 142, 80));
        g.fillRect(X - SIZE / 2, Y - SIZE / 2, (COL + 1) * SIZE, (ROW + 1) * SIZE);
        g.setColor(Color.BLACK);

        for (int i = 0; i <= COL; i++) {
            g.drawLine(X, Y + i * SIZE, X + COL * SIZE, Y + i * SIZE);// 横线
            g.drawLine(X + i * SIZE, Y, X + i * SIZE, Y + ROW * SIZE);// 纵线

        }
    }

    public static void drawAllChess(Graphics g) {
        for (int i = 0; i < chessIndex; i++) {

            int r = chessIndexArr[i][0];
            int c = chessIndexArr[i][1];
            // 查找颜色
            int color = chessPad[r][c];
            if (color == BLACK_CHESS) {
                g.setColor(Color.BLACK);
            } else if (color == WHITE_CHESS) {
                g.setColor(Color.WHITE);
            }

            int chessX = c * SIZE + X - SIZE / 2;
            int chessY = r * SIZE + Y - SIZE / 2;
            g.fillOval(chessX, chessY, SIZE, SIZE);
            drawIndexStr(chessX, chessY, i+1, g);

        }
    }
    //判断悔棋是否可行
    public static void reBackChess(Graphics g) {
        if (chessIndex <= 0) {
            JOptionPane.showMessageDialog(null, "没有可悔棋的棋子");
            return;
        }
        if (chessType == 0){
            JOptionPane.showMessageDialog(null, "本局已结束,无法悔棋");
            return;
        }

        // 悔棋的逻辑
        // 根据最后一颗棋子的行列值 取出棋盘数组中的颜色编号 删除棋盘数组中的数据 索引-1 刷新页面
        int r = chessIndexArr[chessIndex - 1][0];
        int c = chessIndexArr[chessIndex - 1][1];

        chessType = chessPad[r][c];
        chessPad[r][c] = EMPTY;// 清除棋盘数组中的数据
        chessIndex--;
        drawChessPad(g);
        drawAllChess(g);

    }

    public boolean check(int x, int y) {
        int c = (x - X + SIZE / 2) / SIZE;
        int r = (y - Y + SIZE / 2) / SIZE;
        if (chessType == 0){
            JOptionPane.showMessageDialog(null, "棋局已结束,请重开");
            return false;
        }
        if (c > ROW || r > COL || x < X - SIZE / 2 || y < Y - SIZE / 2) {
            JOptionPane.showMessageDialog(null, "请在棋盘内落子");
            return false;
        }
        if (chessPad[r][c] != 0) {
            JOptionPane.showMessageDialog(null, "该位置已有棋子");
            return false;
        }

        return true;
    }

    public void pvpPlayer(int x, int y, Graphics g) {
        saveData(x, y);
        drawChess(x, y, g);
        drawIndexStr(x, y, chessIndex, g);
        isWin(chessPad,x,y);
    }

    public static void saveData(int x, int y) {
        int c = (x - X + SIZE / 2) / SIZE;
        int r = (y - Y + SIZE / 2) / SIZE;
        chessPad[r][c] = chessType;
        chessIndexArr[chessIndex][0] = r;
        chessIndexArr[chessIndex][1] = c;
        chessIndex++;
    }

    public void drawChess(int x, int y, Graphics g) {
        int c = (x - X + SIZE / 2) / SIZE;
        int r = (y - Y + SIZE / 2) / SIZE;
        // 颜色交替
        if (chessType == BLACK_CHESS) {
            g.setColor(Color.BLACK);
            chessType = WHITE_CHESS;
        } else if (chessType == WHITE_CHESS) {
            g.setColor(Color.WHITE);
            chessType = BLACK_CHESS;
        }
        int chessX = c * SIZE + X - SIZE / 2;
        int chessY = r * SIZE + Y - SIZE / 2;
        g.fillOval(chessX, chessY, SIZE, SIZE);
    }

    public static void drawIndexStr(int x, int y, int chessIndex, Graphics g) {
        int c = (x - X + SIZE / 2) / SIZE;
        int r = (y - Y + SIZE / 2) / SIZE;
        int chessX = c * SIZE + X - SIZE / 2;
        int chessY = r * SIZE + Y - SIZE / 2;
        int px = 5;
        if(chessIndex>=10){
            px=chessIndex>=100?12:8;
        }
        g.setColor(Color.BLUE);
        g.setFont(new Font("宋体", Font.BOLD, 18));
        g.drawString("" + chessIndex, chessX + SIZE / 2 - px, chessY + SIZE / 2+5);

    }

    public static void isWin(int[][] chessPad, int x, int y) {
        int c = (x - X + SIZE / 2) / SIZE;
        int r = (y - Y + SIZE / 2) / SIZE;
        int rn = row(chessPad, r, c);// 横向 行不变列变
        int cn = col(chessPad, r, c);// 纵向 行变列变
        int lun = left(chessPad, r, c);// 左上-右下
        int run = right(chessPad, r, c);// 右上-左下

        if (rn >= 5|| cn >= 5 || lun >= 5 || run >= 5) {
            System.out.println("游戏结束了");
            chessType = 0;
            if (chessPad[r][c] == 1) {
                JOptionPane.showMessageDialog(null, "黑棋赢了");

            } else {
                JOptionPane.showMessageDialog(null, "白棋赢了");
            }
        }

    }


    private static int row(int[][] chessPad, int r, int c) {

            int count = 1; // 包括刚放下的棋子
            int player = chessPad[r][c];

            // 检查右侧连续棋子
            for (int i = 1; i < chessPad.length; i++) {
                int nextCol = c + i;
                if (nextCol >= chessPad.length)
                    break; // 超出棋盘范围
                if (chessPad[r][nextCol] == player) {
                    count++;
                    if (count == 5)
                        return count; // 已经找到五个连续棋子
                } else {
                    break; // 遇到不同颜色的棋子,停止检查
                }
            }

            // 检查左侧连续棋子
            for (int i = 1; i < chessPad.length; i++) {
                int prevCol = c - i;
                if (prevCol < 0)
                    break; // 超出棋盘范围
                if (chessPad[r][prevCol] == player) {
                    count++;
                    if (count == 5)
                        return count; // 已经找到五个连续棋子
                } else {
                    break; // 遇到不同颜色的棋子,停止检查
                }
            }

            return count; // 返回连续棋子的数量,可能小于5

    }

    private static int col(int[][] chessPad, int r, int c) {

            int count = 1; // 包括刚放下的棋子
            int player = chessPad[r][c];

            // 检查下方连续棋子
            for (int i = 1; i < chessPad.length; i++) {
                int nextRow = r + i;
                if (nextRow >= chessPad.length)
                    break; // 超出棋盘范围
                if (chessPad[nextRow][c] == player) {
                    count++;
                    if (count == 5)
                        return count; // 已经找到五个连续棋子
                } else {
                    break; // 遇到不同颜色的棋子,停止检查
                }
            }

            // 检查上方连续棋子
            for (int i = 1; i < chessPad.length; i++) {
                int prevRow = r - i;
                if (prevRow < 0)
                    break; // 超出棋盘范围
                if (chessPad[prevRow][c] == player) {
                    count++;
                    if (count == 5)
                        return count; // 已经找到五个连续棋子
                } else {
                    break; // 遇到不同颜色的棋子,停止检查
                }
            }
            return count; // 返回连续棋子的数量,可能小于5
    }

    private static int left(int[][] chessPad, int r, int c) {

            int count = 1; // 包括刚放下的棋子
            int player = chessPad[r][c];

            // 检查左上到右下对角线方向连续棋子
            for (int i = 1; i < chessPad.length; i++) {
                int nextR = r - i;
                int nextC = c + i;
                if (nextR < 0 || nextC >= chessPad.length)
                    break; // 超出棋盘范围
                if (chessPad[nextR][nextC] == player) {
                    count++;
                    if (count == 5)
                        return count; // 已经找到五个连续棋子
                } else {
                    break; // 遇到不同颜色的棋子,停止检查
                }
            }

            for (int i = 1; i < chessPad.length; i++) {
                int prevR = r + i;
                int prevC = c - i;
                if (prevR >= chessPad.length || prevC < 0)
                    break; // 超出棋盘范围
                if (chessPad[prevR][prevC] == player) {
                    count++;
                    if (count == 5)
                        return count; // 已经找到五个连续棋子
                } else {
                    break; // 遇到不同颜色的棋子,停止检查
                }
            }
            return count; // 返回连续棋子的数量,可能小于5
    }

    private static int right(int[][] chessPad, int r, int c) {

            int count = 1; // 包括刚放下的棋子
            int player = chessPad[r][c];

            // 检查右上到左下对角线方向连续棋子
            for (int i = 1; i < chessPad.length; i++) {
                int nextR = r - i;
                int nextC = c - i;
                if (nextR < 0 || nextC < 0)
                    break; // 超出棋盘范围
                if (chessPad[nextR][nextC] == player) {
                    count++;
                    if (count == 5)
                        return count; // 已经找到五个连续棋子
                } else {
                    break; // 遇到不同颜色的棋子,停止检查
                }
            }

            for (int i = 1; i < chessPad.length; i++) {
                int prevR = r + i;
                int prevC = c + i;
                if (prevR >= chessPad.length || prevC >= chessPad.length)
                    break; // 超出棋盘范围
                if (chessPad[prevR][prevC] == player) {
                    count++;
                    if (count == 5)
                        return count; // 已经找到五个连续棋子
                } else {
                    break; // 遇到不同颜色的棋子,停止检查
                }
            }
            return count; // 返回连续棋子的数量,可能小于5
    }

    public void reBoard(Graphics g){

        for (int i = 0; i <= ROW ; i++){
            for (int j = 0; j <= COL; j++){
                chessPad[i][j] = 0;
            }
        }
        chessIndex = 0;
        drawChessPad(g);
        chessType = 1;
    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值