You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

二维整数数组值丢失求助:GameSetting赋值后仅保留最后一个值

问题:多个按钮实例独立操作不同的GameSetting数组,导致数据丢失

我定义了GameSetting类管理3x3游戏数组,提供赋值和获取数组的方法:

public class GameSetting {

private int[][] gameArray;

public GameSetting(){
    gameArray = new int[3][3];
}

public void setValue(int i, int j, int value){
    this.gameArray[i][j] = value;
}

public int[][] getGameArray(){
    return this.gameArray;
}

但MyButton类中每个按钮实例都创建了独立的GameSetting对象:

public class MyButton extends Button {
    private int x;
    private int y;
    private int k;
    private int g;
    private int coordinateA;
    private int coordinateB;
    private GameSetting gameSettings = new GameSetting(); // 每个按钮新建独立实例

    public MyButton(String name, int x, int y, int k, int g, int coordinateA, int coordinateB) {
        super(name);
        this.setLayoutX(x);
        this.setLayoutY(y);
        this.setPrefHeight(121);
        this.setPrefWidth(121);
        this.setOpacity(0.5);
        this.setCursor(Cursor.CLOSED_HAND);
        this.x = x;
        this.y = y;
        this.k = k;
        this.g = g;
        this.coordinateA = coordinateA;
        this.coordinateB = coordinateB;
    }

    public void clickToPlay() {
        this.setOnAction(event -> {
            Parent parent = this.getParent();

            if(parent instanceof Group){
                ((Group) parent).getChildren().remove(this);

                if(HelloApplication.whichPlayer%2 == 0) {
                    GameImage imageViewCross = new GameImage(HelloApplication.circle, this.k, this.g);
                    gameSettings.setValue(coordinateA, coordinateB, 1);
                    ((Group) parent).getChildren().add(imageViewCross);
                }else{
                    GameImage imageViewCircle = new GameImage(HelloApplication.cross, this.k, this.g);
                    gameSettings.setValue(coordinateA, coordinateB, 2);
                    ((Group) parent).getChildren().add(imageViewCircle);
                }
                HelloApplication.whichPlayer++;
                if(HelloApplication.whichPlayer == 9){
                    int[][] test = gameSettings.getGameArray();
                    for (final int[] is : test) {
                        System.out.println(Arrays.toString(is));
                    }
                }
            }
        });
    }
}

每次点击按钮时,赋值操作都在各自的GameSetting实例中进行,最终只能获取当前按钮实例里的最后一次赋值,其他按钮的操作数据全部丢失。需要让所有按钮共享同一个GameSetting实例,统一操作同一个二维数组。


解决方案

方法1:构造函数注入(推荐,解耦性好)

修改MyButton类,不再内部创建GameSetting实例,而是通过构造函数传入全局唯一的GameSetting对象:

  1. 修改MyButton的成员变量和构造函数:
public class MyButton extends Button {
    private GameSetting gameSettings; // 改为外部传入的成员变量
    // 其他成员变量保持不变

    // 构造函数新增GameSetting参数
    public MyButton(String name, int x, int y, int k, int g, int coordinateA, int coordinateB, GameSetting gameSettings) {
        super(name);
        this.setLayoutX(x);
        this.setLayoutY(y);
        this.setPrefHeight(121);
        this.setPrefWidth(121);
        this.setOpacity(0.5);
        this.setCursor(Cursor.CLOSED_HAND);
        this.x = x;
        this.y = y;
        this.k = k;
        this.g = g;
        this.coordinateA = coordinateA;
        this.coordinateB = coordinateB;
        this.gameSettings = gameSettings; // 接收全局实例
    }

    // clickToPlay方法逻辑不变
}
  1. 在初始化按钮时,传入同一个GameSetting实例:
// 在HelloApplication或初始化入口创建全局唯一实例
GameSetting globalGameSetting = new GameSetting();

// 创建所有按钮时都传入该实例
MyButton btn00 = new MyButton("btn00", 0, 0, 0, 0, 0, 0, globalGameSetting);
MyButton btn01 = new MyButton("btn01", 121, 0, 121, 0, 0, 1, globalGameSetting);
// 其他按钮同理

方法2:给GameSetting实现单例模式

让GameSetting自身保证全局只有一个实例,所有按钮都获取该单例操作数组:

修改GameSetting为单例:

public class GameSetting {
    private int[][] gameArray;
    private static GameSetting instance;

    // 私有构造函数,禁止外部直接实例化
    private GameSetting(){
        gameArray = new int[3][3];
    }

    // 全局获取唯一实例的方法
    public static GameSetting getInstance(){
        if(instance == null){
            instance = new GameSetting();
        }
        return instance;
    }

    // setValue和getGameArray方法保持不变
    public void setValue(int i, int j, int value){
        this.gameArray[i][j] = value;
    }

    public int[][] getGameArray(){
        return this.gameArray;
    }
}

修改MyButton获取单例实例:

public class MyButton extends Button {
    private GameSetting gameSettings;

    public MyButton(String name, int x, int y, int k, int g, int coordinateA, int coordinateB) {
        super(name);
        // 其他初始化代码不变
        this.gameSettings = GameSetting.getInstance(); // 获取全局单例
    }

    // clickToPlay方法逻辑不变
}

方法3:使用静态数组(简单直接,灵活性差)

把GameSetting中的数组改为静态变量,让所有实例共享同一个数组:

修改GameSetting类:

public class GameSetting {
    // 改为静态数组,所有实例共享
    private static int[][] gameArray = new int[3][3];

    public GameSetting(){
        // 无需再初始化数组,静态变量已默认初始化
    }

    public void setValue(int i, int j, int value){
        gameArray[i][j] = value;
    }

    public int[][] getGameArray(){
        return gameArray;
    }
}

这种方式下,即使每个MyButton创建自己的GameSetting实例,操作的都是同一个静态数组,数据不会丢失。但静态变量扩展性差,后续如果需要支持多局游戏场景,该方式不适用。


内容的提问来源于stack exchange,提问作者Karlz-Bandz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 09:25:42