疯狂Java讲义_Chapter4_编写控制台的五子棋游戏

编写控制台的五子棋游戏

昨天复习了下《疯狂Java讲义》,完成前几章的习题,
现在基本完成了控制台五子棋游戏的编写,能够按照要求

  • 保证用户下和电脑下的棋上不能已经有棋子

  • 判断横、竖、左斜、右斜有是否有5个棋连在一起,从而判定胜负

来运行。

import java.io.*;
// 导入随机包
import java.util.Random;
/**
 * Description:
 * <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
 * <br/>Copyright (C), 2001-2016, Yeeku.H.Lee
 * <br/>This program is protected by copyright laws.
 * <br/>Program Name:
 * <br/>Date:
 * @author Yeeku.H.Lee kongyeeku@163.com
 * @version 1.0
 */

// 下面全部的方法函数都在Gobang这个类里
public class Gobang {
	// 定义棋盘的大小
	private static int BOARD_SIZE = 15;
	// 定义一个二维数组来充当棋盘
	private String[][] board;

	// 构造原始棋盘
	public void initBoard() {
		// 初始化棋盘数组
		board = new String[BOARD_SIZE][BOARD_SIZE];
		// 把每个元素赋为"╋",用于在控制台画出棋盘
		for (int i = 0 ; i < BOARD_SIZE ; i++)
		{
			for ( int j = 0 ; j < BOARD_SIZE ; j++)
			{
				board[i][j] = "╋";
			}
		}
	}

	// 在控制台输出棋盘的方法
	public void printBoard() {
		// 打印每个数组元素
		for (int i = 0 ; i < BOARD_SIZE ; i++)
		{
			for ( int j = 0 ; j < BOARD_SIZE ; j++)
			{
				// 打印数组元素后不换行
				System.out.print(board[i][j]);
			}
			// 每打印完一行数组元素后输出一个换行符
			System.out.print("\n");
		}
	}
	
