java五子棋禁手规则,复盘等的实现

五子棋程序实现了判赢,禁手,复盘,低级AI(判断还存在许多问题,欢迎指正),继续游戏,夜间模式,悔棋等基本功能

代码可研究不可复制粘贴。

 

禁手的定义:是为了限制黑方的先手优势而设定的一种比赛规则

禁手的分类:三三禁手(黑棋一子落下同时形成两个或两个以上的活三,此子必须为两个活三共同的构成子)、四四禁手(黑棋一子落下同时形成两个或两个以上的冲四或活四)、长连禁手(黑棋一子落下形成一个或一个以上的长连)。

构成禁手的基本子力要素:活三(本方再走一着可以形成活四的三)、活四(有两个点可以成五的四)、冲四(只有一个点可以成五的四)、长连(在棋盘上的阳线和阴线任意一条线上,形成的5个以上同色棋子不间隔的相连)

关于禁手的规定:黑方五连与禁手同时形成,禁手失效,黑方胜

具体规则参见附件

程序说明:

 

0表示空位,1表示黑子,-1表示白子,chesses[15][15]保存的棋盘的当前棋局

 

 

本程序的长连禁手是和判赢一起判断的,判赢算法中会返回当前下子的位置四周有几颗同颜色子相连,如果是黑子并且长度大于5则为长连禁手。

代码举例:

/**
	 * 计算横向是否 5颗相同颜色的子相连
	 * @param r 当前下子的横坐标
	 * @param c 当前下子的纵坐标
	 * @return
	 */
	public static int checkRow(int r, int c) {
		int count = 1;
		// 向右找
		for (int j = c + 1; j < COLS; j++) {
			if (chesses[r][c] == chesses[r][j]) {
				count++;
			} else {
				break;
			}
		}

		// 往左走
		for (int j = c - 1; j >= 0; j--) {
			if (chesses[r][c] == chesses[r][j]) {
				count++;
			} else {
				break;
			}
		}
		return count;

	}

