五子棋游戏Java代码简单实现(含活动图和类图设计)

五子棋游戏Java代码简单实现(含活动图和类图设计)

文章目录

  • 五子棋游戏Java代码简单实现(含活动图和类图设计)
    • 活动图设计
    • 类图设计
    • 代码实现
    • 总结
      • OOA和OOD设计
      • 代码设计
      • 可改进部分

活动图设计

五子棋游戏Java代码简单实现(含活动图和类图设计)_第1张图片

类图设计

五子棋游戏Java代码简单实现(含活动图和类图设计)_第2张图片

代码实现

import java.lang.Math;
import java.io.*;
import java.util.Scanner;

class Gobang 
{
	// 定义棋盘和棋盘大小
	private  String[][] board;
	private static int size = 15;
	// 记录分数
	private int[] score = {0, 0};

	// 初始化棋盘
	public void initBoard()
	{
		board = new String[size][size];
		
		for ( int i = 0; i <= size - 1; i++)
		{
			for ( int j =0 ; j <=size - 1; j++)
				board[i][j] = "+";
		}	
	}

	// 打印棋盘
	public void printBoard()
	{
		System.out.println("------------------------------");

		for ( int i = 0; i < size; i++)
		{
			for ( int j =0 ; j < size; j++)
			{
				System.out.print(board[i][j]);
			}
			System.out.print("\n");
		}

		System.out.println("------------------------------");
	}
	
	// 辅助whoWin()函数的扫描结束判断函数
	public boolean end(String[] posis)
	{
		//相同标志
		boolean flag = false;
		String color = posis[0];
		for (int i=1; i < 5; i++)
		{
			if (color != posis[i])
			{
				flag = false;
				break;
			}
			else
				flag = true;
		}
		if (flag && posis[0] == "●")
		{
			System.out.println("Player black wins!");
			System.out.printf("Black : White的当前比分为%d:%d\n", ++this.score[0], this.score[1]);
			System.out.println("------------------------------");
			return true;
		}
		else if (flag && posis[0] == "○")
		{
			System.out.println("Player white wins!");
			System.out.printf("Black : White的当前比分为%d:%d\n", this.score[0], ++this.score[1]);
			System.out.println("------------------------------");
			return true;
		}
		return false;
	}

	// 判断输赢
	public boolean whoWin()
	{
		// 存储所有连续的五个棋子
		String[] posis = new String[5];

		// 横向遍历
		for ( int i = 0; i < size; i++)
		{	// 遍历列
			for ( int j = 0; j < size-4; j++)
			{	// 遍历同行
				for (int k = 0; k < 5; k++)
				{	// 找到起始元素后遍历前五个board元素
					posis[k] = board[i][j+k];
					// 输出位置和元素
					//System.out.printf("[%d,%d], %s", i, j+k, board[i][j+k]);
				}
				// 判断是否有胜者
				if (end(posis))	return true;
			}

		}
		// 纵向遍历
		for ( int i = 0; i < size-5; i++)
		{	// 遍历列
			for ( int j = 0; j < size-1; j++)
			{	// 遍历行
				for (int k = 0; k < 5; k++)
				{	// 找到起始元素后遍历前五个board元素
					posis[k] = board[i+k][j];
				}
				// 判断是否有胜者
				if (end(posis))	return true;
			}
		}
		// 正斜向遍历
		for ( int i = 0; i < size-5; i++)
		{	// 遍历列
			for ( int j = 0; j < size-5; j++)
			{	// 遍历行
				for (int k = 0; k < 5; k++)
				{	// 找到起始元素后遍历前五个board元素
					posis[k] = board[i+k][j+k];
				}
				// 判断是否有胜者
				if (end(posis))	return true;
			}
		}
		// 反斜向遍历
		for ( int i = 4; i < size-1; i++)
		{	// 遍历列
			for ( int j = 0; j < size-5; j++)
			{	// 遍历行
				for (int k = 0; k < 5; k++)
				{	// 找到起始元素后遍历前五个board元素
					posis[k] = board[i-k][j+k];
				}
				// 判断是否有胜者
				if (end(posis))	return true;
			}
		}
		return false;
	}

