关于使用java实现控制台版五子棋游戏的代码与想法

  • 实现控制台版五子棋游戏
  • 思路过程及代码
  • 一些遇到的问题以及想法
  • 一点更新


实现控制台版五子棋游戏

思路过程及代码

编程实现 控制台版 并支持两人对战的五子棋游戏

五子棋这个游戏相比大家都非常的熟悉,通过让自己的棋子连成5点一线来获得胜利。
我们想一想整个过程可以发现以下几点:

  1. 游戏的进程是两个人轮番行动,直到一个人完成胜利条件为止,我们并不清楚会进行多少次循环,所以我们会采用while的方式对整个循环进行控制而不是使用for循环。
  2. 我们发现五子棋的棋盘是一个二维的数组类型,我们需要用一个二维数组储存整个棋盘的情况。
  3. 为了方便每一次下棋时都能看到棋盘的情况,我们需要创造一个方法去遍历这个棋盘,在每一次棋手下棋之后都将变化后的棋盘展示一次。
  4. 五子棋的胜利条件可以分为4种类型,分别是:
    (1)五个相同棋子一行
    (2)五个相同棋子一列
    (3)五个相同棋子自左下向右上连成一线
    (4)五个相同棋子自左上向右下连成一线
    每一次棋手下棋结束之后都对棋盘进行这四种类型的判断
  5. 为了防止棋盘下满还没有结束的情形,我们选择对棋盘上的尚未下棋的部分进行计数,若没有任何空位,则双方平局

之后我们放上相应的代码:

棋盘的展示的方法

/**创建一个展示棋盘的方法
	 * 
	 */
	public static void showBoard(int[][] a) {
		for (int i = 0;i < 16;i++) {
			for (int j = 0;j < 16;j++) {
				System.out.print(a[j][i]);
				if (a[j][i] > 9) 
					System.out.print(" ");
				else {
					System.out.print("  ");
				}
			}
			System.out.println();
		}
		System.out.println();
	}

判断胜利的方法

/**判断是否胜利
	 * 
	 */
	//如果黑棋胜利返回1 白棋胜利返回2 无人胜利返回0
	public static int victoryJudge1(int[][] a){
		//判断是否胜利-----5个连成一行
		for (int i = 1;i <16;i++) {
			for (int j = 1;j < 12 ;j++) {
				if (a[j][i] == a[j+1][i] && a[j][i]== a[j+2][i] && a[j][i]== a[j+3][i] && a[j][i]== a[j+4][i])
				{
					return a[j][i];
				}
			}
		}
		return 0;
	}
	public static int victoryJudge2(int[][] a){
		//判断是否胜利-----5个连成一列
		for (int j =1;j < 16;j++) {
			for (int i = 1;i < 12;i++) {
				if (a[j][i] ==a[j][i+1] && a[j][i] ==a[j][i+2] && a[j][i] == a[j][i+3] && a[j][i] == a[j][i+4])
				{
					return a[j][i];
				}
			}
		}
		return 0;
	}
	public static int victoryJudge3(int[][] a){
		//判断是否胜利-----5个斜着连成
		for (int i = 5;i < 16;i++) {
			for (int j = 1;j < 12;j++) {
				if (a[j][i] == a[j+1][i-1] && a[j][i] == a[j+2][i-2] && a[j][i] == a[j+3][i-3] && a[j][i] == a[j+4][i-4])
					return a[j][i];
			}
		}
		return 0;
	}
	public static int victoryJudge4(int[][] a){
		
		for (int i = 1;i < 12;i++) {
			for (int j =1;j < 12;j++) {
				if (a[j][i] == a[j+1][i+1] && a[j][i] == a[j+2][i+2] && a[j][i] == a[j+3][i+3] && a[j][i] == a[j+4][i+4])
					return a[j][i];
			}
		}
		
		return 0;
	}

判断输入的数据是否在棋盘范围之内

/**创建一个方法判断输入的行列数是否正确
	 * 
	 */
	public static int inputJudge() {
		int a = 0;
		while (true) {
			if (input.hasNextInt()) {
				a = input.nextInt();
				if (a > 15 || a < 1) {
					System.out.println("您输入的数不正确,请重新输入");
					input.nextLine();
					continue;
				}
				return a;
			} else {
				System.out.println("您输入的数不正确,请重新输入");
				input.nextLine();
				continue;
			}
		}
		
	}

判断并输出哪一方胜利

/**输入,判断胜利的结果并输出结果
	 * 
	 */
	public static int output(int endFlag) {
		if (endFlag == 1) {
			System.out.println("黑棋胜利");
			return 1;
		} else if (endFlag == 2) {
			System.out.println("白棋胜利");
			return 2;
		}
		return 0;
	}

主函数部分

