五子棋(java)

五子棋分析:

[1] 这里做的是一个控制台程序,一个16x16的棋盘组成;同时棋盘的第一行和第一列作为坐 标指示行和列不可落子。

[2] 行列的指示像:0 1 2 3 4 5 6 7 8 9 a b c d e f ,也就是说任何一方在落子的时候只能是这其中的任一组合中选择,如:23,5d,fe,等,否则判断落子不合法,该方重新落子。

[3] 考虑用一个固定的字符数组来初始化棋盘,并且在打印的时候将第一行和第一列至为 0 1 2 3 4 5 6 7 8 9 a b c d e f ,其他可以落子的地方至为'*',那么接下来的问题就是落子的问题了。

[4] 鉴于白黑双方每次只能落子一次并且不能悔棋(当然悔棋是能实现的了),设计的时候在Chess类中给一个对象变量初始化为0,当每一个打印新的棋盘时该变量做一次自加运算,用该变量与2的模运算来判定黑白方落子(余0白方落子,余1黑方落子),现在接下来的问题是解决输赢的问题了。

[5] 这面所以的问题都比较好解决,这里输赢怎么来判断呢?规则是当任何一条线上(横向,纵向,左斜方向,右斜方向)的同一方的棋子率先达到5颗,那么判定该方获胜;我这里的思路是每次下一颗棋子时,总横向,纵向,斜向判断该方的棋子是否达到5颗,达到则该方获胜。


Chess.java
package com.chess.gobang;

/**
 * @ClassName: Chess
 * @Description: TODO
 * @author Bruce
 * @date Aug 29, 2011 9:13:59 PM
 * @version 1.1
 * 
 */
class Chess {
	private static final int ROW_CHESS = 16;
	private static final int COLUMN_CHESS = 16;
	public int stepCount = 0;
	char[][] board = new char[ROW_CHESS][COLUMN_CHESS];

	public int getStepCount() {
		return this.stepCount;
	}

	public void init() {
		for (int i = 0; i < ROW_CHESS; i++) {
			for (int j = 0; j < COLUMN_CHESS; j++) {
				if (i == 0 || j == 0) {
					board[0][j] = Integer.toHexString(j).charAt(0);
					board[j][0] = Integer.toHexString(j).charAt(0);
				} else
					board[i][j] = '*';
			}
		}
	}

	public void printChess() {
		for (int i = 0; i < ROW_CHESS; i++) {
			for (int j = 0; j < COLUMN_CHESS; j++) {
				System.out.print(board[i][j] + " ");
			}
			System.out.println();
		}
		stepCount++;
	}

	public boolean validChessman(char row) {
		switch (row) {
		case '1':
			return true;
		case '2':
			return true;
		case '3':
			return true;
		case '4':
			return true;
		case '5':
			return true;
		case '6':
			return true;
		case '7':
			return true;
		case '8':
			return true;
		case '9':
			return true;
		case 'a':
			return true;
		case 'b':
			return true;
		case 'c':
			return true;
		case 'd':
			return true;
		case 'e':
			return true;
		case 'f':
			return true;
		}
		return false;
	}

	public void setWhite(char row, char col) {
		int i = Character.getNumericValue(row);
		int j = Character.getNumericValue(col);

		if (board[i][j] == '*') {
			board[i][j] = '@';
			this.printChess();
		}

		else if (board[i][j] == '@')
			System.out.println("这里已经有你的棋子!");
		else
			System.out.println("这里已经有黑方棋子!");

	}

	public void setBlack(char row, char col) {
		int i = Character.getNumericValue(row);
		int j = Character.getNumericValue(col);

		if (board[i][j] == '*') {
			board[i][j] = '#';
			this.printChess();
		} else if (board[i][j] == '#')
			System.out.println("这里已经有你的棋子!");
		else
			System.out.println("这里已经有白方棋子!");

	}

