主题:[原创]五子棋(Renju)胜负算法及Java实现
这几天编了一个五子棋的简单程序,现在将中间判断胜负的Java程序说一下.
五子棋的规则就不再述了.
1. 先将棋盘(15x15的)分成13个区域(见下图)
2. 编写一个判断胜负的Java类方法(包括一个代表胜负的boolean返回值,两个代表当前一方下子的位子参数posX,posY,及一个表示所下棋子种类(黑棋还是白棋,用"黑"实心圆String表示,用"白"空心圆String表示)的String参数.
3.此方法中实现了一个棋盘类对象,因为这里主要讲判断胜负,所以棋盘类就不详细讲了.只要知道它有
一个表示棋盘上每一格状态(黑棋,白棋还是没棋)的二维数组public String[][] board; 一个表示棋盘大小的常量public static final int BOARD_SIZE = 15;一个初始化棋盘方法public void initBoard(),和一个打印棋盘的方法public void printBoard().
4.判段是否"胜"可以将棋盘扫描一边,也可以以最后所下子为中心向周围不同方向辐射来计算.我们当然采用第二种.这样我门就有四条线要判断,横向,纵向,左上到右下的斜向,右上到左下的斜向.
5.横向和纵向比较简单,前两段实现了此功能.
6."左上到右下的斜向,右上到左下的斜向"比较复杂,要判断所下子是否在13区域以外的其他区域,以相应的减少斜向X和Y坐标的起始位和终止位(这是关键和难点).
7.其他具体的请看以下代码中的注释.
public boolean isWin(int posX, int posY, String chessman){
//计算后的X轴起始点("左上到右下的斜向"时为左上点X坐标,"右上到左下的斜向"时为右上点X坐标)
int startX = 0;
//计算后的Y轴起始点("左上到右下的斜向"时为左上点Y坐标,"右上到左下的斜向"时为左下点Y坐标)
int startY = 0;
//计算后的X轴终止位("左上到右下的斜向"时为右下点X坐标,"右上到左下的斜向"时为左下点X坐标)
int endX = Chessboard.BOARD_SIZE - 1;
//计算后的Y轴终止位("左上到右下的斜向"时为右下点Y坐标,"右上到左下的斜向"时为右上点Y坐标)
int endY = Chessboard.BOARD_SIZE - 1;
//posX - WIN_COUNT + 1 的值
int minX = 0;
//posY - WIN_COUNT + 1 的值
int minY = 0;
//posX + WIN_COUNT - 1 的值
int maxX = Chessboard.BOARD_SIZE - 1;
//posY + WIN_COUNT - 1 的值
int maxY = Chessboard.BOARD_SIZE - 1;
int sameCount = 0;
//calculate min X position and Y position
minX = posX - WIN_COUNT + 1;
startX = minX < 0 ? 0 : minX;
minY =posY - WIN_COUNT + 1;
startY = minY < 0 ? 0 : minY;
//calculate max X position and Y position
maxX = posX + WIN_COUNT - 1;
endX = maxX > Chessboard.BOARD_SIZE - 1 ? Chessboard.BOARD_SIZE - 1 : maxX;
maxY =posY + WIN_COUNT - 1;
endY = maxY > Chessboard.BOARD_SIZE - 1 ? Chessboard.BOARD_SIZE - 1 : maxY;
String[][] board = chessboard.getBoard();
//Col position chess check 计算横向是否胜
for(int i = startY; i < endY; i++){
if(board[posX][i] == chessman && board[posX][i+1] == chessman){
sameCount++;
}else if(sameCount < WIN_COUNT - 1){
sameCount = 0;
}
}
//Vol position chess check 计算纵向是否胜
for(int i = startX; i < endX; i++){
if(board[i][posY] == chessman && board[i+1][posY] == chessman){
sameCount++;
}else if(sameCount < WIN_COUNT - 1){
sameCount = 0;
}
}
//Inclined position chess check
//Left top to right bottom 计算左上到右下的斜向是否胜,这里要判断所下子是否在13区域以外的其他区域,以相应的减少斜向X和Y坐标的起始位和终止位.
//calculate start X position and Y position
//startX
if (minX < 0){
//area 1
if(posX > posY){
startX = posX - posY;
}
//area 2,3,4,9
else{
startX = 0;
}
}
//area 7,8,12
else if(minY < 0){
startX = posX - posY;
}
//area 5,6,10,11,13
else{
startX = minX;
}
//startY
if (minY < 0){
//area 2
if(posX < posY){
startY = posY - posX;
}
//area 1,7,8,12
else{
startY = 0;
}
}
//area 3,4,9
else if(minX < 0){
startY = posY - posX;
}
//area 5,6,10,11,13
else{
startY = minY;
}
//calculate end X position and Y position
//endX
if (maxX > Chessboard.BOARD_SIZE - 1){
//area 5
if(posX < posY){
endX = Chessboard.BOARD_SIZE - 1 - (posY - posX);
}
//area 6,7,8,11
else{
endX = Chessboard.BOARD_SIZE - 1;
}
}
//area 3,4,10
else if(maxY > Chessboard.BOARD_SIZE - 1){
endX = Chessboard.BOARD_SIZE - 1 - (posY - posX);
}
//area 1,2,9,12,13
else{
endX = maxX;
}
//endY
if (maxY > Chessboard.BOARD_SIZE - 1){
//area 6
if(posX > posY){
endY = Chessboard.BOARD_SIZE - 1 - (posX - posY);
}
//area 3,4,5,10
else{
endY = Chessboard.BOARD_SIZE - 1;
}
}
//area 7,8,11
else if(maxX > Chessboard.BOARD_SIZE - 1){
endY = Chessboard.BOARD_SIZE - 1 - (posX - posY);
}
//area 1,2,9,12,13
else{
endY = maxY;
}
int j = startY;
for(int i = startX; i < endX; i++){
if(board[i][j] == chessman && board[i+1][j+1] == chessman){
sameCount++;
}else if(sameCount < WIN_COUNT - 1){
sameCount = 0;
}
if (j < endY){
j++;
}
}
//Right top to left bottom 计算右上到左下的斜向是否胜,这里要判断所下子是否在13区域以外的其他区域,以相应的减少斜向X和Y坐标的起始位和终止位.
//calculate start X position and Y position
//startX
if (minX < 0){
//area 4
if(posX > (Chessboard.BOARD_SIZE - 1 - posY)){
startX = minX + (maxY - (Chessboard.BOARD_SIZE - 1));
}
//area 1,2,3,9
else{
startX = 0;
}
}
//area 5,6,10
else if(maxY > Chessboard.BOARD_SIZE - 1){
startX = minX + (maxY - (Chessboard.BOARD_SIZE - 1));
}
//area 7,8,11,12,13
else{
startX = minX;
}
//startY
if (minY < 0){
//area 7
if((Chessboard.BOARD_SIZE - 1 - posX) < posY){
startY = minY + (maxX - (Chessboard.BOARD_SIZE - 1));
}
//area 1,2,8,12
else{
startY = 0;
}
}
//area 5,6,11
else if(maxX > Chessboard.BOARD_SIZE - 1){
startY = minY + (maxX - (Chessboard.BOARD_SIZE - 1));
}
//area 3,4,9,10,13
else{
startY = minY;
}
//calculate end X position and Y position
//endX
if (maxX > Chessboard.BOARD_SIZE - 1){
//area 8
if((Chessboard.BOARD_SIZE - 1 - posX) > posY){
// endX = Chessboard.BOARD_SIZE - 1 - ((Chessboard.BOARD_SIZE - 1 - posX) - posY);
endX = maxX + minY;
}
//area 5,6,7,11
else{
endX = Chessboard.BOARD_SIZE - 1;
}
}
//area 1,2,12
else if(minY < 0){
endX = maxX + minY;
}
//area 3,4,9,10,13
else{
endX = maxX;
}
//endY
if (maxY > Chessboard.BOARD_SIZE - 1){
//area 3
if(posX < (Chessboard.BOARD_SIZE - 1 - posY)){
endY = minX + maxY;
}
//area 4,5,6,10
else{
endY = Chessboard.BOARD_SIZE - 1;
}
}
//area 1,2,9
else if(minX < 0){
endY = minX + maxY;
}
//area 7,8,11,12,13
else{
endY = maxY;
}
int k = endY;
for(int i = startX; i < endX; i++){
if(board[i][k] == chessman && board[i+1][k-1] == chessman){
sameCount++;
}else if(sameCount < WIN_COUNT - 1){
sameCount = 0;
}
if (k > startY){
k--;
}
}
//判断是否胜,返回boolean值
if (sameCount >= WIN_COUNT - 1){
return true;
}else{
return false;
}
}
五子棋的规则就不再述了.
1. 先将棋盘(15x15的)分成13个区域(见下图)
2. 编写一个判断胜负的Java类方法(包括一个代表胜负的boolean返回值,两个代表当前一方下子的位子参数posX,posY,及一个表示所下棋子种类(黑棋还是白棋,用"黑"实心圆String表示,用"白"空心圆String表示)的String参数.
3.此方法中实现了一个棋盘类对象,因为这里主要讲判断胜负,所以棋盘类就不详细讲了.只要知道它有
一个表示棋盘上每一格状态(黑棋,白棋还是没棋)的二维数组public String[][] board; 一个表示棋盘大小的常量public static final int BOARD_SIZE = 15;一个初始化棋盘方法public void initBoard(),和一个打印棋盘的方法public void printBoard().
4.判段是否"胜"可以将棋盘扫描一边,也可以以最后所下子为中心向周围不同方向辐射来计算.我们当然采用第二种.这样我门就有四条线要判断,横向,纵向,左上到右下的斜向,右上到左下的斜向.
5.横向和纵向比较简单,前两段实现了此功能.
6."左上到右下的斜向,右上到左下的斜向"比较复杂,要判断所下子是否在13区域以外的其他区域,以相应的减少斜向X和Y坐标的起始位和终止位(这是关键和难点).
7.其他具体的请看以下代码中的注释.
public boolean isWin(int posX, int posY, String chessman){
//计算后的X轴起始点("左上到右下的斜向"时为左上点X坐标,"右上到左下的斜向"时为右上点X坐标)
int startX = 0;
//计算后的Y轴起始点("左上到右下的斜向"时为左上点Y坐标,"右上到左下的斜向"时为左下点Y坐标)
int startY = 0;
//计算后的X轴终止位("左上到右下的斜向"时为右下点X坐标,"右上到左下的斜向"时为左下点X坐标)
int endX = Chessboard.BOARD_SIZE - 1;
//计算后的Y轴终止位("左上到右下的斜向"时为右下点Y坐标,"右上到左下的斜向"时为右上点Y坐标)
int endY = Chessboard.BOARD_SIZE - 1;
//posX - WIN_COUNT + 1 的值
int minX = 0;
//posY - WIN_COUNT + 1 的值
int minY = 0;
//posX + WIN_COUNT - 1 的值
int maxX = Chessboard.BOARD_SIZE - 1;
//posY + WIN_COUNT - 1 的值
int maxY = Chessboard.BOARD_SIZE - 1;
int sameCount = 0;
//calculate min X position and Y position
minX = posX - WIN_COUNT + 1;
startX = minX < 0 ? 0 : minX;
minY =posY - WIN_COUNT + 1;
startY = minY < 0 ? 0 : minY;
//calculate max X position and Y position
maxX = posX + WIN_COUNT - 1;
endX = maxX > Chessboard.BOARD_SIZE - 1 ? Chessboard.BOARD_SIZE - 1 : maxX;
maxY =posY + WIN_COUNT - 1;
endY = maxY > Chessboard.BOARD_SIZE - 1 ? Chessboard.BOARD_SIZE - 1 : maxY;
String[][] board = chessboard.getBoard();
//Col position chess check 计算横向是否胜
for(int i = startY; i < endY; i++){
if(board[posX][i] == chessman && board[posX][i+1] == chessman){
sameCount++;
}else if(sameCount < WIN_COUNT - 1){
sameCount = 0;
}
}
//Vol position chess check 计算纵向是否胜
for(int i = startX; i < endX; i++){
if(board[i][posY] == chessman && board[i+1][posY] == chessman){
sameCount++;
}else if(sameCount < WIN_COUNT - 1){
sameCount = 0;
}
}
//Inclined position chess check
//Left top to right bottom 计算左上到右下的斜向是否胜,这里要判断所下子是否在13区域以外的其他区域,以相应的减少斜向X和Y坐标的起始位和终止位.
//calculate start X position and Y position
//startX
if (minX < 0){
//area 1
if(posX > posY){
startX = posX - posY;
}
//area 2,3,4,9
else{
startX = 0;
}
}
//area 7,8,12
else if(minY < 0){
startX = posX - posY;
}
//area 5,6,10,11,13
else{
startX = minX;
}
//startY
if (minY < 0){
//area 2
if(posX < posY){
startY = posY - posX;
}
//area 1,7,8,12
else{
startY = 0;
}
}
//area 3,4,9
else if(minX < 0){
startY = posY - posX;
}
//area 5,6,10,11,13
else{
startY = minY;
}
//calculate end X position and Y position
//endX
if (maxX > Chessboard.BOARD_SIZE - 1){
//area 5
if(posX < posY){
endX = Chessboard.BOARD_SIZE - 1 - (posY - posX);
}
//area 6,7,8,11
else{
endX = Chessboard.BOARD_SIZE - 1;
}
}
//area 3,4,10
else if(maxY > Chessboard.BOARD_SIZE - 1){
endX = Chessboard.BOARD_SIZE - 1 - (posY - posX);
}
//area 1,2,9,12,13
else{
endX = maxX;
}
//endY
if (maxY > Chessboard.BOARD_SIZE - 1){
//area 6
if(posX > posY){
endY = Chessboard.BOARD_SIZE - 1 - (posX - posY);
}
//area 3,4,5,10
else{
endY = Chessboard.BOARD_SIZE - 1;
}
}
//area 7,8,11
else if(maxX > Chessboard.BOARD_SIZE - 1){
endY = Chessboard.BOARD_SIZE - 1 - (posX - posY);
}
//area 1,2,9,12,13
else{
endY = maxY;
}
int j = startY;
for(int i = startX; i < endX; i++){
if(board[i][j] == chessman && board[i+1][j+1] == chessman){
sameCount++;
}else if(sameCount < WIN_COUNT - 1){
sameCount = 0;
}
if (j < endY){
j++;
}
}
//Right top to left bottom 计算右上到左下的斜向是否胜,这里要判断所下子是否在13区域以外的其他区域,以相应的减少斜向X和Y坐标的起始位和终止位.
//calculate start X position and Y position
//startX
if (minX < 0){
//area 4
if(posX > (Chessboard.BOARD_SIZE - 1 - posY)){
startX = minX + (maxY - (Chessboard.BOARD_SIZE - 1));
}
//area 1,2,3,9
else{
startX = 0;
}
}
//area 5,6,10
else if(maxY > Chessboard.BOARD_SIZE - 1){
startX = minX + (maxY - (Chessboard.BOARD_SIZE - 1));
}
//area 7,8,11,12,13
else{
startX = minX;
}
//startY
if (minY < 0){
//area 7
if((Chessboard.BOARD_SIZE - 1 - posX) < posY){
startY = minY + (maxX - (Chessboard.BOARD_SIZE - 1));
}
//area 1,2,8,12
else{
startY = 0;
}
}
//area 5,6,11
else if(maxX > Chessboard.BOARD_SIZE - 1){
startY = minY + (maxX - (Chessboard.BOARD_SIZE - 1));
}
//area 3,4,9,10,13
else{
startY = minY;
}
//calculate end X position and Y position
//endX
if (maxX > Chessboard.BOARD_SIZE - 1){
//area 8
if((Chessboard.BOARD_SIZE - 1 - posX) > posY){
// endX = Chessboard.BOARD_SIZE - 1 - ((Chessboard.BOARD_SIZE - 1 - posX) - posY);
endX = maxX + minY;
}
//area 5,6,7,11
else{
endX = Chessboard.BOARD_SIZE - 1;
}
}
//area 1,2,12
else if(minY < 0){
endX = maxX + minY;
}
//area 3,4,9,10,13
else{
endX = maxX;
}
//endY
if (maxY > Chessboard.BOARD_SIZE - 1){
//area 3
if(posX < (Chessboard.BOARD_SIZE - 1 - posY)){
endY = minX + maxY;
}
//area 4,5,6,10
else{
endY = Chessboard.BOARD_SIZE - 1;
}
}
//area 1,2,9
else if(minX < 0){
endY = minX + maxY;
}
//area 7,8,11,12,13
else{
endY = maxY;
}
int k = endY;
for(int i = startX; i < endX; i++){
if(board[i][k] == chessman && board[i+1][k-1] == chessman){
sameCount++;
}else if(sameCount < WIN_COUNT - 1){
sameCount = 0;
}
if (k > startY){
k--;
}
}
//判断是否胜,返回boolean值
if (sameCount >= WIN_COUNT - 1){
return true;
}else{
return false;
}
}