	public static void main(String[] args) throws IOException
	{	// 游戏入口
		Gobang gb = new Gobang();
		// 棋盘规格
		int size = Gobang.size;
		// 游戏局数
		int count = 0;
		while (true)
		{	
			while (true)
			{	// 是否进行下一局
				
				Scanner sc= new Scanner(System.in);
				System.out.print("是否开始新游戏(Y/N):");
				String hasnext = sc.next();
				// 这里String对象和字符串的判断不能用==,要用equals方法
				if (hasnext.equals("Y") || hasnext.equals("y"))
				{
					System.out.printf("Black : White的当前比分为%d:%d\n", gb.score[0], gb.score[1]);	
					System.out.println("------------------------------");
					break;
				}
				else if (hasnext.equals("N") || hasnext.equals("n"))
				{
					System.out.printf("Black : White的最终比分为%d:%d\n", gb.score[0], gb.score[1]);
					System.out.println("------------------------------");
					System.exit(0);
				}
				else
					System.out.print("输入错误,请重新输入!");
			}

			// 局数增加1
			count += 1;
			System.out.printf("第 {%d} 局开始:\n", count);
			
			// 初始化棋盘并打印
			gb.initBoard();
			gb.printBoard();
			// String[][] board = gb.board;
			// 回合提前结束标志
			boolean flag = false;

			while (!flag)
			{	// 回合行为
				// 输入结束标志
				boolean reflag = false;
				// 读取用户输入
				while (!reflag)
				{
					System.out.println("你执黑棋,请输入下一步棋的坐标(x,y):");
					BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
					String inputstr = null;
					while ((inputstr = br.readLine()) != null )
					{
						String[] coo = inputstr.split(",");
						int x = Integer.parseInt(coo[0]);
						int y = Integer.parseInt(coo[1]);
						// 判断坐标有效性
						if (x >= 0 && x <= Gobang.size && y>=0 && y<= Gobang.size)
						{
							if (gb.board[x-1][y-1] == "●" || gb.board[x-1][y-1] == "○")
							{
								System.out.println("此处已经有棋,请重新输入坐标:");
							}
							else
							{
								gb.board[x-1][y-1] = "●";
								gb.printBoard();
								System.out.printf("你刚落子到了(%d, %d)位置\n", x, y);
								System.out.println("------------------------------");
								if (gb.whoWin())
									flag = true;
								reflag = true;
								break;
							}
						}
						else
						{
							System.out.println("位置超出棋盘大小,请重新输入!");
						}
					}

				}

				// 电脑随机落子
				while (!flag)
				{
					Integer x = (int)(Math.random()*Gobang.size);
					Integer y = (int)(Math.random()*Gobang.size);
					if (x!=0 && y!=0 && gb.board[x-1][y-1] == "+")
					{
						gb.board[x-1][y-1] = "○";
						gb.printBoard();
						System.out.printf("电脑刚落子到了(%d, %d)位置\n", x, y);
						System.out.println("------------------------------");
						// 判断输赢
						if (gb.whoWin())
							flag = true;
						break;
					}
				}
			}

		}
	}
}

总结

OOA和OOD设计

  1. 活动图比流程图功能更多,前者可以表示多条并行活动,每条分支活动都相当于一单独的流程图。
  2. 活动图并不适合于进一步设计类的各种方法,它更多的是给主函数提供清晰的代码思路,有的流程并不适合甚至构不成一个方法。

代码设计

  1. 先用static关键字分清类实例和对象实例,这对于方法的代码实现非常重要。
  2. Math.random()和Random.nextInt()的区别。前者是静态且线程安全的,后者是非静态非线程安全的。一般的生成随机数可以用(int)(Math.random()*n)足够应用大多场合,但注意它是闭合区间[0,n]即包含0的。
  3. InputStreamReaderScanner两种读取IO输入的方法。InputStreamReader是一个转换流,将字节输入流转化为字符输入流,本例中就是将System.in标准输入(键盘输入)作为参数传递给该转换流生成一个Reader对象,再利用一个BufferedReader类来包装Reader对象,使用其方法br.readLine()来读取。
    Scnner类是一个简单的文本扫描器,可以对字符串,文件和输入流操作,使用正则表达式解析原始类型和字符串,最后使用各种next方法将得到的令牌转换成不同类型的值。
  4. 注意对象引用,尤其是字符串对象,进行值相等判断时==equals()
    的区别,作值相等的判断通常使用eqals()方法。
  5. 注意Java和Python的逻辑运算语法不同。Java中使用!, ||, &&;Python中使用not, or, and
  6. 标准输出System.out.print()。其中变量outSystem类的一个静态成员Field,它是一个java.io.PrintStream对象的引用,使用的也是PrintStream类的一个方法。

可改进部分

  1. 游戏逻辑需要改进,尤其是电脑的下棋逻辑,需要机器学习的参与。
  2. checked异常可以进一步进行处理。
  3. 主函数的代码有抽象为类方法的可能,比如落子的逻辑判断部分。

你可能感兴趣的:(Java)