Commit 515fef13 authored by 刘家荣's avatar 刘家荣 💬
Browse files

fix(save): didn't write save

parent 2b8b28ea
Loading
Loading
Loading
Loading
+98 −21
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@ import com.alibaba.fastjson2.JSONObject;
import com.formdev.flatlaf.FlatLightLaf;
import model.History;
import model.Room;
import model.dataType.ChessColor;
import model.dataType.GameType;
import model.game.Game;
import network.Client;
@@ -26,6 +27,7 @@ import java.io.IOException;
import java.net.UnknownHostException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.logging.Logger;
@@ -36,59 +38,83 @@ import java.util.logging.Logger;
public class AppController {
	public static Logger logger = Logger.getLogger("default-logger");

	// 静态变量,保存历史记录和游戏状态
	private static History savedHistory;

	private static Game savedGame;

	// 存档文件路径
	public static final String savePath = "res/save/save.json";

	/**
	 * 构造函数
	 */
	public AppController() {

	}

	/**
	 * 获取保存的历史记录
	 *
	 * @return 历史记录对象
	 */
	public static History getSavedHistory() {
		return savedHistory;
	}

	/**
	 * 获取保存的游戏状态
	 *
	 * @return 游戏状态对象
	 */
	public static Game getSavedGame() {
		return savedGame;
	}