public static boolean longlink(int r, int c) {
		if (chesses[r][c] == 1) {
			return (SuanFa.checkRow(r, c) > 5 || SuanFa.checkxiezuo(r, c) > 5
					|| SuanFa.checkCol(r, c) > 5 || SuanFa.checkxieyou(r, c) > 5);
		} else {
			return false;
		}

 

三三禁手和四四禁手类似,但是四四禁手有一些特殊情况。这里一44禁手为例进行说明

 

首先,判断禁手,并不需要扫描整个棋盘,只需要扫描当前落子的周围关键位置,比如放了棋子在chesses[r][c]的位置,横向只需要扫描chesses[r-4][c-4]到[r+4][c+4]的位置。选择好范围之后,从[r-4][c-4]开始,每次扫描连续的5个位置看是否构成活四或者重四(三三禁手只有活三),由于采用1,-1来计数,可以直接这样判断:

if (chesses[r][j] + chesses[r][j + 1] + chesses[r][j + 2]+ chesses[r][j + 3] +chesses[r][j + 4] == 4)

 如果这5个连续位置相加为4,必然是4个黑子和一个空位。(用1,2标记棋盘黑白子处理相对来说麻烦一点,但原理是一样的,多加几个判断即可。)

依次从各个方向找完之后,我们可以用count来记录找到了几个满足条件的活四或者冲四或者活三。

如果找到两个,已经构成禁手,立即结束查找。

但是,如果你理解了以上过程,你就会发现,现在的情况只能判断特定的一些禁手情况。这里我用图片进行说明:


java五子棋禁手规则,复盘等的实现
 

图片1中这类型禁手已经可以进行判断了,(4,5)为最后一颗黑色落子,他会从(4,5)位置为焦点进行扫描,横向竖向都已经扫到了活三。但是2中的这种情况,以(7,10)进行扫描的话无法扫描出(6,X)横向的活三。

所以在扫描过程中,还需要对(7,10)周围的(6,10)进行扫描,如果以(6,10)为焦点也扫描到了活三,这个时候也是三三禁手。

这里用一个层次来标记一下,方便递归来查找。int cenci=1;如果是SetChesses设置的棋子,那么他的cenci=1;如果是SetChesses设置的棋子为焦点扫描到的活三,活四,冲四,那么该方向其余元素(6,10),(8,10)的层次cenci=0;这样,就不会一直扫描下去。

在这里又出现一个问题,即便用cenci来记录了要找周围元素的活四等等,以(6,10)为例,(6,10)会找到横着的活三,也会找到竖着的活三,这样,竖着的就算重复了,这是非常不合理的,所以得用一个变量标记一下方向,对于层次为0的我们只要找其余三个方向。

 

活四中还有几种特例:比如:


java五子棋禁手规则,复盘等的实现

此处(5,6)构成了四四禁手(三三禁手没有这样的特例),由于这种类型的禁手很少,所以在程序中单独列举出来进行判断。
 

活四判断代码参考如下:

public static int Four(int r, int c, int cenci, char direction) {
		if (chesses[r][c] == 1) {
			int i, j, count4 = 0;
			if (cenci == 1) {
				// 判断横向四
				for (j = 0; j < 11; j++) {
					if (chesses[r][j] + chesses[r][j + 1] + chesses[r][j + 2]
							+ chesses[r][j + 3] + chesses[r][j + 4] == 4) {
						count4++;
						for (int k = 0; k < 5; k++) {
							if (chesses[r][j + k] == 1) {
								count4 += Four(r, j + k, 0, 'a');
								if (count4 > 1) {
									return 2;
								}
							}
						}
						break;
					}
				}

				// 判断纵向四
				for (i = 0; i < 11; i++) {
					if (chesses[i][c] + chesses[i + 1][c] + chesses[i + 2][c]
							+ chesses[i + 3][c] + chesses[i + 4][c] == 4) {
						count4++;
						for (int k = 0; k < 5; k++) {
							if (chesses[i + k][c] == 1) {
								count4 += Four(i + k, c, 0, 'b');
								if (count4 > 1) {
									return 2;
								}
							}
						}
						break;
					}
				}

				// 判断“\”向四
				if (c > r) {
					for (i = 0, j = c - r; i < (11 - c + r); i++, j++) {
						if (chesses[i][j] + chesses[i + 1][j + 1]
								+ chesses[i + 2][j + 2] + chesses[i + 3][j + 3]
								+ chesses[i + 4][j + 4] == 4) {
							count4++;
							for (int k = 0; k < 5; k++) {
								if (chesses[i + k][j + k] == 1) {
									count4 += Four(i + k, j + k, 0, 'c');
									if (count4 > 1) {
										return 2;
									}
								}
							}
							break;
						}
					}
				} else {
					for (i = r - c, j = 0; i < 11; i++, j++) { // 判断“\”向“活三”
						if (chesses[i][j] + chesses[i + 1][j + 1]
								+ chesses[i + 2][j + 2] + chesses[i + 3][j + 3]
								+ chesses[i + 4][j + 4] == 4) {
							count4++;
							for (int k = 0; k < 5; k++) {
								if (chesses[i + k][j + k] == 1) {
									count4 += Four(i + k, j + k, 0, 'c');
									if (count4 > 1) {
										return 2;
									}
								}
							}
							break;
						}
					}
				}

				if (r + c < 15) {

					for (i = r + c, j = 0; i >= 4; i--, j++) { // 判断“/”向“活三”
						if (chesses[i][j] + chesses[i - 1][j + 1]
								+ chesses[i - 2][j + 2] + chesses[i - 3][j + 3]
								+ chesses[i - 4][j + 4] == 4) {
							count4++;
							for (int k = 0; k < 5; k++) {
								if (chesses[i - k][j + k] == 1) {
									count4 += Four(i - k, j + k, 0, 'd');
									if (count4 > 1) {
										return 2;
									}
								}
							}
							break;
						}
					}
				} else {
					for (i = 14, j = r + c - 14; j < 11; i--, j++) { // 判断“/”向“活三”
						if (chesses[i][j] + chesses[i - 1][j + 1]
								+ chesses[i - 2][j + 2] + chesses[i - 3][j + 3]
								+ chesses[i - 4][j + 4] == 4) {
							count4++;
							for (int k = 0; k < 5; k++) {
								if (chesses[i - k][j + k] == 1) {
									count4 += Four(i - k, j + k, 0, 'd');
									if (count4 > 1) {
										return 2;
									}
								}
							}
							break;
						}
					}
				}

				if (count4 > 1) {
					return 2;
				}

			}

			else {

				if (direction != 'a') {
					// 判断横向四
					for (j = 0; j < 11; j++) {
						if (chesses[r][j] + chesses[r][j + 1]
								+ chesses[r][j + 2] + chesses[r][j + 3]
								+ chesses[r][j + 4] == 4) {
							return 1;
						}
					}
				}

				if (direction != 'b') {
					// 判断纵向四
					for (i = 0; i < 11; i++) {
						if (chesses[i][c] + chesses[i + 1][c]
								+ chesses[i + 2][c] + chesses[i + 3][c]
								+ chesses[i + 4][c] == 4) {
							return 1;
						}
					}
				}

				if (direction != 'c') {
					// 判断“\”向四
					if (c > r) {
						for (i = 0, j = c - r; i < (11 - c + r); i++, j++) {
							if (chesses[i][j] + chesses[i + 1][j + 1]
									+ chesses[i + 2][j + 2]
									+ chesses[i + 3][j + 3]
									+ chesses[i + 4][j + 4] == 4) {
								return 1;
							}
						}
					} else {
						for (i = r - c, j = 0; i < 11; i++, j++) { // 判断“\”向“活三”
							if (chesses[i][j] + chesses[i + 1][j + 1]
									+ chesses[i + 2][j + 2]
									+ chesses[i + 3][j + 3]
									+ chesses[i + 4][j + 4] == 4) {
								return 1;
							}
						}
					}
				}

				if (direction != 'd') {
					if (r + c < 15) {

						for (i = r + c, j = 0; i >= 4; i--, j++) { // 判断“/”向“活三”
							if (chesses[i][j] + chesses[i - 1][j + 1]
									+ chesses[i - 2][j + 2]
									+ chesses[i - 3][j + 3]
									+ chesses[i - 4][j + 4] == 4) {
								return 1;
							}
						}
					} else {
						for (i = 14, j = r + c - 14; j < 11; i--, j++) { // 判断“/”向“活三”
							if (chesses[i][j] + chesses[i - 1][j + 1]
									+ chesses[i - 2][j + 2]
									+ chesses[i - 3][j + 3]
									+ chesses[i - 4][j + 4] == 4) {
								return 1;
							}
						}
					}
				}
			}

			// 横向特殊四四
			if (c > 2 && c < 12 && chesses[r][c - 3] == 1
					&& chesses[r][c - 2] == 0 && chesses[r][c - 1] == 1
					&& chesses[r][c + 3] == 1 && chesses[r][c + 2] == 0
					&& chesses[r][c + 1] == 1) {
				return 2;
			} else if (c > 2 && c < 11 && chesses[r][c - 3] == 1
					&& chesses[r][c - 2] == 1 && chesses[r][c - 1] == 0
					&& chesses[r][c + 4] == 1 && chesses[r][c + 3] == 1
					&& chesses[r][c + 2] == 0 && chesses[r][c + 1] == 1) {
				return 2;
			} else if (c > 3 && c < 11 && chesses[r][c - 4] == 1
					&& chesses[r][c - 3] == 1 && chesses[r][c - 2] == 1
					&& chesses[r][c - 1] == 0 && chesses[r][c + 4] == 1
					&& chesses[r][c + 3] == 1 && chesses[r][c + 2] == 1
					&& chesses[r][c + 1] == 0) {
				return 2;
			} else if (c > 3 && c < 11 && chesses[r][c - 4] == 1
					&& chesses[r][c - 3] == 1 && chesses[r][c - 2] == 0
					&& chesses[r][c - 1] == 1 && chesses[r][c + 4] == 1
					&& chesses[r][c + 3] == 1 && chesses[r][c + 2] == 0
					&& chesses[r][c + 1] == 1) {
				return 2;
			}

			// 纵向特殊四四
			if (r > 2 && r < 12 && chesses[r - 3][c] == 1
					&& chesses[r - 2][c] == 0 && chesses[r - 1][c] == 1
					&& chesses[r + 3][c] == 1 && chesses[r + 2][c] == 0
					&& chesses[r + 1][c] == 1) {
				return 2;
			} else if (r > 2 && r < 11 && chesses[r - 3][c] == 1
					&& chesses[r - 2][c] == 1 && chesses[r - 1][c] == 0
					&& chesses[r + 4][c] == 1 && chesses[r + 3][c] == 1
					&& chesses[r + 2][c] == 0 && chesses[r + 1][c] == 1) {
				return 2;
			} else if (r > 3 && r < 11 && chesses[r - 4][c] == 1
					&& chesses[r - 3][c] == 1 && chesses[r - 2][c] == 1
					&& chesses[r - 1][c] == 0 && chesses[r + 4][c] == 1
					&& chesses[r + 3][c] == 1 && chesses[r + 2][c] == 1
					&& chesses[r + 1][c] == 0) {
				return 2;
			} else if (r > 3 && r < 11 && chesses[r - 4][c] == 1
					&& chesses[r - 3][c] == 1 && chesses[r - 2][c] == 0
					&& chesses[r - 1][c] == 1 && chesses[r + 4][c] == 1
					&& chesses[r + 3][c] == 1 && chesses[r + 2][c] == 0
					&& chesses[r + 1][c] == 1) {
				return 2;
			}

			// "\"向特殊四四
			if (c > 2 && c < 12 && r > 2 && r < 12
					&& chesses[r - 3][c - 3] == 1 && chesses[r - 2][c - 2] == 0
					&& chesses[r - 1][c - 1] == 1 && chesses[r + 3][c + 3] == 1
					&& chesses[r + 2][c + 2] == 0 && chesses[r + 1][c + 1] == 1) {
				return 2;
			} else if (c > 2 && c < 11 && r > 2 && r < 11
					&& chesses[r - 3][c - 3] == 1 && chesses[r - 2][c - 2] == 1
					&& chesses[r - 1][c - 1] == 0 && chesses[r + 4][c + 4] == 1
					&& chesses[r + 3][c + 3] == 1 && chesses[r + 2][c + 2] == 0
					&& chesses[r + 1][c + 1] == 1) {
				return 2;
			} else if (c > 3 && c < 11 && r > 3 && r < 11
					&& chesses[r - 4][c - 4] == 1 && chesses[r - 3][c - 3] == 1
					&& chesses[r - 2][c - 2] == 1 && chesses[r - 1][c - 1] == 0
					&& chesses[r + 4][c + 4] == 1 && chesses[r + 3][c + 3] == 1
					&& chesses[r + 2][c + 2] == 1 && chesses[r + 1][c + 1] == 0) {
				return 2;
			} else if (c > 3 && c < 11 && r > 3 && r < 11
					&& chesses[r - 4][c - 4] == 1 && chesses[r - 3][c - 3] == 1
					&& chesses[r - 2][c - 2] == 0 && chesses[r - 1][c - 1] == 1
					&& chesses[r + 4][c + 4] == 1 && chesses[r + 3][c + 3] == 1
					&& chesses[r + 2][c + 2] == 0 && chesses[r + 1][c + 1] == 1) {
				return 2;
			}

			// "/"向特殊四四
			// 101 1 101
			if (c > 2 && c < 12 && r > 2 && r < 12
					&& chesses[r - 3][c + 3] == 1 && chesses[r - 2][c + 2] == 0
					&& chesses[r - 1][c + 1] == 1 && chesses[r + 3][c - 3] == 1
					&& chesses[r + 2][c - 2] == 0 && chesses[r + 1][c - 1] == 1) {
				return 2;
			}
			// 110 1 1011
			else if (c > 3 && c < 12 && r > 3 && r < 11
					&& chesses[r - 3][c + 3] == 1 && chesses[r - 2][c + 2] == 1
					&& chesses[r - 1][c + 1] == 0 && chesses[r + 4][c - 4] == 1
					&& chesses[r + 3][c - 3] == 1 && chesses[r + 2][c - 2] == 0
					&& chesses[r + 1][c - 1] == 1) {
				return 2;
			}
			// 1110 1 0111
			else if (c > 3 && c < 11 && r > 3 && r < 11
					&& chesses[r - 4][c + 4] == 1 && chesses[r - 3][c + 3] == 1
					&& chesses[r - 2][c + 2] == 1 && chesses[r - 1][c + 1] == 0
					&& chesses[r + 4][c - 4] == 1 && chesses[r + 3][c - 3] == 1
					&& chesses[r + 2][c - 2] == 1 && chesses[r + 1][c - 1] == 0) {
				return 2;
			}
			// 1101 1 011
			else if (c > 3 && c < 11 && r > 3 && r < 11) {
				if (chesses[r - 4][c + 4] == 1 && chesses[r - 3][c + 3] == 1
						&& chesses[r - 2][c + 2] == 0
						&& chesses[r - 1][c + 1] == 1
						&& chesses[r + 4][c - 4] == 1
						&& chesses[r + 3][c - 3] == 1
						&& chesses[r + 2][c - 2] == 0
						&& chesses[r + 1][c - 1] == 1) {
					return 2;
				}
			}
		}

		return 0;

	}

 

函数调用如下:

/**
	 * 判赢有禁手
	 * @param r 最后一次下子的行数
	 * @param c 最后一次下子的列数
	 */
	public boolean JudgeWinWithJinshou(int r, int c) {

		if (Main.count == -1) {// 白子
			if (SuanFa.beFive(r, c)) {
				javax.swing.JOptionPane.showMessageDialog(mu, "白子赢了!!");
				ReDisplayChesseBoard();
				return true;
			}

		} else if (Main.count == 1) {// 黑子
			if (SuanFa.Five(r, c)) {// 五子
				javax.swing.JOptionPane.showMessageDialog(mu, "黑子赢了!!");
				ReDisplayChesseBoard();
				return true;
			} else if (SuanFa.LiveThree(r, c, 1, 'e') > 1) {
				javax.swing.JOptionPane.showMessageDialog(mu, "三三禁手!黑子输了!!");
				ReDisplayChesseBoard();
				return true;
			} else if (SuanFa.Four(r, c, 1, 'e') > 1) {
				javax.swing.JOptionPane.showMessageDialog(mu, "四四禁手!黑子输了!!");
				ReDisplayChesseBoard();
				return true;
			} else if (SuanFa.longlink(r, c)) {// 长连
				javax.swing.JOptionPane.showMessageDialog(mu, "长连禁手!黑子输了!!");
				ReDisplayChesseBoard();
				return true;
			}

		}
		return false;
	}

 

 

你可能感兴趣的:(五子棋,复盘,悔棋,禁手,判赢)