save game (minesweeper) progress using serialization java - java

I am completing an assignment for uni, we were given the source code for a minesweeper game and we have certain requirements to implement. One of these is that all games are read from disk after a user logs in, and users can save game progress at any time. I have been reading into serialization to save/load game progress but I am finding it a little hard to grasp the concept. I'm not exactly sure on where to start to write code for this. The game does not use a 2D array as a lot of other minesweeper games do. Can someone point me to any good documentation that is easy to understand, I find some webpages get a little too technical and I get lost! Or if anyone knows of a better way to save the progress of a minesweeper game? Sorry if my question is broad, I'm not 100% sure on what I should be reading to learn about this so that's why I'm asking for help, to get pointed in the right direction.

Basically you implement Serialization what forces you to convert all the objects it hold to a serialization process so it can be saved on memory.
Serialization is correctly implemented if used only on entities
class MinesweeperState implements Serializable {
private Board board;
}
class Board implements Serializable {
private int[][] mineTable;
}
And no more than sets and gets, the logic within initializating the table, filling the mines and setting its surrounding mine counters I would like to set on a Proxy or Adapter.
for the saving itself, just use a Manager with this code
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);
}

You want to save all information that are related to the STATE that the game is in.
This means, game board (2D grid or however you store), player name, scores, etc.
The technical part about how to serialize an object is relatively easy... see http://www.javapractices.com/topic/TopicAction.do?Id=57.
However, you have to be careful with stuff like static or transient variables and know how these affect serialization (e.g. static class objects are not serialized but are lost).
Once you decide what needs saving, you can create a Class that contains variables/references to all the important objects - like a wrapper. This is if you want to avoid saving many different files.
You also need to add implements Serialiable to all the class definitions of objects that will be serialized.
So, in my example below we write the SavedState wrapper object, but as this contains Board, Board must also be serializable. You could write each object you want to save in a separate file but I prefer to have an object that holds all important information in 1 object/file because I find it is cleaner.
You then make assignments and write your object.
So Example:
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;
}
}

Related

Save and read multiple types of setting in a text file

