Loading...

五子棋

流程图

包截图

GUI界面

主菜单界面

运行五子棋程序,出现开始界面,如下图所示

代码如下:

import javafx.application.Application;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.*;
import javafx.stage.Stage;


public class BeginStage extends Application {


    final Button btBeginGame = new Button("开始游戏");
    final Button btQuitGame = new Button("退出游戏");
    Pane pane1 = new Pane();//开始面板
    Scene scene1 = new Scene(pane1);//开始界面
    Stage stage1 = new Stage();//游戏界面

    public BeginStage(){
        //设置开始界面
        //绑定“开始游戏”的位置
        btBeginGame.layoutYProperty().bind(pane1.heightProperty().divide(1.1));
        btBeginGame.layoutXProperty().bind(pane1.widthProperty().divide(4));
        btBeginGame.setScaleX(1.5);
        btBeginGame.setScaleY(1.5);
        btBeginGame.setStyle("-fx-background-radius:15;");

        //绑定“退出游戏”的位置
        btQuitGame.layoutYProperty().bind(pane1.heightProperty().divide(1.1));
        btQuitGame.layoutXProperty().bind(pane1.widthProperty().divide(1.58));
        btQuitGame.setScaleX(1.5);
        btQuitGame.setScaleY(1.5);
        btQuitGame.setStyle("-fx-background-radius:15;");

        //设置开始界面的背景图片
        ImageView beginBack = new ImageView(new Image(getClass().getResourceAsStream("sample/5.png")));
        beginBack.fitHeightProperty().bind(pane1.heightProperty());
        beginBack.fitWidthProperty().bind(pane1.widthProperty());

        pane1.getChildren().addAll(beginBack,btBeginGame,btQuitGame);

        stage1.setTitle("五子棋");
        stage1.setScene(scene1);
        //开始界面按钮添加事件处理
        btBeginGame.setOnAction(e -> {
            ChooseStage chooseStage = new ChooseStage();
            chooseStage.stage.show();
            stage1.close();
        });
        btQuitGame.setOnAction(e ->{
                    stage1.close();
                }
        );
    }
    public void start(Stage stage){
       BeginStage beginStage = new BeginStage();
       beginStage.stage1.show();
    }

}

模式选择界面

点击开始游戏后,出现主菜单,以及对战选项,如下图所示

效果展示

代码如下:

import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;

public class ChooseStage {
    private Button btDouble = new Button("双人对战");
    private Button btOne = new Button("人机对战");
    private Button btNet = new Button("联机对战");
    private Button btServer = new Button("创建服务器");
    private Button btQuit = new Button("返回");
    ImageView backGround = new ImageView(new Image(getClass().getResourceAsStream("sample/52.jpg")));

    private Pane pane = new Pane();
    public Stage stage = new Stage();
    Scene scene = new Scene(pane);
    public ChooseStage(){
        pane.getChildren().addAll(backGround,btDouble,btNet,btOne,btServer,btQuit);
        backGround.fitHeightProperty().bind(pane.heightProperty());
        backGround.fitWidthProperty().bind(pane.widthProperty());

        btDouble.setLayoutX(300);
        btDouble.setLayoutY(300);
        btDouble.setScaleX(1.3);
        btDouble.setScaleY(1.3);

        btNet.setLayoutX(300);
        btNet.setLayoutY(360);
        btNet.setScaleX(1.3);
        btNet.setScaleY(1.3);

        btOne.setLayoutX(300);
        btOne.setLayoutY(420);
        btOne.setScaleX(1.3);
        btOne.setScaleY(1.3);

        btServer.setLayoutX(293);
        btServer.setLayoutY(480);
        btServer.setScaleX(1.3);
        btServer.setScaleY(1.3);

        btQuit.setLayoutX(313);
        btQuit.setLayoutY(540);
        btQuit.setScaleX(1.3);
        btQuit.setScaleY(1.3);

        btDouble.setOnAction(event -> {

        });

        btNet.setOnMouseClicked(event -> {

        });

        btOne.setOnMouseClicked(event -> {

        });

        btQuit.setOnMouseClicked(event -> {
            stage.close();
            BeginStage beginStage = new BeginStage();
            beginStage.stage1.show();
        });

        btDouble.setOnMouseClicked(event -> {

        });

        stage.setScene(scene);
        stage.setTitle("五子棋");
        stage.setResizable(false);

    }
}