	// 判断谁获胜了
	// 根据调用的Symbol不同,来判断电脑赢还是玩家赢
	public static boolean judgematch(String[][] board, String symbol) {
		// 判断水平上是否有5个相同符号连在一块
		// 先从头开始遍历
		int i = 0; 
		int j = 0;
		int a = 0;
		int b = 0;
		int n = 0;
		int sum = 0;
		int times = 0;
		boolean flag = false;
		// 初始化字符串变量current的值
		String current = "a";
		// 一行一行分析
		for (i = 0; i <= 14; i++  )  {
			// 每一行刚开始,让sum变量值为0.
			sum = 0;
			for (j = 0; j <= 13; j++  ) {
				current = board[i][j] ;
				if (current == symbol ) {
					// 每次遇到标识符,就让统计变量sum加一
					sum++;
					if (sum == 5) {
						flag = true ;
						return flag;
					}
					if (board[i][j + 1] != symbol) {
						sum = 0;
					}
				}
		  }
		}

		// 一列一列分析
		for (j = 0; j <= 14; j++ ) {
			// 每一列刚开始,让sum变量值为0.
			sum = 0;
			for (i = 0; i <= 13; i++ ) {
			    current = board[i][j];
				if (current == symbol) {
					// 每次遇到标识符,就让统计变量sum加1
					sum++;
					if (sum == 5) {
						flag = true ;
						return flag;
					}
					if (board[i + 1][j] != symbol) {
						sum = 0;
					}
				}
			}
		}
		
		// 这个
		// 中心线分析
		// 先分析“左斜”的上半部分
		// i 始终等于0 ,j 不断累加移动
		// 注意,其他3个和这个差不多,根据这个改变
		for (i = 0, j = 0; j <= 14; j++) {
			// 每一斜行刚开始,让sum变量值为0.
			sum = 0;
			// i 是几,times 就可以移动几次
			// 构造a ,b 来代替i, j 移动
			a = i;
			b = j;
			for (times = 0 ; times <= j - 1 ; times++ ) {
				// 确定刚开始的当前的的字符串;
				// j的值为x,就要分析x次current;
				current = board[a][b] ;
				// 判断当前子和期望的子是否相同,相同则
				if (current == symbol) {
					sum++;      
					// 判断是否5子相连
					if (sum == 5) {
						 flag = true ;
						 return flag;
					}
					// !!!!!!
					// 分析不了最左下变得值,次数不够;次数太多会溢出==》 只能借助特殊if条件来判断
					if (sum == 4) {
						// sum值为4时才进行预判。
						if (board[a + 1][b - 1] == symbol) {
							flag = true ;
							return flag;
						}
					}
					// 判断下一子是否是同样的子,不同则令sun清零
					if (board[a + 1][b - 1] != symbol) {
					sum = 0 ;
					}
					// 往左下角移动一次
					a = a + 1;
				    b = b - 1;			
				}
				// 当和期望的子不同时:
				if (current != symbol) {
				//	往左下角移动一次
					a = a + 1;
				    b = b - 1;
				}
			}
		}

	   //		 再分析“左斜”的下半部分
		// i 始终等于14 ,j 不断递减移动
		for (i = 14, j = 14; j >= 0; j--) {
			// 每一斜行刚开始,让sum变量值为0.
			sum = 0;
			// i 是几,times 就可以移动几次
			// 构造a ,b 来代替i, j 移动
			a = i;
			b = j;
			for (times = 0 ; times <= 14 - j -1 ; times++ ) {
				// 确定刚开始的当前的的字符串;
				// j的值为x,就要分析x次current;
				current = board[a][b] ;
				// 判断当前子和期望的子是否相同,相同则
				if (current == symbol) {
					sum++;      
					// 判断是否5子相连
					if (sum == 5) {
						 flag = true ;
						 return flag;
					}
					// !!!!!!
					// 分析不了最左下变得值,次数不够;次数太多会溢出==》 只能借助特殊if条件来判断
					if (sum == 4) {
						// sum值为4时才进行预判。
						if (board[a - 1][b + 1] == symbol) {
							flag = true ;
							return flag;
						}
					}
					// 判断下一子是否是同样的子,不同则令sun清零
					if (board[a - 1][b + 1] != symbol) {
					sum = 0 ;
					}
					// 往右上角移动一次
					a = a - 1;
				    b = b + 1;			
				}
				// 当和期望的子不同时:
				if (current != symbol) {
				//	往右上角移动一次
					a = a - 1;
				    b = b + 1;
				}
			}
		}

		//	 再分析“右斜”的上半部分
		// i 始终等于0 ,j 不断递减移动
		for (i = 0, j = 14; j >= 0; j--) {
			// 每一斜行刚开始,让sum变量值为0.
			sum = 0;
			// i 是几,times 就可以移动几次
			// 构造a ,b 来代替i, j 移动
			a = i;
			b = j;
			for (times = 0 ; times <= 14 - j -1 ; times++ ) {
				// 确定刚开始的当前的的字符串;
				// j的值为x,就要分析x次current;
				current = board[a][b] ;
				// 判断当前子和期望的子是否相同,相同则
				if (current == symbol) {
					sum++;      
					// 判断是否5子相连
					if (sum == 5) {
						 flag = true ;
						 return flag;
					}
					// !!!!!!
					// 分析不了最左下变得值,次数不够;次数太多会溢出==》 只能借助特殊if条件来判断
					if (sum == 4) {
						// sum值为4时才进行预判。
						if (board[a + 1][b + 1] == symbol) {
							flag = true ;
							return flag;
						}
					}
					// 判断下一子是否是同样的子,不同则令sun清零
					if (board[a + 1][b + 1] != symbol) {
					sum = 0 ;
					}
					// 往右下角移动
					a = a + 1;
				    b = b + 1;			
				}
				// 当和期望的子不同时:
				if (current != symbol) {
				//	往右下角移动
					a = a + 1;
				    b = b + 1;
				}
			}
		}

		//	 最后分析“右斜”的下半部分
		// i 始终等于14 ,j 不断递增移动
		for (i = 14, j =0; j <=14; j++) {
			// 每一斜行刚开始,让sum变量值为0.
			sum = 0;
			// i 是几,times 就可以移动几次
			// 构造a ,b 来代替i, j 移动
			a = i;
			b = j;
			for (times = 0 ; times <= j - 1 ; times++ ) {
				// 确定刚开始的当前的的字符串;
				// j的值为x,就要分析x次current;
				current = board[a][b] ;
				// 判断当前子和期望的子是否相同,相同则
				if (current == symbol) {
					sum++;      
					// 判断是否5子相连
					if (sum == 5) {
						 flag = true ;
						 return flag;
					}
					// !!!!!!
					// 分析不了最左下变得值,次数不够;次数太多会溢出==》 只能借助特殊if条件来判断
					if (sum == 4) {
						// sum值为4时才进行预判。
						if (board[a - 1][b - 1] == symbol) {
							flag = true ;
							return flag;
						}
					}
					// 判断下一子是否是同样的子,不同则令sun清零
					if (board[a - 1][b - 1] != symbol) {
					sum = 0 ;
					}
					// 往右下角移动
					a = a - 1;
				    b = b - 1;			
				}
				// 当和期望的子不同时:
				if (current != symbol) {
				//	往右下角移动
					a = a - 1;
				    b = b - 1;
				}
			}
		}

		return flag;
	}


/** 
 * 主函数
 */
    public static void main(String[] args) throws Exception  {   
		// 创建对象Gobang 的一个Gobang类型的实例 gb
        Gobang gb = new Gobang();
		gb.initBoard();
		gb.printBoard();
		// 要创建随机数,首先应该要创建Random对象的实例。!!!
		Random rand = new Random();
		int yPos_pc = 0;
		int xPos_pc = 0;
		// 初始化布尔变量result_Human
		boolean result_Human = false ;
		// 初始化布尔变量result_Human
		boolean result_Computer = false ;
		// 这是用于获取键盘输入的方法
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		String inputStr = null;
		// br.readLine():每当在键盘上输入一行内容按回车,用户刚输入的内容将被br读取到。
		while ((inputStr = br.readLine()) != null)
		{
			// 将用户输入的字符串以逗号(,)作为分隔符,分隔成2个字符串
			String[] posStrArr = inputStr.split(",");
			// 将2个字符串转换成用户下棋的座标
			int xPos = Integer.parseInt(posStrArr[0]);
			int yPos = Integer.parseInt(posStrArr[1]);
			// 判断人下的棋子上是否有棋子,如果有,提醒重新下这个棋子
			if (gb.board[yPos - 1][xPos - 1] == "╋")  {
			// 把对应的数组元素赋为"●"。
			// 没有其他棋子,则可以下在这里
			gb.board[yPos - 1][xPos - 1] = "●"; 
			}
			// 如果已有棋子,则
			else if (gb.board[yPos - 1][xPos - 1] != "╋" )  {
				System.out.println("There is a piece on the board, please try to use another place !");
				System.out.println("请重新输入您下棋的座标,应以x,y的格式:");
				continue ;
			}
			/*
			 电脑随机生成2个整数,作为电脑下棋的座标,赋给board数组。
			 还涉及
				1.座标的有效性,只能是数字,不能超出棋盘范围
				2.如果下的棋的点,不能重复下棋。
				3.每次下棋后,需要扫描谁赢了
			 */
			 // 构建电脑下的棋子坐标
			// 同时判断电脑下的棋子坐标是否有效
			 for (int i=0; i >=0; i++ ) {
				 yPos_pc = rand.nextInt(14) + 1 ;
			     xPos_pc = rand.nextInt(14) + 1;
				 if ( gb.board[ yPos_pc  ][xPos_pc  ] == "╋" )  {
					// Gobang.java:85: 错误: 非法字符: '\uff1b'
					// 下面的分号写错了,用了中文的 
					  // gb.board[ yPos_pc - 1][xPos_pc - 1]  = "●" ;
					 //  gb.board[ yPos_pc - 1 ][xPos_pc - 1 ]  = "▲" ;
					  gb.board[ yPos_pc - 1 ][xPos_pc - 1 ]  = "▲" ;
					  break;
				 }
			 }
			 // 打印棋盘
			 gb.printBoard();


			 // 调用判断谁赢了的算法
			// 判断人类
			// result_Human =  judgematch( board, "*" ) ;
			result_Human =  judgematch( gb.board, "●" ) ;
			// 判断电脑
		    // result_Pc =  judgematch( board, "▲" ) ;
			// result_Pc =  judgematch( gb.board, "▲" ) ;
			result_Computer =  judgematch( gb.board, "▲" ) ;
//			 while (gb.board[ rand.nextInt(16) - 1][rand.nextInt(16) - 1] != "●"  )  {
//					gb.board[yPos_pc - 1][xPos_pc - 1] = "$" ;
//			 }
	
			if (result_Human) {
				System.out.println("Human victory");
			//	break;
			}
			if (result_Computer) {
				System.out.println("Computer victory");
				// break;
			}
			System.out.println("请输入您下棋的座标,应以x,y的格式:");
		}
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值