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

类图设计

代码实现
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("------------------------------");
}
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++)
{
posis[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++)
{
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++)
{
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++)
{
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();
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("输入错误,请重新输入!");
}
count += 1;
System.out.printf("第 {%d} 局开始:\n", count);
gb.initBoard();
gb.printBoard();
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设计
- 活动图比流程图功能更多,前者可以表示多条并行活动,每条分支活动都相当于一单独的流程图。
- 活动图并不适合于进一步设计类的各种方法,它更多的是给主函数提供清晰的代码思路,有的流程并不适合甚至构不成一个方法。
代码设计
- 先用static关键字分清类实例和对象实例,这对于方法的代码实现非常重要。
Math.random()和Random.nextInt()的区别。前者是静态且线程安全的,后者是非静态非线程安全的。一般的生成随机数可以用(int)(Math.random()*n)足够应用大多场合,但注意它是闭合区间[0,n]即包含0的。InputStreamReader和Scanner两种读取IO输入的方法。InputStreamReader是一个转换流,将字节输入流转化为字符输入流,本例中就是将System.in标准输入(键盘输入)作为参数传递给该转换流生成一个Reader对象,再利用一个BufferedReader类来包装Reader对象,使用其方法br.readLine()来读取。
Scnner类是一个简单的文本扫描器,可以对字符串,文件和输入流操作,使用正则表达式解析原始类型和字符串,最后使用各种next方法将得到的令牌转换成不同类型的值。- 注意对象引用,尤其是字符串对象,进行值相等判断时
==和equals()
的区别,作值相等的判断通常使用eqals()方法。 - 注意Java和Python的逻辑运算语法不同。Java中使用
!, ||, &&;Python中使用not, or, and。 - 标准输出
System.out.print()。其中变量out是System类的一个静态成员Field,它是一个java.io.PrintStream对象的引用,使用的也是PrintStream类的一个方法。
可改进部分
- 游戏逻辑需要改进,尤其是电脑的下棋逻辑,需要机器学习的参与。
- checked异常可以进一步进行处理。
- 主函数的代码有抽象为类方法的可能,比如落子的逻辑判断部分。