static Scanner input = new Scanner(System.in);
	/**
	 * 五子棋游戏
	 */
	public static void main(String[] args) {
		int[][] board = new int[16][16];
		//test
		showBoard(board);
		
		for (int i = 0;i<16;i++) {
			board[0][i] = i;
			board[i][0] = i;
		}
		//test
		showBoard(board);
		int column = 0;//列
		int row = 0;//行
		int endFlag = 0;//结束标志
				
		while (true) {
			
			//黑棋走
			while (true) {
				System.out.println("黑棋走");
				System.out.println("请输入下的行数(1-15)");
				row = inputJudge();
				System.out.println("请输入下的列数(1-15)");
				column = inputJudge();
				if (board[column][row] == 1 || board[column][row] == 2) {
					System.out.println("棋盘这个地方已经有棋子了请重新输入");
					input.nextLine();
					continue;
				}
				else {
					board[column][row] = 1;
					break;
				}
			
			}
			
			//判断是否胜利
			showBoard(board);
			endFlag = output(victoryJudge1(board));
			if (endFlag == 2 || endFlag == 1) {
				break;
			}
			endFlag = output(victoryJudge2(board));
			if (endFlag == 2 || endFlag == 1) {
				break;
			}
			endFlag = output(victoryJudge3(board));
			if (endFlag == 2 || endFlag == 1) {
				break;
			}
			endFlag = output(victoryJudge4(board));
			if (endFlag == 2 || endFlag == 1) {
				break;
			}
			
			
			//白棋走
			while (true) {
				System.out.println("白棋走");
				System.out.println("请输入下的行数(1-15)");
				row = inputJudge();
				System.out.println("请输入下的列数(1-15)");
				column = inputJudge();
				if (board[column][row] == 1 || board[column][row] == 2) {
					System.out.println("棋盘这个地方已经有棋子了请重新输入");
					input.nextLine();
					continue;
				} else {
					board[column][row] = 2;
					break;
				}
		
			}
			//判断是否胜利
			showBoard(board);
			endFlag = output(victoryJudge1(board));
			if (endFlag == 2 || endFlag == 1) {
				break;
			}
			endFlag = output(victoryJudge2(board));
			if (endFlag == 2 || endFlag == 1) {
				break;
			}
			endFlag = output(victoryJudge3(board));
			if (endFlag == 2 || endFlag == 1) {
				break;
			}
			endFlag = output(victoryJudge4(board));
			if (endFlag == 2 || endFlag == 1) {
				break;
			}
			
			
			//如果棋盘下满都没有人胜利则平局
			int checkTime = 0;//次数统计
			for (int i = 1;i < 16;i++) {
				for (int j = 1;j < 16;j++) {
					if (board[j][i] == 0)
						checkTime++;
				}
			}
			if (checkTime == 0) {
				System.out.println("棋盘已满 平局");
				break ;
			}
		}

	}

其它的只需要导入Scanner的包就好了。

一些遇到的问题以及想法

在这个过程当中我还是遇到了很多问题

  1. 判断胜利的四个条件没有办法放在一个方法之中:最开始的时候,我只写了一个方法去判断胜利,相当于把victoryJudge的4个方法写在了一起,但是发现只有最上面的方法会执行,另外三个就不执行了,把他们分开为4个方法之后就又可以执行了,不是很明白为什么会这样。
  2. 判断胜利的方法冗杂:不仅仅是victoryJudge的4个方法,我还设计了一个output的方法,仅仅是简写了几步黑棋还是白棋胜利的输出,一开始的想法是在其中加入break,让他可以跳出最大的游戏循环,发现会报错。之后为最大的游戏循环上了一个标签,break后面加上标签,这样也会报错。不知道怎么样才能在外部的方法中加入break。
  3. 过程中的简化:整个程序疯狂的使用双层for循环来判断是否满足胜利条件,不知道有没有更简便或者说效率更高的方法去判断是否满足胜利条件。

一点更新

在经过课上和老师同学的沟通后发现实际上是判断的逻辑出现了问题,在我的判断逻辑victoryJudge中,双层for循环之后应该判断该棋子是否下过棋子,更改之后的版本如下图所示

public static int victoryJudge1(int[][] a){
		//判断是否胜利-----5个连成一行
		for (int i = 1;i <16;i++) {
			for (int j = 1;j < 12 ;j++) {
				if (a[j][i] == 1 || a[j][i] == 2){//***
					if (a[j][i] == a[j+1][i] && a[j][i]== a[j+2][i] && a[j][i]== a[j+3][i] && a[j][i]== a[j+4][i])
				
						return a[j][i];
				}
			}
		}
		return 0;
	}

这里只放了一个更改之后的样子,其他3个判断方法同样添加***的那个判断就ok了。

另外,似乎没有能够通过调用其他方法来跳出主函数中的无限循环的办法。唯一可以做的是将无限循环中的判断条件更改成一个可改变的值,以此来进行跳出。

很明显,这个想法不适用于这个五子棋程序,因为如果无限循环的判断周期为一人下一次棋之后,没有办法保证第一个人下棋之后如果获得胜利就结束。最好的办法还是让判断方法返回一个值,以此来决定是否要跳出无限循环。