五子棋:不会下五子棋也没关系,会用Java写五子棋就行

关注公号"微澜网络"获取完整源代码!

效果展示:

目录

效果展示:

导语:

游戏介绍:

程序设计:

1.游戏规则和功能:

2.用户界面设计:

3.程序架构设计:

4.可扩展性和灵活性:

5.用户体验:

6.测试和优化:

开发步骤:

1.绘制主体框架

2.编写按钮事件类

3.编写棋盘类包含棋子画法

4.重新开始、悔棋功能

(1)重新开始游戏

(2)悔棋

​​​​​​​5.项目结构

结语:


导语:

五子棋,一种古老而智慧的棋类游戏,深受广大棋友的喜爱。今天,我们将以一种全新的方式------使用Java编程语言,来探索五子棋的魅力。无论你是否擅长下棋,只要掌握了Java编程,你就能编写出一款属于自己的五子棋游戏。让我们一起来开发一款属于自己的五子棋游戏吧!

大家好,今天用JavaFX技术写一个单机版的五子棋对战小游戏,文中示例思路清晰、代码完整,适合Java初学者尝试实战,供大家参考。

游戏介绍:

五子棋,又称连珠棋,是一种起源于中国古代的棋类游戏。它以两人对弈,在15×15的棋盘上轮流下棋,通过在棋盘上连成五子或五子以上的直线、斜线或对角线来获得胜利。五子棋看似简单,实则蕴含着丰富的战略和战术,需要玩家具备敏锐的观察力、精准的计算能力和出色的布局能力。

程序设计:

1.游戏规则和功能:

  • 游戏应该符合五子棋的规则,即两名玩家轮流在棋盘上落子,先在横、竖、斜向连成五子的玩家获胜。

  • 提供开始游戏、重新开始、悔棋、退出游戏等功能。

  • 实现胜负判断,当一方获胜或棋盘填满平局时结束游戏。

2.用户界面设计:

  • 使用图形界面或控制台界面,提供友好的用户交互。

  • 显示棋盘、落子情况、玩家信息等。

  • 提供按钮或命令行选项以控制游戏流程,如开始游戏、重新开始、悔棋等。

3.程序架构设计:

  • 使用面向对象的思想,设计棋盘、玩家、游戏控制器等类。

  • 实现游戏逻辑与界面的分离,便于后续维护和扩展。

  • 使用合适的数据结构来表示棋盘状态,例如二维数组。

4.可扩展性和灵活性:

  • 考虑到后续可能的需求变更,设计时应该尽量使代码具有可扩展性和灵活性。

  • 例如,可以支持不同大小的棋盘、不同级别的人机对战、网络对战等扩展功能。

5.用户体验:

  • 确保游戏界面简洁明了,易于上手。

  • 提供合适的提示和反馈,让玩家清晰地了解游戏状态和下一步操作。

6.测试和优化:

  • 进行充分的单元测试和集成测试,确保游戏的稳定性和可靠性。

  • 根据用户反馈和测试结果进行优化,提升游戏性能和用户体验。

基于上述考虑,可以开始设计和实现Java语言的五子棋游戏。在具体实现过程中,可以借助Java图形界面库(JavaFX)或控制台输入输出来实现用户界面,同时利用Java的面向对象特性来组织代码结构,实现游戏逻辑。

开发步骤:

1.绘制主体框架

使用JavaFX绘制了一个基本框架。只包含了UI的绘制,主要内容包括面板对象、重新开始游戏按钮、悔棋按钮,没有添加具体的按钮功能。

java 复制代码
@Override
    public void start(Stage primaryStage) {
        BorderPane root = new BorderPane();

        // 创建棋盘面板对象
        GridPane boardPane = new GridPane();
        // 设置棋盘面板样式
        boardPane.setStyle("-fx-background-color: #FFE4B5; -fx-padding: 10;");

        // 创建重新开始游戏按钮
        Button restartButton = new Button("重新开始游戏");
        // 设置重新开始游戏按钮样式
        restartButton.setStyle("-fx-font-size: 14;");

        // 创建悔棋按钮
        Button undoButton = new Button("悔棋");
        // 设置悔棋按钮样式
        undoButton.setStyle("-fx-font-size: 14;");

        // 创建底部按钮面板
        BorderPane bottomPane = new BorderPane();
        bottomPane.setLeft(restartButton);
        bottomPane.setRight(undoButton);
        // 设置底部按钮面板样式
        bottomPane.setStyle("-fx-background-color: #F5F5F5; -fx-padding: 10;");

        // 将棋盘面板和底部按钮面板添加到主面板中
        root.setCenter(boardPane);
        root.setBottom(bottomPane);

        // 设置主场景
        Scene scene = new Scene(root, 600, 600);

        // 设置主舞台标题
        primaryStage.setTitle("微澜五子棋游戏");
        // 设置主舞台场景
        primaryStage.setScene(scene);
        // 显示主舞台
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }

​​​代码效果展示如下:

2.编写按钮事件类

用来监听重新开始游戏按钮和悔棋按钮,并在点击时作出相应的动作。这个类需要在主程序中进行实例化,并设置给对应的按钮。

