您的位置:首页 > 其它

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, 所以请大家指出!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  黑白棋