	public boolean isWin(char row, char col) {

		if (this.validChessman(row) && this.validChessman(col)) {

			int r = Character.getNumericValue(row);
			int l = Character.getNumericValue(col);
			int left = 0;
			int right = 0;
			int up = 0;
			int down = 0;

			int leftUp = 0;
			int leftDown = 0;

			int rightUp = 0;
			int rightDown = 0;

			int ri = l;
			int upPoint = r;
			int tempL = l;

			int leftUpR = r;
			int leftUpL = l;
			int leftDownR = r;
			int leftDownL = l;

			int rightUpR = r;
			int rightUpL = l;
			int rightDownR = r;
			int rightDownL = l;

			if (this.getStepCount() % 2 == 0) {

				// 判断横向
				while (this.validChessman(Integer.toHexString(--l).charAt(0))
						&& board[r][l] == '@') {
					left++;
				}
				while (ri < 16
						&& this.validChessman(Integer.toHexString(ri).charAt(0))
						&& board[r][ri++] == '@') {
					right++;
				}
				if (right + left > 4) {
					System.out.println("恭喜你,白方获胜!");
					return true;
				}
				// 判断纵向
				while (this.validChessman(Integer.toHexString(--r).charAt(0))
						&& board[r][tempL] == '@')
					up++;
				while (upPoint < 16
						&& this.validChessman(Integer.toHexString(upPoint)
								.charAt(0)) && board[upPoint++][tempL] == '@')
					down++;
				if (up + down > 4) {
					System.out.println("恭喜你,白方获胜!");
					return true;
				}
				// 判断左斜方向
				while (this.validChessman(Integer.toHexString(--leftUpR)
						.charAt(0))
						&& this.validChessman(Integer.toHexString(--leftUpL)
								.charAt(0)) && board[leftUpR][leftUpL] == '@')
					leftUp++;
				while (leftDownR < 16
						&& leftDownL < 16
						&& this.validChessman(Integer.toHexString(leftDownR)
								.charAt(0))
						&& this.validChessman(Integer.toHexString(leftDownL)
								.charAt(0))
						&& board[leftDownR++][leftDownL++] == '@')
					leftDown++;
				if (leftUp + leftDown > 4) {
					System.out.println("恭喜你,白方获胜!");
					return true;
				}
				// 判断右斜方向
				while (this.validChessman(Integer.toHexString(--rightUpR)
						.charAt(0))
						&& this.validChessman(Integer.toHexString(++rightUpL)
								.charAt(0))
						&& rightUpL < 16
						&& board[rightUpR][rightUpL] == '@')
					rightUp++;
				while (this.validChessman(Integer.toHexString(rightDownR)
						.charAt(0))
						&& this.validChessman(Integer.toHexString(rightDownL)
								.charAt(0))
						&& rightDownR < 16
						&& board[rightDownR++][rightDownL--] == '@')
					rightDown++;
				if (rightUp + rightDown > 4) {
					System.out.println("恭喜你,白方获胜!");
					return true;
				}

			} else {
				// 判断横向
				while (this.validChessman(Integer.toHexString(--l).charAt(0))
						&& board[r][l] == '#') {
					left++;
				}
				while (ri < 16
						&& this.validChessman(Integer.toHexString(ri).charAt(0))
						&& board[r][ri++] == '#') {
					right++;
				}
				if (right + left > 4) {
					System.out.println("恭喜你,黑方获胜!");
					return true;
				}
				// 判断纵向
				while (this.validChessman(Integer.toHexString(--r).charAt(0))
						&& board[r][tempL] == '#')
					up++;
				while (upPoint < 16
						&& this.validChessman(Integer.toHexString(upPoint)
								.charAt(0)) && board[upPoint++][tempL] == '#')
					down++;
				if (up + down > 4) {
					System.out.println("恭喜你,黑方获胜!");
					return true;
				}
				// 判断左斜方向
				while (this.validChessman(Integer.toHexString(--leftUpR)
						.charAt(0))
						&& this.validChessman(Integer.toHexString(--leftUpL)
								.charAt(0)) && board[leftUpR][leftUpL] == '#')
					leftUp++;
				while (leftDownR < 16
						&& leftDownL < 16
						&& this.validChessman(Integer.toHexString(leftDownR)
								.charAt(0))
						&& this.validChessman(Integer.toHexString(leftDownL)
								.charAt(0))
						&& board[leftDownR++][leftDownL++] == '#')
					leftDown++;
				if (leftUp + leftDown > 4) {
					System.out.println("恭喜你,黑方获胜!");
					return true;
				}
				// 判断右斜方向
				while (this.validChessman(Integer.toHexString(--rightUpR)
						.charAt(0))
						&& this.validChessman(Integer.toHexString(++rightUpL)
								.charAt(0))
						&& rightUpL < 16
						&& board[rightUpR][rightUpL] == '#')
					rightUp++;
				while (this.validChessman(Integer.toHexString(rightDownR)
						.charAt(0))
						&& this.validChessman(Integer.toHexString(rightDownL)
								.charAt(0))
						&& rightDownR < 16
						&& board[rightDownR++][rightDownL--] == '#')
					rightDown++;
				if (rightUp + rightDown > 4) {
					System.out.println("恭喜你,黑方获胜!");
					return true;
				}
			}
		}
		return false;
	}
}



