Java 简易五子棋的实现 V1.5 落子与悔棋

V1.0版本搭建了框架,这次将重点实现落子与悔棋功能

-落子

-落子的逻辑

        因为当时我们使用的是面板来放置棋盘,所以棋盘以及落子的坐标都以面板的坐标为基准。之前设计的棋盘为16*16格子,所以棋盘大小为17*17*SIZE,即左右分别多出半个SIZE大小,毕竟棋子是圆的,中心在直线交汇处,最边上的棋子有半颗棋子在外面。

        当我们点击棋盘上的某个位置时,应当根据坐标进行一系列换算,得出该坐标对应棋盘的横纵坐标,再根据横纵坐标画出棋子。

        可以看到下图,对于落子的计算,我们应该将棋盘划分为如图的区域,点击对应区域,便在对应区域的中心点,即坐标点处画一个圆。算法放在代码中,自行理解,重点就是利用整除,再进行微调,X、SIZE等都在GoData里。

        

    int X = 70, Y = 70, SIZE = 40, COL = 15, ROW = 15;

换算为棋盘坐标 

    public static int calC(int x) {
        int c = (x - X + SIZE / 2) / SIZE;
        return c;
    }

    public static int calR(int y) {
        int r = (y - Y + SIZE / 2) / SIZE;
        return r;
    }

 换算为面板坐标

    public static int calTX(int c) {
        int x = c * SIZE + X - SIZE / 2;
        return x;
    }

    public static int calTY(int r) {
        int y = r * SIZE + Y - SIZE / 2;
        return y;
    }

 -棋子的存储

直接创建一个Chess类,存储棋子的颜色,坐标以及落子顺序。

在每次绘制棋子时,都要同步将棋子存储起来

考虑到后续功能,我们创建了一个动态数组 ArrayList<Chess> chesses 来存储顺序,一个二维数组 Int[][] chessList 来存储坐标和实现悔棋

public class Chess {
    int chessFlag;
    int x,y,index;

    public Chess(int x,int y, int chessFlag ,int i){
        this.x = x;
        this.y = y;
        this.chessFlag = chessFlag;
        index = i;
    }
}
    int chessFlag = 1;
    int index = 0;
    ArrayList<Chess> chesses = new ArrayList<>();
    int[][] chessList = new int[ROW + 1][COL + 1];

-棋子的绘制

利用Java swing 自带的填充椭圆的方法,将参数设置成SIZE即可,在绘制前改变颜色,即可绘制不同颜色的棋子

g.setColor(Color.white);
g.fillOval(GoData.calTX(maxC), GoData.calTY(maxR), SIZE, SIZE);

-结合按钮,实现完整功能

public void mousePressed(MouseEvent e) {
        int x = e.getX();
        int y = e.getY();
        System.out.println(x + "," + y);
        if(isWin){
            return;
        }
        if (cl.equals("开始游戏") && !isAI || cl.equals("悔棋") && !isAI) {
            if (GoData.peopleSet1(x, y, chessList, chessFlag, index, chesses, g)) {
                if (chessFlag == 1) { //棋子换色
                    chessFlag = 2;
                } else if (chessFlag == 2) {
                    chessFlag = 1;
                }
            }
}

这部分代码再GoData接口中 

public static boolean peopleSet1(int x, int y, int[][] chessList, int chessFlag, int index, ArrayList<Chess> chesses, Graphics g) {
        if (!GoData.isChessPad(x, y)) { //确保棋子不出棋盘
            return false;
        }
        int c = GoData.calC(x); //c,d为棋子在棋盘上的格子坐标
        int d = GoData.calR(y);

        if (chessList[c][d] != 0) { //判断棋子是否重叠
            return false;
        }

        chessList[c][d] = chessFlag; //棋子坐标和颜色
        Chess chess = new Chess(c, d, chessFlag, index++);
        chesses.add(chess); //棋子顺序

        int chessX = GoData.calTX(c); //格子坐标换算窗口坐标
        int chessY = GoData.calTY(d);

        if (chessFlag == 1) { //棋子换色
            g.setColor(Color.black);
        } else if (chessFlag == 2) {
            g.setColor(Color.white);
        }

        g.fillOval(chessX, chessY, SIZE, SIZE);
        return true;
    }

-悔棋

-悔棋的逻辑

人人对战时,悔棋只回退一步,所以只需找到chesses数组里的最后一颗棋子,获得其坐标,颜色,然后将其删除,再用坐标将二维数组里的对应位置改回空,即0。最后还要按照棋子顺序将所有棋子以及棋盘重绘一次,最后一颗棋子覆盖掉。

case "悔棋" -> {
    if (chesses.isEmpty()) {
        return;
    }
    if (isWin){
        isWin = false;  
    }
    if (chesses.get(chesses.size() - 1).chessFlag == 1) { //确保悔棋后棋子颜色正确
        chessFlag = 1;
    } else if (chesses.get(chesses.size() - 1).chessFlag == 2) {
        chessFlag = 2;
    }
    chessList[chesses.get(chesses.size() - 1).x][chesses.get(chesses.size() - 1).y] = 0;
    chesses.remove(chesses.size() - 1);
    GoData.drawGamePad(g, chessList);
}

以下代码再GoData中

    public static void drawGamePad(Graphics g, int[][] cl) {
        drawChessPad(g);
        drawChesses(g, cl);
    }

    public static void drawChessPad(Graphics g) { //绘制棋盘
        g.setColor(Color.orange);
        g.fillRect(X - 20, Y - 20, SIZE * (COL + 1), SIZE * (ROW + 1));

        g.setColor(Color.black);
        for (int i = 0; i <= 15; i++) {
            g.drawLine(X, Y + (i * SIZE), X + (ROW * SIZE), Y + (i * SIZE));
            g.drawLine(X + (i * SIZE), Y, X + (i * SIZE), Y + (COL * SIZE));
        }
    }

    public static void drawChesses(Graphics g, int[][] cl) {
        for (int i = 0; i <= ROW; i++) {
            for (int j = 0; j <= COL; j++) {
                if (cl[i][j] == 1) {
                    g.setColor(Color.black);
                } else if (cl[i][j] == 2) {
                    g.setColor(Color.white);
                } else {
                    continue;
                }
                int chessX = i * SIZE + X - SIZE / 2;
                int chessY = j * SIZE + Y - SIZE / 2;
                g.fillOval(chessX, chessY, SIZE, SIZE);
            }
        }
    }

-运行结果 

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值