java 复制代码
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.control.Button;

public class ButtonEventHandler implements EventHandler<ActionEvent> {
    private GomokuGameUI gameUI; // 引用游戏UI对象

    public ButtonEventHandler(GomokuGameUI gameUI) {
        this.gameUI = gameUI;
    }

    @Override
    public void handle(ActionEvent event) {
        if (event.getSource() instanceof Button) {
            Button clickedButton = (Button) event.getSource();
            if (clickedButton.getText().equals("重新开始游戏")) {
                // 处理重新开始游戏按钮点击事件
                System.out.println("重新开始游戏按钮被点击了");
                // 添加重新开始游戏的逻辑
            } else if (clickedButton.getText().equals("悔棋")) {
                // 处理悔棋按钮点击事件
                System.out.println("悔棋按钮被点击了");
                // 添加悔棋的逻辑
            }
        }
    }
}

​​​​​​ 创建了一个 ButtonEventHandler 类的实例,并将游戏UI对象传递给它。然后,我们将这个事件处理类与重新开始游戏按钮和悔棋按钮进行关联,以便在点击按钮时执行相应的动作。补充UI对象内容如下:

java 复制代码
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;

public class GomokuGameUI extends Application {

    @Override
    public void start(Stage primaryStage) {
        BorderPane root = new BorderPane();

        // 其他代码

        // 创建按钮事件处理类,并将游戏UI对象传入
        ButtonEventHandler buttonHandler = new ButtonEventHandler(this);

        // 将按钮事件处理类设置给重新开始游戏按钮和悔棋按钮
        restartButton.setOnAction(buttonHandler);
        undoButton.setOnAction(buttonHandler);
        //其他代码
    }

    public static void main(String[] args) {
        launch(args);
    }
}

代码效果展示如下:

3.编写棋盘类包含棋子画法

下面是一个简单的棋盘类,用于绘制五子棋的棋盘并管理棋子的放置。在这个棋盘类中,我们将棋盘表示为一个二维数组,用于存储棋子的位置和类型信息。我在这里添加了放置棋子和检查胜利的方法。

java 复制代码
import javafx.collections.ObservableList;
import javafx.event.EventHandler;
import javafx.scene.Node;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Rectangle;

public class GomokuBoardPane extends Pane {
    public static final int BOARD_SIZE = 15;
    public static final int CELL_SIZE = 40;

    private char[][] board;

    //定义玩家信息
    private char currentPlayer;
    //在 GomokuBoardPane 类中添加一个变量来跟踪游戏是否结束
    private boolean gameEnded;

    public GomokuBoardPane() {
        board = new char[BOARD_SIZE][BOARD_SIZE];
        currentPlayer = 'X'; // 初始化为玩家 X
        initializeBoard();
        setOnMouseClicked(new BoardClickHandler());

    }

    public void initializeBoard() {
        //清屏
        getChildren().clear();

        for (int row = 0; row < BOARD_SIZE; row++) {
            for (int col = 0; col < BOARD_SIZE; col++) {
                board[row][col] = '-';
                Rectangle cell = new Rectangle(CELL_SIZE, CELL_SIZE);
                cell.setFill(Color.BISQUE);
                cell.setStroke(Color.BLACK);
                cell.setX(20 + col * CELL_SIZE);
                cell.setY(20 + row * CELL_SIZE);
                getChildren().add(cell);

            }
        }
    }
    
    public void setGameEnded(boolean b) {
        gameEnded = b;
    }

    public void setCurrentPlayer(char x) {
        currentPlayer = x;
    }

    private class BoardClickHandler implements EventHandler<MouseEvent> {
        @Override
        public void handle(MouseEvent event) {

            if (!gameEnded) {
                int col = (int) (event.getX() / CELL_SIZE);
                int row = (int) (event.getY() / CELL_SIZE);
                if (isValidMove(row, col)) {
                    placePiece(currentPlayer, row, col);
                    // 在此处添加其他玩家的逻辑(例如交替落子、检查胜利等)
                    if (checkWin(row, col)) {
                        System.out.println("Player " + currentPlayer + " wins!");
                        // 在此处添加游戏结束的逻辑,例如显示胜利信息、禁用棋盘等
                        // 在 handle 方法中调用 endGame 方法
                        endGame(currentPlayer);
                    } else {
                        currentPlayer = (currentPlayer == 'X') ? 'O' : 'X'; // 切换玩家
                    }
                }
            }
        }
    }

    private boolean isValidMove(int row, int col) {
        return board[row][col] == '-';
    }

    private void placePiece(char type, int row, int col) {
        board[row][col] = type;
        Circle piece = new Circle(CELL_SIZE / 2, type == 'X' ? Color.BLACK : Color.WHITE);
        piece.setCenterX(col * CELL_SIZE + CELL_SIZE / 2);
        piece.setCenterY(row * CELL_SIZE + CELL_SIZE / 2);
        getChildren().add(piece);
    }

