java实现五子棋人人对战(纯控制台)

265 阅读2分钟

适应对象

纯控制台输出,没有使用java swing,只有一个启动类。适合只关注代码逻辑,对java swing不感兴趣的初学者。

游戏过程截图展示

image.png

image.png

image.png

主要特点

  1. 纯控制台输出,不涉及java swing
  2. 只有一个类,复制过去即可启动
  3. 双人五子棋对战,交互良好
  4. 支持查看最后一次落子
  5. 胜负判断满足五子连珠即可,没有考虑禁手

代码

package gobang;

import java.util.Scanner;

/**
 * TODO
 *
 * @author chen
 * @since 2022/5/2 12:37 下午
 */
public class GobangApplication {
    public static void main(String[] args) {
        System.out.println("********************************************************");
        System.out.println("                   欢迎来到双人五子棋对战");
        System.out.println("********************************************************");

        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入黑方的名字:");
        String blackName = scanner.next();
        System.out.println("黑方选手为:" + blackName);
        System.out.println("请输入白方的名字:");
        String whiteName = scanner.next();
        System.out.println("白方选手为:" + whiteName);

        String[] roleNames = new String[2];
        roleNames[0] = blackName;
        roleNames[1] = whiteName;
        int[] grade = new int[2];
        boolean play = true;
        while (play) {
            //    输入棋盘大小 棋盘太大显示异常
            System.out.println("请输入棋盘大小,棋盘要大于10,小于17");
            int size = scanner.nextInt();
            if (size < 10 || size > 17) {
                System.out.println("你输入的棋盘大小为" + size + ",棋盘要大于10,小于17");
                continue;
            }
            System.out.println("欢迎黑方选手" + blackName + "和白方选手" + whiteName + "进行双人五子棋对战");

            //打印棋盘
            int[][] chessboard = new int[size][size];
            StringBuilder head = new StringBuilder("\t");
            for (int j = 0; j < size; j++) {
                head.append(j + 1)
                    .append("\t");
            }
            System.out.println(head);
            for (int i = 0; i < size; i++) {
                StringBuilder line = new StringBuilder();
                line.append(i + 1);
                for (int j = 0; j < size; j++) {
                    line.append("\t");
                    if (chessboard[i][j] == 1) {
                        line.append('○');
                    } else if (chessboard[i][j] == -1) {
                        line.append('●');
                    } else if (chessboard[i][j] == 2) {
                        line.append('□');
                    } else if (chessboard[i][j] == -2) {
                        line.append('■');
                    } else {
                        line.append(' ');
                    }
                }
                line.append("\t");
                line.append(i + 1);
                System.out.println(line);
            }
            System.out.println(head);

            boolean hasWinner = false;
            //currentRole -1 是黑 1 是白
            //roleNames[] roleNames[0] 是黑 roleNames[1] 是白
            int currentRole = -1;
            while (!hasWinner) {
                //选手下棋
                System.out.println(roleNames[currentRole > 0 ? 1 : 0] + "落子。");
                System.out.println("请输入落子的行:");
                int line = scanner.nextInt();
                if (line < 1 || line > size) {
                    System.out.println("行" + line + "超出了棋盘范围");
                    continue;
                }
                System.out.println("请输入落子的列:");
                int column = scanner.nextInt();
                if (column < 1 || column > size) {
                    System.out.println("列" + column + "超出了棋盘范围");
                    continue;
                }
                if (chessboard[line - 1][column - 1] != 0) {
                    System.out.println("行" + line + "列" + column + "处已经有子,请重新落子");
                    continue;
                }
                //当前落子设置成 黑子-2,白子2
                //历史落子设置成 黑子-1,白子1
                chessboard[line - 1][column - 1] = currentRole * 2;

                //打印棋盘
                System.out.println(head);
                for (int i = 0; i < size; i++) {
                    StringBuilder newline = new StringBuilder();
                    newline.append(i + 1);
                    for (int j = 0; j < size; j++) {
                        newline.append("\t");
                        if (chessboard[i][j] == 1) {
                            newline.append('○');
                        } else if (chessboard[i][j] == -1) {
                            newline.append('●');
                        } else if (chessboard[i][j] == 2) {
                            newline.append('□');
                        } else if (chessboard[i][j] == -2) {
                            newline.append('■');
                        } else {
                            newline.append(' ');
                        }
                    }
                    newline.append("\t");
                    newline.append(i + 1);
                    System.out.println(newline);
                }
                System.out.println(head);

                //判断胜负 横竖撇捺四个方向满五子即为胜利,不考虑禁手
                int[][] checkDirection = new int[][] {{1, 0}, {0, 1}, {1, 1}, {1, -1}};
                //依次判断横竖撇捺四种情况
                for (int i = 0; i < checkDirection.length && !hasWinner; i++) {
                    int sum = 1;
                    //两个方向
                    for (int j = 0; j < 2 && !hasWinner; j++) {
                        int x = line - 1;
                        int y = column - 1;

                        checkDirection[i][0] *= -1;
                        checkDirection[i][1] *= -1;
                        while (sum < 5) {
                            x = x + checkDirection[i][0];
                            y = y + checkDirection[i][1];
                            if (x >= 0 && x < size && y >= 0 && y < size && chessboard[x][y] == currentRole) {
                                //棋盘范围内,且与当前落子同一阵营
                                sum++;
                            } else {
                                break;
                            }
                        }
                        if (sum == 5) {
                            hasWinner = true;
                        }
                    }
                }
                if (hasWinner) {
                    grade[currentRole > 0 ? 1 : 0]++;
                    System.out.println(roleNames[currentRole > 0 ? 1 : 0] + "胜出!");
                }
                //最新移动改成默认旗子
                chessboard[line - 1][column - 1] = currentRole;
                //切换对手
                currentRole = -currentRole;
            }
            System.out.println("********************************************************");
            System.out.println(roleNames[0] + "胜出" + grade[0] + "次," + roleNames[1] + "胜出" + grade[1] + "次。");
            System.out.println("********************************************************");
            System.out.println("是否再来一盘? (Y继续,任意键退出)");
            if (!"Y".equalsIgnoreCase(scanner.next())) {
                play = false;
            }
        }
    }
}