06 黑白棋

1. 前言

这个是在贴吧 看见一个网友写了一个关于五子棋的界面, 然后我也模拟写了一个, 但是后来无趣的时候, 将他改成了黑白棋的规则, 但是没有加入判断胜负的逻辑, 只是一个存在基本规则的界面而已
这个实际上写了已经很久了,所以可能注释, 代码风格等信息可能不是那么的好看
备注 : 没有AI

设计思路 : 难点主要在于对于八个方向上的可吃的棋子的处理

元素介绍
棋盘 : 我们看到的是一个形象的视图, BlackAndWhite中存在一个逻辑上的棋盘
棋子 : 用户下子双方控制的棋子

游戏画面 :
这里写图片描述

2. 基本的数据结构介绍

2.1 BlackAndWhite : 整个业务逻辑的核心Model, 控制着吃掉可吃掉的棋子[updatePieces ]

/**
 * file name : BlankAndWhite.java
 * created at : 9:16:59 PM May 27, 2015
 * created by 970655147
 */

package com.hx.blankAndWhite;


public class BlankAndWhite {

    private int[][] pieces;     // 每个"下子"的逻辑数据

    // 初始化
    public BlankAndWhite() {
        pieces = new int[Tools.ROWLINESNUM][Tools.COLLINENUM];
    }

    // 判断(row, col)是否可落子
    public boolean isBlank(int row, int col) {
        return pieces[row][col] == Tools.BLANK;
    }

    // 设置某一个坐标的棋子
    public void setGrid(int row, int col, int val) {
        pieces[row][col] = val;

        updatePieces(row, col, val);
    }

    // 更新可更新的棋子
        // 依次更新 下方, 上方, 右方, 左方的棋子
        // 依次更新 右上方, 左上方, 右下方, 左下的棋子
    private void updatePieces(int row, int col, int val) {
        if(val != Tools.BLANK) {
            // -----------split-------------
            // TT -> TF -> FT -> FF
            boolean isRow = true, isInc = true;
            int tmp = moveToAnotherSamePiece(row, col, isRow, isInc, val);
            if(pieces[tmp][col] == val) {
                setPieces(row, col, tmp, col, val);
            }

            isInc = !isInc;
            tmp = moveToAnotherSamePiece(row, col, isRow, isInc, val);
            if(pieces[tmp][col] == val) {
                setPieces(row, col, tmp, col, val);
            }

            isRow = !isRow;
            isInc = !isInc;
            tmp = moveToAnotherSamePiece(row, col, isRow, isInc, val);
            if(pieces[row][tmp] == val) {
                setPieces(row, col, row, tmp, val);
            }

            isInc = !isInc;
            tmp = moveToAnotherSamePiece(row, col, isRow, isInc, val);
            if(pieces[row][tmp] == val) {
                setPieces(row, col, row, tmp, val);
            }

            // -----------split-------------
            // TT -> TF -> FT -> FF
            boolean isUp = true, isRight = true;
            int rowTmp = -1, colTmp = -1;
            tmp = moveToAnotherSamePieceSidely(row, col, isUp, isRight, val);
            rowTmp = getRow(row, isUp, tmp);
            colTmp = getCol(col, isRight, tmp);
            if(pieces[rowTmp][colTmp] == val) {
                setPiecesSidely(row, col, isUp, isRight, tmp, val);
            }

            isRight = !isRight;
            tmp = moveToAnotherSamePieceSidely(row, col, isUp, isRight, val);
            rowTmp = getRow(row, isUp, tmp);
            colTmp = getCol(col, isRight, tmp);
            if(pieces[rowTmp][colTmp] == val) {
                setPiecesSidely(row, col, isUp, isRight, tmp, val);
            }

            isUp = !isUp;
            isRight = !isRight;
            tmp = moveToAnotherSamePieceSidely(row, col, isUp, isRight, val);
            rowTmp = getRow(row, isUp, tmp);
            colTmp = getCol(col, isRight, tmp);
            if(pieces[rowTmp][colTmp] == val) {
                setPiecesSidely(row, col, isUp, isRight, tmp, val);
            }

            isRight = !isRight;
            tmp = moveToAnotherSamePieceSidely(row, col, isUp, isRight, val);
            rowTmp = getRow(row, isUp, tmp);
            colTmp = getCol(col, isRight, tmp);
            if(pieces[rowTmp][colTmp] == val) {
                setPiecesSidely(row, col, isUp, isRight, tmp, val);
            }

        }
    }