    public boolean checkWin(int row, int col) {
        char piece = board[row][col];
        // 检查横向
        int count = 1;
        for (int i = col - 1; i >= 0 && board[row][i] == piece; i--) {
            count++;
        }
        for (int i = col + 1; i < BOARD_SIZE && board[row][i] == piece; i++) {
            count++;
        }
        if (count >= 5) return true;

        // 检查纵向
        count = 1;
        for (int i = row - 1; i >= 0 && board[i][col] == piece; i--) {
            count++;
        }
        for (int i = row + 1; i < BOARD_SIZE && board[i][col] == piece; i++) {
            count++;
        }
        if (count >= 5) return true;

        // 检查左上到右下斜向
        count = 1;
        for (int i = row - 1, j = col - 1; i >= 0 && j >= 0 && board[i][j] == piece; i--, j--) {
            count++;
        }
        for (int i = row + 1, j = col + 1; i < BOARD_SIZE && j < BOARD_SIZE && board[i][j] == piece; i++, j++) {
            count++;
        }
        if (count >= 5) return true;

        // 检查右上到左下斜向
        count = 1;
        for (int i = row - 1, j = col + 1; i >= 0 && j < BOARD_SIZE && board[i][j] == piece; i--, j++) {
            count++;
        }
        for (int i = row + 1, j = col - 1; i < BOARD_SIZE && j >= 0 && board[i][j] == piece; i++, j--) {
            count++;
        }
        return count >= 5;
    }

    // 在游戏结束时调用此方法
    private void endGame(char winner) {
        gameEnded = true;
        System.out.println("Player " + winner + " wins!");
        // 在这里添加显示胜利信息的逻辑
    }
}

​​​​​​​将主框架里面的初始画棋盘内容替换,ButtonEventHandler 类中的构造方法增加一种。

java 复制代码
 // 创建棋盘对象
    GomokuBoardPane boardPane = new GomokuBoardPane();
    // 将棋盘添加到主面板中
    root.setCenter(boardPane);
    
    
    // 创建按钮事件处理类,并将游戏UI对象和棋盘对象传入
    ButtonEventHandler buttonHandler = new ButtonEventHandler(this, boardPane);

​​​​​​​代码效果展示如下:

因为判断的基本方法我们已经处理过,到这一步就可以进行游戏。

4.重新开始、悔棋功能

(1)重新开始游戏

机器重启即可,考虑是直接重画一次棋盘最方便。

java 复制代码
// 重新开始游戏的逻辑
boardPane.initializeBoard();//重画棋盘
boardPane.setCurrentPlayer('X');//设置玩家
boardPane.setGameEnded(false);//标记游戏状态

​​​​​​​**(2)悔棋**

画棋子的懒省事没有查居中内容。现在计算最后一个棋子的坐标时,需要吧坐标减去20再更新状态。注意切换玩家

java 复制代码
// 移除最后一步棋子
    public void undoMove() {
        ObservableList<Node> children = getChildren();
        int lastPieceIndex = children.size() - 1; // 获取最后一个棋子的索引
        if (lastPieceIndex >= 0) {
            Node lastPiece = children.get(lastPieceIndex); // 获取最后一个棋子节点
            if (lastPiece instanceof Circle) {
                Circle lastCircle = (Circle) lastPiece;
                int row = (int) ((lastCircle.getCenterY() - 20.0) / CELL_SIZE);
                int col = (int) ((lastCircle.getCenterX() - 20.0) / CELL_SIZE);
                // 移除最后一个棋子节点
                children.remove(lastPiece);
                // 更新棋盘状态
                board[row][col] = '-';
                // 切换当前玩家
                currentPlayer = (currentPlayer == 'X') ? 'O' : 'X';
            }
        }
    }

​​​​​​​5.项目结构

项目到这里就基本完成了。主要实现了玩家对战,重新开始,悔棋等操作,结构简单。适合初学者学习。

结语:

本次开发过程多曲折。本身就不熟悉JavaFx图形库,想着了解一下新内容,结果不知不觉踩了不少坑。棋盘类从GridPane到Pane,也是有一些意想不到事情发生。做事情之前尤其是开发内容应该提前预估一下可能遇到的问题。这次问题好好记录,保证下次不犯类似的问题。(后续有机会继续改进这个项目

需要完整源码参考的请扫码:

相关推荐
你怎么知道我是队长15 分钟前
C语言---缓冲区
c语言·开发语言
一勺菠萝丶24 分钟前
PDF24 转图片出现“中间横线”的根本原因与终极解决方案(DPI 原理详解)
java
姓蔡小朋友28 分钟前
Unsafe类
java
一只专注api接口开发的技术猿41 分钟前
如何处理淘宝 API 的请求限流与数据缓存策略
java·大数据·开发语言·数据库·spring
superman超哥42 分钟前
Rust 异步递归的解决方案
开发语言·后端·rust·编程语言·rust异步递归
荒诞硬汉42 分钟前
对象数组.
java·数据结构
期待のcode44 分钟前
Java虚拟机的非堆内存
java·开发语言·jvm
黎雁·泠崖44 分钟前
Java入门篇之吃透基础语法(二):变量全解析(进制+数据类型+键盘录入)
java·开发语言·intellij-idea·intellij idea
仙俊红1 小时前
LeetCode484周赛T4
java