Gobang.java
package com.chess.gobang;

/** 
 * @ClassName: Gobang 
 * @Description: TODO
 * @author Bruce
 * @date Aug 29, 2011 9:14:42 PM 
 * @version 1.1
 * 
 */
import java.util.Scanner;

public class Gobang {

	public static void main(String[] args) {
		Chess chess = new Chess();
		chess.init();
		chess.printChess();

		Scanner sc = new Scanner(System.in);
		String chessman = "";
		char rowChessman = 0;
		char colChessman = 0;

		while (!chess.isWin(rowChessman, colChessman)) {
			//倘若到最后都没分出胜负,跳出循环,结束,平局
			if(chess.getStepCount() == 226)
			{
				break;
			}
				
			// 由白方开始落子
			if (chess.getStepCount() % 2 == 1) {
				System.out.println("请白方落子(@):");
				
				chessman = sc.next();
				//棋子坐标长度是否为两位,否则重新落子
				if (chessman.length() == 2) {
					rowChessman = chessman.charAt(0);
					colChessman = chessman.charAt(1);
					boolean whiteDone = false;
					while (!whiteDone) {
						// 棋子合法,继续;否则直到获得合法棋子为止
						if (chess.validChessman(rowChessman)
								&& chess.validChessman(colChessman)) {
							chess.setWhite(rowChessman, colChessman);
							whiteDone = true;
						} else {
							//棋子包含无效字符,重新落子
							System.out.println("白棋子不合法,请重新落子:");
							break;
						}
					}
				} else {
					System.out.println("白棋子坐标长度应该为2,请重新落子:");
				}
			} else {
				// 黑方开始落子
				System.out.println("请黑方落子(#):");
				chessman = sc.next();
				//棋子坐标长度是否为两位,否则重新落子
				if (chessman.length() == 2) {
					rowChessman = chessman.charAt(0);
					colChessman = chessman.charAt(1);
					boolean blackDone = false;
					while (!blackDone) {
						// 棋子合法,继续;否则直到获得合法棋子为止
						if (chess.validChessman(rowChessman)
								&& chess.validChessman(colChessman)) {
							chess.setBlack(rowChessman, colChessman);
							blackDone = true;
						} else {
							//棋子包含无效字符,重新落子
							System.out.println("黑棋子不合法,请重新落子:");
							break;
						}
					}
				} else {
					System.out.println("黑棋子坐标长度应该为2,请重新落子:");
				}
			}
		}
		System.out.println("恭喜二位,你们实力相当,占城平手!");
	}

}





附注:
[size=medium]
[1] 我认为这里的isWin()方法写的实在是对不住观众,仅仅是功能实现而已;这个仅仅是一个中间版本,接下来的时候我会优化这些代码,使其更加的面向对象,这样可读性也会好很多。

[2] 在判断棋子的合法性我用了一个包含switch的方法,这里当然也可以利用类似二分查找的算法,只是返回值是boolean类型而已,不过我觉得这里用switch语句可能可读性更加好点,而且在这里其性能也不比二分查找差(我的感觉而已)
size]

你可能感兴趣的:(java,五子棋,gobang,chess)