    // 移动到下一个非opposite的位置[水平, 垂直方向均可]
    // isRow 表示是否是垂直方向
    // isInc 表示是否递增
    private int moveToAnotherSamePiece(int row, int col, boolean isRow, boolean isInc, int val) {   
        int tmp = row + 1;
        if(!isRow ) {
            tmp = col + 1;
        }
        if(!isInc) {
            tmp -= 2;
        }

        if(isInc ) {
            if(isRow ) {
                while(tmp < pieces.length && pieces[tmp][col] == getOppositeForPiece(val)) {
                    tmp ++;
                }
            } else {
                while(tmp < pieces[0].length && pieces[row][tmp] == getOppositeForPiece(val)) {
                    tmp ++;
                }
            }
        } else {
            if(isRow ) {
                while(tmp >= 0 && pieces[tmp][col] == getOppositeForPiece(val)) {
                    tmp --;
                }
            } else {
                while(tmp >= 0 && pieces[row][tmp] == getOppositeForPiece(val)) {
                    tmp --;
                }
            }
        }

        return tmp;
    }

    // 返回斜着走的步数
    // isUp    表示是否是垂直方向
    // isRight 表示是否是水平方向
    private int moveToAnotherSamePieceSidely(int row, int col, boolean isUp, boolean isRight, int val) {    
        int tmp01 = row + 1;
        int tmp02 = col - 1;
        if(isUp ) {
            tmp01 -= 2;
        }
        if(isRight ) {
            tmp02 += 2;
        }

        if(isUp ) {
            if(isRight ) {
                while(tmp01 >= 0 && tmp02 < pieces[0].length && pieces[tmp01][tmp02] == getOppositeForPiece(val)) {
                    tmp01 --;
                    tmp02 ++;
                }
            } else {
                while(tmp01 >= 0 && tmp02 >= 0 && pieces[tmp01][tmp02] == getOppositeForPiece(val)) {
                    tmp01 --;
                    tmp02 --;
                }
            }
        } else {
            if(isRight ) {
                while(tmp01 < pieces.length && tmp02 < pieces[0].length && pieces[tmp01][tmp02] == getOppositeForPiece(val)) {
                    tmp01 ++;
                    tmp02 ++;
                }
            } else {
                while(tmp01 < pieces.length && tmp02 >= 0 && pieces[tmp01][tmp02] == getOppositeForPiece(val)) {
                    tmp01 ++;
                    tmp02 --;
                }
            }
        }

        return Math.abs(tmp01 - row);
    }

    // 设置(startRow, startCol) 到(endRow, endCol)区域的棋子为val
    private void setPieces(int startRow, int startCol, int endRow, int endCol, int val) {
        if(startRow > endRow) {
            int tmp = startRow;
            startRow = endRow;
            endRow = tmp;
        }
        if(startCol > endCol) {
            int tmp = startCol;
            startCol = endCol;
            endCol = tmp;
        }

        for(int i=startRow; i<=endRow; i++ ) {
            for(int j=startCol; j<=endCol; j++) {
                pieces[i][j] = val;
            }
        }
    }

    // 从(startRow, startCol) 开始斜着设置cnt个坐标
    // isUp 表示是否向上移动
    // isRight 表示是否向右移动
    private void setPiecesSidely(int startRow, int startCol, boolean isUp, boolean isRight, int cnt, int val) {
        for(int i=0; i<cnt; i++) {
            pieces[startRow][startCol] = val;
            startRow = getNextRow(startRow, isUp);
            startCol = getNextCol(startCol, isRight);
        }
    }

    // 根据isUp 获取row的下一个行坐标
    private int getNextRow(int row, boolean isUp) {
        return getRow(row, isUp, 1);
    }
    //  根据isUp, offset 获取row的下一个行坐标
    private int getRow(int row, boolean isUp, int offset) {
        if(isUp) {
            return row - offset;
        } else {
            return row + offset;
        }
    }

