“Network”游戏棋人机对弈的设计与实现(二)—判断步骤是否合法

人机对弈之前,计算机首先需要具备能够判断双方所走的步骤是否合法的功能,这里使用棋盘类GameBoard来实现相关的功能。

首先将对弈的棋盘看成是一个8*8的二维数组,每一个单元格对应一个数组下标,并且单元格中存储该单元格中棋子的颜色。棋盘模型如图所示:


棋盘类的总体代码:

package gameboard;

public class GameBoard {
	 public final static int BLACK = -1;
	 public final static int WHITE = 1;
	 public final static int EMPTY = 0;
	 private int[][] gameBoard = new int[8][8];
	 private int blackNum,whiteNum;
	 public GameBoard(){
		 blackNum = 0;
		 whiteNum = 0;
		 for(int i = 0; i < gameBoard.length; i++){
			 for(int j = 0; j < gameBoard[0].length; j++){
				 gameBoard[i][j] = EMPTY;
			 }
		 }
	 }
	 //将棋盘指定格子设置成指定颜色
	 public void setBoard(int x, int y, int color){
		 gameBoard[x][y] = color;
		 if(color == BLACK && blackNum < 10){
			 blackNum++;
		 }else if(color == WHITE && whiteNum < 10){
			 whiteNum++;
		 }
	 }
	 public int getGameBoard(int hIndex, int vIndex){
		 return gameBoard[hIndex][vIndex];
	 }
	 //判断步骤是否合法
	 public boolean isLeagleMove(int hIndex, int vIndex, int color){
		 boolean isLeagle = true;
		 //与该棋子(x,y)相邻棋子的个数
		 int adjacentNumber = 0;
		 int adjacentHIndex = -1;
		 int adjacentVIndex = -1;
		 //查看位置是否被占用以及黑白的goal area
		 if(gameBoard[hIndex][vIndex] != 0 || 
				 (color == WHITE && (vIndex == 0 || vIndex == 7)) || 
				 (color == BLACK && (hIndex == 0 || hIndex ==7)) ||
				 (hIndex == 0 && vIndex == 0) ||
				 (hIndex == 7 && vIndex == 0) ||
				 (hIndex == 0 && vIndex == 7) ||
				 (hIndex == 7 && vIndex == 7)){
			 isLeagle = false;
		 //判断将要放的位置是否有相邻的棋子,如果有相邻两个以上的棋子则位置不合法,若只有一个相邻的棋子,则继续判断,若没有相邻棋子,则位置合法
		 }else{
			 gameBoard[hIndex][vIndex] = color;
			 //internal area
			 if(hIndex != 0 && vIndex != 0 && hIndex != 7 && vIndex != 7){
				 for(int x = hIndex - 1; x <= hIndex + 1; x++){
					 if(gameBoard[x][vIndex - 1] == gameBoard[hIndex][vIndex]){
						 adjacentNumber++;
						 if(adjacentNumber >= 2){
							 //在返回前 ,将棋盘还原
							 gameBoard[hIndex][vIndex] = EMPTY;
							 return false;
						 }
						 adjacentHIndex = x;
						 adjacentVIndex = vIndex - 1;
					 }
					 if(gameBoard[x][vIndex + 1] == gameBoard[hIndex][vIndex]){
						 adjacentNumber++;
						 if(adjacentNumber >= 2){
							 
							 gameBoard[hIndex][vIndex] = EMPTY;
							 return false;
						 }
						 adjacentHIndex = x;
						 adjacentVIndex = vIndex + 1;
					 }
				 }
				 if(gameBoard[hIndex - 1][vIndex] == gameBoard[hIndex][vIndex]){
					 adjacentNumber++;
					 if(adjacentNumber >= 2){
						 gameBoard[hIndex][vIndex] = EMPTY;
						 return false;
					 }
					 adjacentHIndex = hIndex - 1;
					 adjacentVIndex = vIndex;
				 }
				 if(gameBoard[hIndex + 1][vIndex] == gameBoard[hIndex][vIndex]){
					 adjacentNumber++;
					 if(adjacentNumber >= 2){
						 gameBoard[hIndex][vIndex] = EMPTY;
						 return false;
					 }
					 adjacentHIndex = hIndex + 1;
					 adjacentVIndex = vIndex;
				 }
		 //white left goal area
		 }else if(hIndex == 0){
			 for(int y = vIndex - 1; y <= vIndex + 1; y++){
				 if(gameBoard[1][y] == gameBoard[hIndex][vIndex]){
					 adjacentNumber++;
					 if(adjacentNumber >= 2){
						 gameBoard[hIndex][vIndex] = EMPTY;
						 return false;
					 }
					 adjacentHIndex = 1;
					 adjacentVIndex = y;
				 }
			 }
			 if(gameBoard[0][vIndex - 1] == gameBoard[hIndex][vIndex]){
				 adjacentNumber++;
				 if(adjacentNumber >= 2){
					 gameBoard[hIndex][vIndex] = EMPTY;
					 return false;
				 }
				 adjacentHIndex = 0;
				 adjacentVIndex = vIndex - 1;
			 }
			 if(gameBoard[0][vIndex + 1] == gameBoard[hIndex][vIndex]){
				 adjacentNumber++;
				 if(adjacentNumber >= 2){
					 gameBoard[hIndex][vIndex] = EMPTY;
					 return false;
				 }
				 adjacentHIndex = 0;
				 adjacentVIndex = vIndex + 1;
			 }
		 //white right goal area
		 }else if(hIndex == 7){
			 for(int y = vIndex - 1; y <= vIndex + 1; y++){
				 if(gameBoard[6][y] == gameBoard[hIndex][vIndex]){
					 adjacentNumber++;
					 if(adjacentNumber >= 2){
						 gameBoard[hIndex][vIndex] = EMPTY;
						 return false;
					 }
					 adjacentHIndex = 6;
					 adjacentVIndex = y;
				 }
			 }
			 if(gameBoard[7][vIndex - 1] == gameBoard[hIndex][vIndex]){
				 adjacentNumber++;
				 if(adjacentNumber >= 2){
					 gameBoard[hIndex][vIndex] = EMPTY;
					 return false;
				 }
				 adjacentHIndex = 7;
				 adjacentVIndex = vIndex - 1;
			 }
			 if(gameBoard[7][vIndex + 1] == gameBoard[hIndex][vIndex]){
				 adjacentNumber++;
				 if(adjacentNumber >= 2){
					 gameBoard[hIndex][vIndex] = EMPTY;
					 return false;
				 }
				 adjacentHIndex = 7;
				 adjacentVIndex = vIndex + 1;
			 }
		 //black top goal area
		 }else if(vIndex == 0){
			 for(int x = hIndex - 1; x <= hIndex + 1; x++){
				 if(gameBoard[x][1] == gameBoard[hIndex][vIndex]){
					 adjacentNumber++;
					 if(adjacentNumber >= 2){
						 gameBoard[hIndex][vIndex] = EMPTY;
						 return false;
					 }
					 adjacentHIndex = x;
					 adjacentVIndex = 1;
				 }
			 }
			 if(gameBoard[hIndex - 1][0] == gameBoard[hIndex][vIndex]){
				 adjacentNumber++;
				 if(adjacentNumber >= 2){
					 gameBoard[hIndex][vIndex] = EMPTY;
					 return false;
				 }
				 adjacentHIndex = hIndex - 1;
				 adjacentVIndex = 0;
			 }
			 if(gameBoard[hIndex + 1][0] == gameBoard[hIndex][vIndex]){
				 adjacentNumber++;
				 if(adjacentNumber >= 2){
					 gameBoard[hIndex][vIndex] = EMPTY;
					 return false;
				 }
				 adjacentHIndex = hIndex + 1;
				 adjacentVIndex = 0;
			 }
		 //black bottom goal area
		 }else if(vIndex == 7){
			 for(int x = hIndex - 1; x <= hIndex + 1; x++){
				 if(gameBoard[x][6] == gameBoard[hIndex][vIndex]){
					 adjacentNumber++;
					 if(adjacentNumber >= 2){
						 gameBoard[hIndex][vIndex] = EMPTY;
						 return false;
					 }
					 adjacentHIndex = x;
					 adjacentVIndex = 6;
				 }
			 }
			 if(gameBoard[hIndex - 1][7] == gameBoard[hIndex][vIndex]){
				 adjacentNumber++;
				 if(adjacentNumber >= 2){
					 gameBoard[hIndex][vIndex] = EMPTY;
					 return false;
				 }
				 adjacentHIndex = hIndex - 1;
				 adjacentVIndex = 7;
			 }
			 if(gameBoard[hIndex + 1][7] == gameBoard[hIndex][vIndex]){
				 adjacentNumber++;
				 if(adjacentNumber >= 2){
					 gameBoard[hIndex][vIndex] = EMPTY;
					 return false;
				 }
				 adjacentHIndex = hIndex + 1;
				 adjacentVIndex = 7;
			 }
		 }
		}
		//check the adjacent node to see whether it has two adjacent node
		if(adjacentHIndex != -1){
			adjacentNumber = 0;
			if(adjacentHIndex != 0 && adjacentVIndex != 0 && adjacentHIndex != 7 && adjacentVIndex != 7){
				 for(int x = adjacentHIndex - 1; x <= adjacentHIndex + 1; x++){
					 if(gameBoard[x][adjacentVIndex - 1] == gameBoard[adjacentHIndex][adjacentVIndex]){
						 adjacentNumber++;
						 if(adjacentNumber >= 2){
							 gameBoard[hIndex][vIndex] = EMPTY;
							 return false;
						 }
					 }
					 if(gameBoard[x][adjacentVIndex + 1] == gameBoard[adjacentHIndex][adjacentVIndex]){
						 adjacentNumber++;
						 if(adjacentNumber >= 2){
							 gameBoard[hIndex][vIndex] = EMPTY;
							 return false;
						 }
					 }
				 }
				 if(gameBoard[adjacentHIndex - 1][adjacentVIndex] == gameBoard[adjacentHIndex][adjacentVIndex]){
					 adjacentNumber++;
					 if(adjacentNumber >= 2){
						 gameBoard[hIndex][vIndex] = EMPTY;
						 return false;
					 }
				 }
				 if(gameBoard[adjacentHIndex + 1][adjacentVIndex] == gameBoard[adjacentHIndex][adjacentVIndex]){
					 adjacentNumber++;
					 if(adjacentNumber >= 2){
						 gameBoard[hIndex][vIndex] = EMPTY;
						 return false;
					 }
				 }
		 //white left goal area
		 }else if(adjacentHIndex == 0){
			 for(int y = adjacentVIndex - 1; y <= adjacentVIndex + 1; y++){
				 if(gameBoard[1][y] == gameBoard[adjacentHIndex][adjacentVIndex]){
					 adjacentNumber++;
					 if(adjacentNumber >= 2){
						 gameBoard[hIndex][vIndex] = EMPTY;
						 return false;
					 }
				 }
			 }
			 if(gameBoard[0][adjacentVIndex - 1] == gameBoard[adjacentHIndex][adjacentVIndex]){
				 adjacentNumber++;
				 if(adjacentNumber >= 2){
					 gameBoard[hIndex][vIndex] = EMPTY;
					 return false;
				 }
			 }
			 if(gameBoard[0][adjacentVIndex + 1] == gameBoard[adjacentHIndex][adjacentVIndex]){
				 adjacentNumber++;
				 if(adjacentNumber >= 2){
					 gameBoard[hIndex][vIndex] = EMPTY;
					 return false;
				 }
			 }
		 //white right goal area
		 }else if(adjacentHIndex == 7){
			 for(int y = adjacentVIndex - 1; y <= adjacentVIndex + 1; y++){
				 if(gameBoard[6][y] == gameBoard[adjacentHIndex][adjacentVIndex]){
					 adjacentNumber++;
					 if(adjacentNumber >= 2){
						 gameBoard[hIndex][vIndex] = EMPTY;
						 return false;
					 }
				 }
			 }
			 if(gameBoard[7][adjacentVIndex - 1] == gameBoard[adjacentHIndex][adjacentVIndex]){
				 adjacentNumber++;
				 if(adjacentNumber >= 2){
					 gameBoard[hIndex][vIndex] = EMPTY;
					 return false;
				 }
			 }
			 if(gameBoard[7][adjacentVIndex + 1] == gameBoard[adjacentHIndex][adjacentVIndex]){
				 adjacentNumber++;
				 if(adjacentNumber >= 2){
					 gameBoard[hIndex][vIndex] = EMPTY;
					 return false;
				 }
			 }
		 //black top goal area
		 }else if(adjacentVIndex == 0){
			 for(int x = adjacentHIndex - 1; x <= adjacentHIndex + 1; x++){
				 if(gameBoard[x][1] == gameBoard[adjacentHIndex][adjacentVIndex]){
					 adjacentNumber++;
					 if(adjacentNumber >= 2){
						 gameBoard[hIndex][vIndex] = EMPTY;
						 return false;
					 }
				 }
			 }
			 if(gameBoard[adjacentHIndex - 1][0] == gameBoard[adjacentHIndex][adjacentVIndex]){
				 adjacentNumber++;
				 if(adjacentNumber >= 2){
					 gameBoard[hIndex][vIndex] = EMPTY;
					 return false;
				 }
			 }
			 if(gameBoard[adjacentHIndex + 1][0] == gameBoard[adjacentHIndex][adjacentVIndex]){
				 adjacentNumber++;
				 if(adjacentNumber >= 2){
					 gameBoard[hIndex][vIndex] = EMPTY;
					 return false;
				 }
			 }
		 //black bottom goal area
		 }else if(adjacentVIndex == 7){
			 for(int x = adjacentHIndex - 1; x <= adjacentHIndex + 1; x++){
				 if(gameBoard[x][6] == gameBoard[adjacentHIndex][adjacentVIndex]){
					 adjacentNumber++;
					 if(adjacentNumber >= 2){
						 gameBoard[hIndex][vIndex] = EMPTY;
						 return false;
					 }
				 }
			 }
			 if(gameBoard[adjacentHIndex - 1][7] == gameBoard[adjacentHIndex][adjacentVIndex]){
				 adjacentNumber++;
				 if(adjacentNumber >= 2){
					 gameBoard[hIndex][vIndex] = EMPTY;
					 return false;
				 }
			 }
			 if(gameBoard[adjacentHIndex + 1][7] == gameBoard[adjacentHIndex][adjacentVIndex]){
				 adjacentNumber++;
				 if(adjacentNumber >= 2){
					 gameBoard[hIndex][vIndex] = EMPTY;
					 return false;
				 }
			 }
		 }
		}
//		gameBoard[hIndex][vIndex] = EMPTY;
		return isLeagle;
	 }
	 public int getBlackNum(){
		 return blackNum;
	 }
	 public int getWhiteNum(){
		 return whiteNum;
	 }
	 public void addWhiteNum(){
		 whiteNum++;
	 }
	 public void addBlackNum(){
		 blackNum++;
	 }
	 //将指定坐标点还原
	 public void undo(int hIndex, int vIndex) {
		this.setBoard(hIndex, vIndex, EMPTY);
	}
}
这其中的核心方法是isLeagleMove(int hIndex,int vIndex, int color);其中hIndex与vIndex分别是将要放置的棋子位置的横纵坐标,color为棋子颜色。本人采用的策略是首先判断(hIndex,vIndex)处是否有其他棋子,以及(hIndex,vIndex)是否属于其中一方的老家,如是,则另一方不可以将棋子放在这里。最后还需要判断(hIndex,vIndex)是否是四个顶点,如果是四个顶点,不是合法步骤。这些都是在方法的第一个if语句中实现的。

这个方法的难点是判断将(hIndex,vIndex)放入color颜色棋子后会不会与棋盘上的其他棋子构成cluster(也就是(一)中的(6)规则)。这里分两种情况考虑,即(hIndex,vIndex)是边界点与非边界点两种情况。两种情况下遍历周围棋子的坐标不同,边界点情况下相邻单元格有5个,非边界点情况下相邻单元格有8个。采用adjacentNumber来记录相邻的棋子数,如果在遍历过程中发现adjacentNumber已经大于2,则此时已经构成了cluster,该步骤不合法。若遍历结束后发现adjacentNumber等于1,这说明有一个相邻节点,但此时不能确定是否构成了cluster,因为与(hIndex,vIndex)相邻的那个节点也有可能与其他节点构成cluster,这种情况如图红框所示,因此还需要继续判断与(hIndex,vIndex)相邻的那个单元格的adjacentNumber,如果它的adjacentNumber=2,则该步骤也不合法,若adjacentNumber=1,则合法。具体见代码实现。最后需要注意的是判断完成后需要把单元格还原。因为这里只是判断,并没有真正落下棋子。



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值