I want to have a setting system that I can read write and use variables from the are stored in a file.
To summarize, There is a class and inside that class is a list of settings.
When I make a setting I want to add it to the list so that I can write it to the text file later.
I also want to be able to get the setting value without casting it which would use generics.
So for boolSetting I would only need to do boolSetting.get() or boolSetting.value ect
To start with code I have already written I have the code to read and write to the file. This works perfect (I think). I just need help with the setting part. Here is the read and write to file.
package winter.settings;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import net.minecraft.src.Config;
import winter.Client;
public class WinterSettings {
public static File WinterSetting;
public static void readSettings() {
try {
File WinterSetting = new File(System.getProperty("user.dir"), "WinterSettings.txt");
BufferedReader bufferedreader = new BufferedReader(new InputStreamReader(new FileInputStream(WinterSetting), "UTF-8"));
String s = "";
while ((s = bufferedreader.readLine()) != null)
{
System.out.println(s);
String[] astring = s.split(":");
Client.modules.forEach(m ->{
if(m.name==astring[0]) {
m.settings.forEach(setting ->{
if(setting.name==astring[1]) {
setting.value=astring[2];
}
});
}
});
}
bufferedreader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void writeSettings() {
try {
File WinterSetting = new File(System.getProperty("user.dir"), "WinterSettings.txt");
PrintWriter printwriter = new PrintWriter(new FileWriter(WinterSetting));
Client.modules.forEach(m ->{
m.settings.forEach(setting ->{
printwriter.println(m.name+":"+setting.name+":"+setting.value);
});
});
printwriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Pretty much how this works is I have a setting in a Module which just stores some information.
The setting has a name and a value
To write it I am just writing
The module name, the setting name, the setting value For example: ModuleName:SettingName:false
This works fine, but leads to the problem that I just don't know enough about generics. I can't find a way that works with writing reading and setting / getting. The setting should have a name and value. Some code I wrote is below I just don't know how to continue it.
public class Setting<T> {
public String name;
public T value;
public Setting(String name, T value) {
this.name = name;
this.value = value;
}
public T getValue() {
return value;
}
}
From here I have subclasses for each type of setting. Not sure if this is good programming or not.
Now I can set get / write, but when I read the value isn't updated correctly.
Right now I make a new setting like
private final BooleanSetting toggleSprint = new BooleanSetting("ToggleSprint", true);
There is one problem to this from what I can tell. First off when I try to add it to a list when initilizing I get an error.
Type mismatch: cannot convert from boolean to BooleanSetting.
In short: I need to be able to read write get and set a value in a setting object. This can be boolean / int / ect.
Above is some of my code to read / write to txt file. Setting class and what I have of making a new setting.
My 2 problems are that I read the settings correctly and when making them I can't add them to a list.
Use the Boolean.True static variable
new BooleanSetting("ToggleSprint", Boolean.TRUE);
or
Boolean.valueOf(true)

Read my own printed line in console

Is there a way in which, from a function, I print a String in with System.out.print() and then read it from another function?
something like:
void printC(String foo){
System.out.print(foo);
}
void read(){
String c;
while(something){
printC(somethingElse);
c = System.console.readLine();
JOptionPane.showMessageDialog(c);
}
}
No, you can't. As other people have commented, you probably just want an internal data structure to connect different components.
In command-line programs, the standard input and standard output (plus standard error) are completely independent streams. It's typical for all three to be connected to a single virtual terminal, but they can be redirected independently from the shell, such as by using a pipeline or files.
Think about what if the input of your program is coming from a file and the output is being piped to another program; trying to "get back" the output doesn't make any sense.
Try PipedOutputStream.
import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.io.PrintStream;
import java.util.Scanner;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
public class Test extends JFrame {
void printC(String foo){
System.out.print(foo);
}
void read() throws IOException{
String c = "";
PipedOutputStream pipeOut = new PipedOutputStream();
PipedInputStream pipeIn = new PipedInputStream(pipeOut);
System.setOut(new PrintStream(pipeOut));
Scanner sc = new Scanner(pipeIn);
while(!c.equalsIgnoreCase("Quit")){
printC("Test\n");
c = sc.nextLine();
JOptionPane.showMessageDialog(this, c);
}
}
public static void main(String[] args) throws IOException {
Test t = new Test();
t.read();
}
}
Why do you want to do this? Is it so that you can print something to the screen or so that you can create events?
If you particularly want to pass messages to the screen AND also another part of your application; a simple solution could involve creating your own PrintStream class. You can deal with the object in the same way as you would otherwise deal with System.out (as that's a PrintStream too).
Something along the lines of this:
public class FancyStream extends PrintStream
{
LinkedList<String> messageQueue = new LinkedList<>();
#Override
public void println(String line)
{
System.out.println(line);
messageQueue.add(line);
}
public String getLine()
{
return messageQueue.pop();
}
}
However, if you want events (as you've suggested in the comments), this is not the way to do it!
You should take a look at the Observer pattern for dealing with events. The wikipedia article about this is here.
There's plenty of other resources to learn about the Observer pattern if you do a Google search. Java even has a built in Observable class and Observer interface that may solve your problem.

how to access a method from private static class

im trying to put all stopwords on a hashset, i dont want to add it one by one so im trying to put in a txt file and have my scanner scan it. the problem is i think my code does not reach my scanner here is my code:
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.*;
public class StopWords {
public static final Set<String> stopWords = new HashSet<String>();
private static class scan {
public scan()throws IOException {
Scanner s = null;
try{
s = new Scanner(new BufferedReader(new FileReader("stopwords.txt")));
while (s.hasNext()) {
//System.out.println(s.next());
stopWords.add(s.next());
}
}finally{
if (s != null) {
s.close();
}
}
}
}
}
im running my main on other class and im just calling this class. thanks in advance
Make a wrapper for it in enclosing class.
Something like:
public void doScan() {
try {
scan.scan();
catch (IOException e) {};
}
in StopWords class.
This way you could call doScan() on instance of StopWords. You could also make it static.
And I agree that you should follow naming convections of Java language (wikipedia.org).
Just want to add a couple tricks you might consider:
First - you could store your stopwords in a properties file, then use java.util.Properties.load to pull the data in.
Second - you can put your stopwords file on your classpath, and bundle up the stopwords file with the rest of your code in a jar for delivery.
You wind up with something like this:
final Properties stopProps = new java.util.Properties();
stopProps.load( new InputStreamReader( this.class.getClassLoader().getResourceAsStream( "mycode/stopWords.properties", "UTF-8" ) );
...
Good luck!

Exchanging Object between client and server using sockets in java

I am trying to build an application where the server is a bank and the clients are the bracnhs of that bank so it's classic Multithread server / client app. In the first step i want the bank to record every branch that connects to it. so iwant to send the branck as object in the objectstream of the socket so that the bank can extract it and record it.
here's what i have done so far
import java.io.IOException;
import java.net.ServerSocket;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class Banque {
private List<Succursale> listSucc = new ArrayList<Succursale>();
private int sommeTotale;
private int nbSuccInit = 4;
public void ajouteSucc(Succursale suc){
}
public Banque(){
initialiserServeur();
}
private void initialiserServeur() {
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(10118);
}
catch (IOException e)
{
System.err.println("On ne peut pas ecouter au port: 10118.");
System.exit(1);
}
System.out.println ("Le serveur est en marche, Attente de la connexion.....");
int i = 0;
while(i<5){
try {
UtilMultiTh mt = new UtilMultiTh(serverSocket.accept());
Thread t = new Thread(mt);
t.start();
listSucc.add(mt.getSuc());
System.out.println(listSucc.size());
for(int j =0; j<listSucc.size();j++){
System.out.println("La succursale "+(j+1)+" est:"+listSucc.get(j).getName());
}
i++;
System.out.println("FLAGPOSTban");
}
catch (IOException e)
{
System.err.println("Accept a echoue.");
System.exit(1);
}
}
System.out.println ("connexion reussie");
System.out.println ("Attente de l'entree.....");
}
public static void main (String [] args){
Banque banK = new Banque();
}
}
The class MultiTh that manage the multi thread connection of the branchs
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.PrintWriter;
import java.net.*;
public class UtilMultiTh implements Runnable {
private Socket soc;
private Succursale suc;
public UtilMultiTh(Socket s){
System.out.println("FLAGconsmth");
this.soc = s;
}
public void run() {
System.out.println("FLAGPOSrun");
ObjectOutputStream oos;
ObjectInputStream ois;
try{
oos = new ObjectOutputStream(soc.getOutputStream());
ois = new ObjectInputStream(soc.getInputStream());
//System.out.println("La succ est");
try {
Object o = ois.readObject();
if(o!=null){
suc = (Succursale)o;
//System.out.println("La succ est"+suc.getName());
}
/*while(o!=null){
suc = (Succursale)o;
System.out.println("La succ est"+suc.getName());
}*/
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
oos.close();
ois.close();
soc.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
public synchronized Succursale getSuc() {
return suc;
}
public void setSuc(Succursale suc) {
this.suc = suc;
}
}
And here's the Succursale class for the branchs
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
public class Succursale implements Serializable {
private String coordonnees;
private String name;
private int sommeDepart;
private int sommeRecue;
private int sommeEnvoyee;
private List<Succursale> listSuccAc = new ArrayList<Succursale>();
private GuiSuccursale succView;
public Succursale (){
succView = new GuiSuccursale(Constantes.sommeDepart,1);
this.sommeDepart=Constantes.sommeDepart;
this.name="Succursale: "+(1);
connexionBanque();
}
public void connexionBanque(){
String host = Constantes.adrBanque[0];
int port = Constantes.portBanque[0];
Socket echoSocket = null;
try {
echoSocket = new Socket(host, port);
ObjectOutputStream oos = new ObjectOutputStream(echoSocket.getOutputStream());
oos.writeObject(this);
System.out.println("FLAGPOSTSUcc");
} catch (UnknownHostException e) {
System.err.println("Hôte inconnu: " + host);
System.exit(1);
} catch (IOException e) {
e.printStackTrace();
System.err.println("Ne pas se connecter au serveur: " + host);
System.exit(1);
}
}
public void connexionSuccursales(){
}
public void envoiManuel(){
}
public String getName() {
return name;
}
public void envoiPeriodique(){
}
public static void main (String[] args){
Succursale suc = new Succursale();
}
}
I have two questions, how can i from the UtilMultuTh return a Succursale to Banque and before that why is that in the UtilMultiTh class readObject return null while in the succursale class just after etablishing the connection i put the class in the socket ? Do i have to put an infinite loop in here ?
EDIT: I changed the code, now multith is correctly getting the Succursale from the socket, the problem now is that the threads are no synchronised because UtilMultiTh gets the Succursale after Banque wants to get it, i am not familiar with synchrnosation, how can i tell Banque to do the getSuccursale only after utilMultiTh performed its run ?
Google's protobufs are perfect for this. I'd suggest using them and sending the byte output between client and server. You'll need to frame your output if you're planning to use TCP.
Java's serialization mechanism could always break between different runtime versions. Also, what if you decide to implement the server or client in another language? You'll have to duplicate java's entire serialization logic. Protobuf takes care of the tedious process required to marshall and unmarshall objects to and from bytes. So pretty much, its a better form of java's built in serialization which is language independent.
So I suggest you abandon Object streams. I know this isn't the answer you were hoping for, but it will make things nicer for you in the long run.
ProtoBuffers
This is not an answer to you question, but it won't fit in a comment and I think it needs to be said.
Be sure to reset your output stream after each write! ObjecdtOutputStream only writes an object once. If you try to write it again, it will just send a little note "Put that object I sent a while ago in back the input stream again at this point." Saves space, but if your object has changed, those changes won't get through. Also, the original object sent is going to be kept in memory on both sides, killing your performance. Reset clears everything out and gives you a fresh start.
Also, I'd use Externalizable rather than Serializable. This gives you control over what is sent (though you have to write some code). There is some danger that if you write an object that refers to other objects it will write all those other objects as well, which you may not want. Also, Externalizable lets you write to the same, old format even if the class changes. Also, it lets you put in version numbers. These can sometimes allow a newer version to read a stream written by an older version, but it always gives you a warning that the format has changed.
The intent of ObjectOutputStream is that you can write one object that includes all your data. A truly vast graph can be sent with one call to writeObject. This is ingenious. It worked fine for me, writing the complete state of a computer game to a disk file with one writeObject( this ), but it's usually a disaster when writing to a socket.
I am somewhat inclined not to use ObjectOutput, but to just write primitives. It's simpler and faster and you have a lot of control. But I have had trouble knowing which object to create on the Input end. I think the best thing to do is read and write objects, but keep the I/O simple by writing your own method for the Externalizable interface and calling reset() after each writeObject.

Android: Mixing multiple AudioTrack instances?

I need to run two instances of AudioTrack at the same time. They must run separately because I'm playing them at different, variable sample rates. I found that if I run them in the same thread, they "take turns". I'm running them each in their own thread, but the audio is stuttering.
Any ideas on making two instances play nice? If not, any tips on mixing two short buffers into one, even if I want to play them at different sample rates.
I have 4 audioTracks playing at once and they seem to play fine. Testing on HTC Desire 1.1ghz OC. I get glitches with the threading sometimes though. Occasionally if all four are playing one will not stop when I try to join the thread. Need to do more testing.
Here is my class for playing back a wav file recorded at a given path
package com.ron.audio.functions;
import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;
public class AudioPlayManager implements Runnable {
private File fileName;
private volatile boolean playing;
public AudioPlayManager() {
super();
setPlaying(false);
}
public void run(){
// Get the length of the audio stored in the file (16 bit so 2 bytes per short)
// and create a short array to store the recorded audio.
int musicLength = (int)(fileName.length()/2);
short[] music = new short[musicLength];
try {
// Create a DataInputStream to read the audio data back from the saved file.
InputStream is = new FileInputStream(fileName);
BufferedInputStream bis = new BufferedInputStream(is);
DataInputStream dis = new DataInputStream(bis);
// Read the file into the music array.
int i = 0;
while (dis.available() > 0) {
music[i] = dis.readShort();
i++;
}
// Close the input streams.
dis.close();
// Create a new AudioTrack object using the same parameters as the AudioRecord
// object used to create the file.
AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,
11025,
AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT,
musicLength,
AudioTrack.MODE_STREAM);
// Start playback
audioTrack.play();
// Write the music buffer to the AudioTrack object
while(playing){
audioTrack.write(music, 0, musicLength);
}
}
catch(Exception e){
e.printStackTrace();
}
}
public void setFileName(File fileName) {
this.fileName = fileName;
}
public File getFileName() {
return fileName;
}
public void setPlaying(boolean playing) {
this.playing = playing;
}
public boolean isPlaying() {
return playing;
}
}

Categories

Resources