    // 根据isRight 获取col的下一个列坐标
    private int getNextCol(int col, boolean isRight) {
        return getCol(col, isRight, 1);
    }
    //  根据isRight, offset 获取col的列标
    private int getCol(int col, boolean isRight, int offset) {
        if(isRight) {
            return col + offset;
        } else {
            return col - offset;
        }
    }

    // 获取val对立的棋子  如果是白棋 返回黑棋, 如果是黑棋 返回白棋
    private static int getOppositeForPiece(int val) {
        return Tools.WHITE_BLANK_SUM - val;
    }

    // 获取pieces
    public int[][] getPieces() {
        return pieces;
    }

    // 判断(row, col)是否是白棋
    public boolean isWhite(int row, int col) {
        return pieces[row][col] == Tools.WHITEPIECE;
    }
}

2.2 Tools : 存在一些常量 以及一些公共方法, 主要的方法是给定一个点, 找出其距离最近的棋盘上的点[比如 : 用户可能点击的并不在准确的棋子应该落子的位置, 这时候, 应该找出该点周围四个落子点中最近的落子点落子]

package com.hx.blankAndWhite;

public class Tools {
    // frame的宽高
    public static final int FRAMEWIDTH = 810;
    public static final int FRAMEHEIGHT = 600;

    // 一个格子的宽高
    public static final int GRIDWIDTH = 30;
    public static final int GRIDHEIGHT = 30;

    // 多少条行落子点/列落子点
    public static final int ROWLINESNUM = Tools.FRAMEHEIGHT / Tools.GRIDHEIGHT;
    public static final int COLLINENUM = Tools.FRAMEWIDTH / Tools.GRIDWIDTH;

    // 棋子的半径/一半半径
    public static final int PIECERADIS = 20;
    public static final int HALFPIECERADIS = PIECERADIS / 2;

    // frame的背景颜色 棋盘上线的颜色 白子的颜色 黑子的颜色
    public static final Color BGCOLOR = new Color(240, 225, 181);
    public static final Color LINECOLOR = new Color(52, 158, 213);
    public static final Color WHITECOLOR = new Color(255, 255, 255);
    public static final Color BLACKCOLOR = new Color(0, 0, 0);

    // 空白/黑子/白子 落子点的数据
    public static final int BLANK = 0;
    public static final int WHITEPIECE = 1;
    public static final int BLACKPIECE = 2;
    public static final int WHITE_BLANK_SUM = WHITEPIECE + BLACKPIECE;

    // 获取到离点p 最近的在交叉点上的点
    public static Point getLeastPoint(Point p) {
        // 找到离p的两对x y边缘坐标
        int pXLeft = p.x - p.x % Tools.GRIDWIDTH;
        int pYUp = p.y - p.y % Tools.GRIDHEIGHT;
        int pXRight = pXLeft + Tools.GRIDWIDTH;
        int pYDown = pYUp + Tools.GRIDHEIGHT;

        // 找到离p 最近的落子点
        double min = 0;
        Point res = p, p02 = null;
        p02 = new Point(pXLeft, pYUp);
//      p.printInfo();  p02.printInfo();    Tools.printHorizon();
        double leftUp = getSquareDistance(p, p02);
        if(min < leftUp) {
            min = leftUp;   res = p02;
        }
        p02 = new Point(pXLeft, pYDown);
        double leftDown = getSquareDistance(p, p02);
        if(leftDown < min) {
            min = leftDown; res = p02;
        }
        p02 = new Point(pXRight, pYUp);
        double rightUp = getSquareDistance(p, p02);
        if(rightUp < min) {
            min = rightUp;  res = p02;
        }
        p02 = new Point(pXRight, pYDown);
        double rightDown = getSquareDistance(p, p02);
        if(rightDown < min) {
            min = rightDown;    res = p02;
        }

        return res;
    }

    // 调试
    public static void printHorizon() {
        System.out.println("----------------");
    }

    // 两个点的距离平方和
    public static double getSquareDistance(Point p1, Point p2) {
        return Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2);
    }

    // for debug ...
    public static void awaitInput() {
        try {
            System.in.read();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

3 下载链接 [包含图片, 源码] :

http://download.csdn.net/detail/u011039332/9058493
这里写图片描述

运行时截图 :

这里写图片描述

注 : 因为作者的水平有限,必然可能出现一些bug, 所以请大家指出!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值