06 黑白棋
2015-08-28 16:12
369 查看
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, 所以请大家指出!
相关文章推荐
- 基于allegro5的黑白棋子翻转游戏
- windows SDK的C语言黑白棋开发 推荐
- 黑白棋
- 黑白棋(aphabeta剪枝算法的应用)带界面
- 分享 秦时明月人机大战黑白棋
- 黑白棋
- QT黑白棋AI项目详解:一种另类的绘制方式
- Android游戏开发之黑白棋
- Miller_Rabin素数测试算法模板对比
- android屏幕适配 - 切图
- bash: ifconfig: command not found 解决办法
- SeaJS与RequireJS最大的区别
- Android-如何获得当前正在运行的activity和进程的相关信息
- hibernate配置文件hibernate.cfg.xml的详细解释
- Java中keySet()返回值的排序问题
- Cross Site Tracing (XST) Attacks(跨站跟踪攻击)练习详细步骤(WebGoat5.4)
- Hibernate 事务管理
- USACO 1.1 Greedy Gift Givers
- C#IISRESET服务
- django 1.8 官方文档翻译: 3-4-1 基于类的视图