	/**
	 * 进入房间选择页面
	 *
	 * @throws ExecutionException
	 * @throws InterruptedException
	 * @throws ExecutionException   异常信息
	 * @throws InterruptedException 异常信息
	 */
	public static void goRooms() throws ExecutionException, InterruptedException {
		while (true) {
			// 创建房间选择页面的future
			CompletableFuture<FrameReturnType<RoomFrame>> roomFuture = new CompletableFuture<>();
			// 异步执行创建房间选择页面
			SwingUtilities.invokeLater(() -> {
				RoomFrame.instance = new RoomFrame(roomFuture);
				RoomFrame.instance.setVisible(true);
			});
			// 获取房间选择页面返回的结果
			FrameReturnType<RoomFrame> result = roomFuture.get();
			// 关闭房间选择页面
			RoomFrame.instance.setVisible(false);
			RoomFrame.instance.dispose();
			// 根据返回结果进入相应模式的游戏
			if (result instanceof goOnline result1) {
				goOnlineGame(result1.onlineMode, result1.room);
			} else return;
			} else {
				return;
			}
		}
	}

	/**
	 * 进入本地游戏
	 *
	 * @throws ExecutionException
	 * @throws InterruptedException
	 * @param useSave  是否使用保存的存档
	 * @param type 游戏类型
	 * @throws ExecutionException   异常信息
	 * @throws InterruptedException 异常信息
	 */
	public static void goOfflineGame(boolean useSave, GameType type) throws ExecutionException, InterruptedException {
		// 创建游戏页面的future
		CompletableFuture<FrameReturnType<ChessGameFrame>> gameFuture = new CompletableFuture<>();
		// 异步执行创建游戏页面
		SwingUtilities.invokeLater(() -> {
			ChessGameFrame.instance = new ChessGameFrame(gameFuture);
			ChessGameFrame.instance.setVisible(true);
		});
		// 根据useSave参数选择使用保存的存档还是重新创建存档
		if (useSave) {
			Game.instance = savedGame;
			History.instance = savedHistory;
@@ -97,7 +123,16 @@ public class AppController {
			History.instance = new History(Game.instance.clone());
			write(savePath);
		}
		// 获取游戏页面返回的结果
		gameFuture.get();
		// 如果游戏结束,重新创建游戏对象和历史记录对象
		if (Game.instance.winnerColor != ChessColor.NONE) {
			Game.instance = new Game(type);
			History.instance = new History(Game.instance.clone());
		}
		// 保存游戏状态
		write(savePath);
		// 关闭游戏页面
		ChessGameFrame.instance.setVisible(false);
		ChessGameFrame.instance.dispose();
	}
@@ -105,43 +140,60 @@ public class AppController {
	/**
	 * 进入联机游戏
	 *
	 * @throws ExecutionException
	 * @throws InterruptedException
	 * @param onlineMode 在线模式
	 * @param room       房间信息
	 * @throws ExecutionException   异常信息
	 * @throws InterruptedException 异常信息
	 */
	public static void goOnlineGame(OnlineStatus onlineMode, Room room) throws ExecutionException, InterruptedException {
		// 创建游戏页面的future
		CompletableFuture<FrameReturnType<ChessGameFrame>> gameFuture = new CompletableFuture<>();
		// 创建新的游戏对象和历史记录对象
		Game.instance = new Game(GameType.ONLINE);
		History.instance = new History(Game.instance.clone());
		// 根据在线模式选择连接服务器还是客户端
		if (onlineMode == OnlineStatus.SERVER_WAITING) {
			try {
				// 启动服务器
				Server.start();
				// 创建棋盘游戏页面
				SwingUtilities.invokeLater(() -> {
					ChessGameFrame.instance = new ChessGameFrame(gameFuture);
					ChessGameFrame.instance.setVisible(true);
				});
			} catch (UnknownHostException e) {
				// 连接失败,完成future并提示用户
				gameFuture.complete(new exitGame());
				JOptionPane.showMessageDialog(null, "房间创建失败", "提示", JOptionPane.WARNING_MESSAGE);
			}
		} else {
			boolean isPlayer = onlineMode == OnlineStatus.CLIENT_PLAYING;
			// 连接服务器或客户端
			Client.connect(room.ip, isPlayer ? room.playerPort : room.watcherPort, isPlayer,
					() -> {
						// 异步执行创建棋盘游戏页面
						SwingUtilities.invokeLater(() -> {
							ChessGameFrame.instance = new ChessGameFrame(gameFuture);
							ChessGameFrame.instance.setVisible(true);
						});
						// 游戏页面创建完成后,设置游戏和历史记录对象
						Game.instance = new Game(GameType.ONLINE);
						History.instance = new History(Game.instance.clone());
					},
					() -> {
						// 连接失败,完成future并提示用户
						gameFuture.complete(new exitGame());
						JOptionPane.showMessageDialog(null, "连接失败", "提示", JOptionPane.WARNING_MESSAGE);
					},
					() -> {
						// 连接断开,完成future并提示用户
						gameFuture.complete(new exitGame());
						JOptionPane.showMessageDialog(null, "连接已断开", "提示", JOptionPane.WARNING_MESSAGE);
					});
		}
		// 获取棋盘游戏页面返回的结果
		gameFuture.get();
		// 关闭棋盘游戏页面
		ChessGameFrame.instance.setVisible(false);
		ChessGameFrame.instance.dispose();
	}
@@ -149,13 +201,15 @@ public class AppController {
	/**
	 * 年度大无语事件之JSON能做的事JSONObject不能做
	 *
	 * @param path
	 * @throws IOException
	 * @throws JSONException
	 * @param path 文件路径
	 * @throws IOException   IO异常信息
	 * @throws JSONException JSON异常信息
	 */
	public static void read(String path) throws IOException, JSONException {
		try {
			// 读取JSON文件
			JSONObject jsonObject = JSONObject.parse(Files.readString(Path.of(path)));
			// 解析JSON文件,将数据赋值给游戏对象和历史记录对象
			savedGame = JSON.parseObject(jsonObject.getJSONObject("Game").toString(), Game.class);
			savedHistory = JSON.parseObject(jsonObject.getJSONObject("History").toString(), History.class);
		} catch (JSONException | IOException | IllegalArgumentException e) {
@@ -164,14 +218,24 @@ public class AppController {
		}
	}

	/**
	 * 写入JSON文件
	 *
	 * @param path 文件路径
	 * @return 是否成功写入
	 */
	public static boolean write(String path) {
		System.out.println("write");
		try {
			// 创建JSONObject对象
			JSONObject jsonObject = new JSONObject();
			// 将游戏对象和历史记录对象转换为JSON字符串,存入JSONObject对象中
			jsonObject.put("Game", Game.instance);
			jsonObject.put("History", History.instance);
			// 创建文件并写入JSONObject对象
			File save = new File(path);
			save.createNewFile();   // 不覆盖已有存档
			Files.writeString(Path.of(path), JSON.toJSONString(jsonObject));
			save.createNewFile();
			Files.writeString(Path.of(path), JSON.toJSONString(jsonObject), StandardOpenOption.TRUNCATE_EXISTING);
			read(path);
			return true;
		} catch (IOException | JSONException e) {
@@ -181,8 +245,13 @@ public class AppController {
		}
	}

	/**
	 * 主方法
	 *
	 * @param args 命令行参数
	 */
	public static void main(String[] args) {

		// 读取存档
		try {
			read(savePath);
		} catch (IOException | JSONException e) {
@@ -191,28 +260,36 @@ public class AppController {
			savedHistory = null;
		}

		// 启动
		try {
			// 初始化FlatLightLaf
			FlatLightLaf.setup();
			while (true) {
				// AppFrame
				// 创建主界面窗体,传递future,等待窗体在完成后返回结果
				CompletableFuture<FrameReturnType<AppFrame>> appFuture = new CompletableFuture<>();
				SwingUtilities.invokeLater(() -> {
					AppFrame.instance = new AppFrame(appFuture);
				});
				// 获取主界面返回的结果
				FrameReturnType<AppFrame> result = appFuture.get();
				// 关闭主界面窗体
				AppFrame.instance.setVisible(false);
				AppFrame.instance.dispose();
				// 根据返回结果选择进入相应界面
				if (result instanceof goOffline result1) {
					goOfflineGame(result1.useSave, result1.gameType);
				} else if (result instanceof goRooms result1) {
					goRooms();
				} else break;
				} else {
					break;
				}

			}

		} catch (InterruptedException | ExecutionException e) {
			throw new RuntimeException(e);
		}
		System.exit(0);

	}

}
+8 −8
Original line number Diff line number Diff line
@@ -95,14 +95,14 @@ public enum ChessClickController {
		ChessGameFrame.getStatusLabel().setText(String.format("%s's TURN", Game.instance.getCurrentColor().getName()));
		ChessGameFrame.instance.refreshScore(0);
		ChessGameFrame.instance.refreshScore(1);
		if (Game.instance.getScoreboard()[0] >= 60) {
		if (Game.instance.winnerColor != ChessColor.NONE) {
			if (Game.instance.winnerColor == ChessColor.RED) {
				JOptionPane.showMessageDialog(null, "红方胜利", "提示", JOptionPane.WARNING_MESSAGE);
				ChessGameFrame.instance.exit();
		}
		if (Game.instance.getScoreboard()[1] >= 60) {
			} else {
				JOptionPane.showMessageDialog(null, "黑方胜利", "提示", JOptionPane.WARNING_MESSAGE);
				ChessGameFrame.instance.exit();

			}
		}
	}
}
+18 −1
Original line number Diff line number Diff line
@@ -26,6 +26,8 @@ public class Game implements Cloneable {

	public final ChessColor hostColor;  //服务器颜色,或者人机对战中人类颜色

	public ChessColor winnerColor = ChessColor.NONE;

	public Chessboard getChessboard() {
		return chessboard;
	}
@@ -63,6 +65,17 @@ public class Game implements Cloneable {
		this.scoreboard = new int[]{0, 0};
	}

	// 判断胜负
	public void judgeWinner() {
		if (scoreboard[0] > 60) {
			winnerColor = ChessColor.RED;
		} else if (scoreboard[1] > 60) {
			winnerColor = ChessColor.BLACK;
		} else {
			winnerColor = ChessColor.NONE;
		}
	}

	/**
	 * 不知道吃子第三个参数是啥的, 随便填(
	 */
@@ -87,6 +100,7 @@ public class Game implements Cloneable {
				ai.start();
			}
		}
		judgeWinner();
		return res;
	}

@@ -144,7 +158,10 @@ public class Game implements Cloneable {
					chessboard.getSquareById(eatStep.dstChessId),
					chessboard.getSquareById(eatStep.burySquareId));
		}
		if (res != null) History.instance.pop();
		if (res != null) {
			History.instance.pop();
			judgeWinner();
		}
		return res;
	}