棋盘初始化

对原paint代码进行覆盖,进行导入背景图、画出棋盘线条、画出棋子、标出最新下的棋子的位置等操作

代码如下:

计算出每个格子的边长,画出横线纵线,画出棋盘,并表明棋盘中的五点

原始代码为利用java工具画出棋子原型,再对棋子进行填充,代码如下

由于运行之后棋子边界并不光滑,视觉效果不好因此改进代码如下

利用棋子图片原型,直接将图面贴至棋盘,使视觉效果更佳

对战界面选项设置

首先创建游戏界面窗口和菜单栏,并创建菜单栏中的“选项”菜单,把“重玩一盘”、“玩家1先手”、“玩家2先手”加入“选项”下拉项中

处理鼠标点击事件

利用鼠标监听事件e交替监听玩家一与玩家二的落子情况,分别下出黑子与白字

public void mouseClicked(MouseEvent e){
				//鼠标点击引发下棋事件
				if(flag) {
					play(e);
					flag=false;
				}
				else {
					play2(e);
					flag=true;
				}
				
				
			}

人机对战

机器落子

机器落子,采用五元组评分算法,对处于空白处的棋位进行判定,最后判断分数最高的棋子位置.

for(int i = 0; i < 15; i++){
			for(int j = 0; j < 15; j++){
				if(chessboard[i][j] == 0 && score[i][j] > maxScore){
					goalX = i;
					goalY = j;
					maxScore = score[i][j];
				}
			}
		}		

由于考虑到在下棋子第一步时,人类落子后周围八个位置的分值皆相同,防止出现机器人每次在人类落子之后落子位置总是相同,因此进行如下改进:若是有多个棋子位置分数相同,则相应位置储存再数组中,随机抽取一个位置进行落子

五元组评分算法(通过对每一个位置进行评分,落子在分数最高的位置)

                //既有人类落子,又有机器落子,判分为0
		if(humanChessmanNum > 0 && machineChessmanNum > 0){
			return 0;
		}
		//2.全部为空,没有落子,判分为7
		if(humanChessmanNum == 0 && machineChessmanNum == 0){
			return 7;
		}
		//3.机器落1子,判分为35
		if(machineChessmanNum == 1){
			return 35;
		}
		//4.机器落2子,判分为800
		if(machineChessmanNum == 2){
			return 800;
		}
		//5.机器落3子,判分为15000
		if(machineChessmanNum == 3){
			return 15000;
		}
		//6.机器落4子,判分为800000
		if(machineChessmanNum == 4){
			return 800000;
		}
		//7.人类落1子,判分为15
		if(humanChessmanNum == 1){
			return 15;
		}
		//8.人类落2子,判分为400
		if(humanChessmanNum == 2){
			return 400;
		}
		//9.人类落3子,判分为1800
		if(humanChessmanNum == 3){
			return 1800;
		}
		//10.人类落4子,判分为100000
                if(humanChessmanNum == 4){
			return 100000;
		}

双人对战

方法``一

(基本操作同上)
判断胜利的条件(八个方向)

方法二(说明:由于一开始用swing写的棋子以及界面视觉效果不佳,因此考虑尝试采用javafx编写双人对战的代码,因为javafx落子时,可以直接将棋子设置为一个按钮,点击后不设置操作,相比于swing直接画棋子来说,视觉效果要好一点,但后期操作后可以将网上扣取的图片作为棋子利用swing贴在棋盘上,统一操作后采用了方法一)

判断胜利条件基本相同,稍有不同的地方在于界面的建立

posted @ 2021-01-28 20:14  孤海  阅读(192)  评论(1编辑  收藏  举报