我正在为 uni 完成一项任务,我们获得了扫雷游戏的源代码,我们有一定的要求要实现。其中之一是用户登录后从磁盘读取所有游戏,用户可以随时保存游戏进度。我一直在阅读序列化以保存/加载游戏进度,但我发现很难掌握这个概念。我不确定从哪里开始为此编写代码。该游戏不像许多其他扫雷游戏那样使用 2D 数组。有人可以向我指出任何易于理解的好文档,我发现有些网页有点过于技术性,我迷路了!或者是否有人知道保存扫雷游戏进度的更好方法?抱歉,如果我的问题很广泛,我不能 100% 确定我应该读什么来了解这个,所以'
2 回答
您想要保存与STATE
游戏所在的所有信息相关的信息。这意味着,游戏板(2D 网格或您存储的任何方式)、玩家姓名、分数等。
关于如何序列化对象的技术部分相对容易......参见http://www.javapractices.com/topic/TopicAction.do?Id=57。但是,您必须小心诸如静态或瞬态变量之类的东西,并了解它们如何影响序列化(例如,静态类对象未序列化但会丢失)。
一旦你决定了需要保存什么,你就可以创建一个包含所有重要对象的变量/引用的类——比如一个包装器。这是如果您想避免保存许多不同的文件。您还需要添加implements Serialiable
将被序列化的对象的所有类定义。
因此,在下面的示例中,我们编写了SavedState
包装器对象,但由于它包含Board
,Board
也必须是可序列化的。您可以将要保存的每个对象写入单独的文件中,但我更喜欢将所有重要信息保存在 1 个对象/文件中的对象,因为我发现它更干净。
然后,您进行分配并编写您的对象。
所以例子:
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.util.ArrayList;
public class Game {
Board board;
String name;
public static void main(String[] args) {
Game game = new Game();
game.InitBoard();
//Now save the board
game.SaveBoard();
System.out.println("Player Name is:"+game.name);
System.out.println("Saved Board, changing in memory playername to 'test'.");
game.name = "test";
game.LoadBoard();
System.out.println("Loaded Board, Player Name is:"+game.name);
}
public void InitBoard()
{
board = new Board();
name = "player...";
}
public void SaveBoard()
{
try {
SavedState state = new SavedState(board, name);
OutputStream file = new FileOutputStream("game.mine");
OutputStream buffer = new BufferedOutputStream(file);
ObjectOutput output = new ObjectOutputStream(buffer);
output.writeObject(state);
output.flush();
output.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public void LoadBoard()
{
SavedState state;
InputStream file;
try {
file = new FileInputStream("game.mine");
InputStream buffer = new BufferedInputStream(file);
ObjectInput input = new ObjectInputStream (buffer);
state = (SavedState)input.readObject();
this.board = state.board;
this.name = state.playerName;
input.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
class Board implements Serializable {
ArrayList<Integer> boardElements = new ArrayList<Integer>(); // or however
// else you
// store
// your
// values
// etc...
public Board() {
boardElements.add(1); // etc...
}
}
class SavedState implements Serializable {
Board board;
String playerName;
public SavedState(Board board, String playerName) {
this.board = board;
this.playerName = playerName;
}
}
基本上,您实现了序列化,它迫使您将它持有的所有对象转换为序列化过程,以便可以将其保存在内存中。
如果仅在实体上使用,序列化将正确实现
class MinesweeperState implements Serializable {
private Board board;
}
class Board implements Serializable {
private int[][] mineTable;
}
并且不超过设置和获取,初始化表,填充地雷和设置其周围的地雷计数器的逻辑我想在代理或适配器上设置。
为了节省本身,只需使用带有此代码的 Manager
FileOutputStream fos = null;
ObjectOutputStream out = null;
try {
fos = new FileOutputStream(YOUR_FILENAME_CONSTANT,false);
out = new ObjectOutputStream(fos);
out.writeObject(minesweeperState);
out.close();
System.out.println("Minesweeper state persisted");
} catch (IOException ex) {
LOGGER.err(ex);
}