Gå til innhold

Duplisere objekter i Java (Sokoban)


Anbefalte innlegg

Skrevet (endret)

Hei, driver med en innlevering som omhandler spillet Sokoban. Jeg skal legge til muligheten for å undo ett eller flere flytt. Slik jeg vil løse oppgaven er å bruke en stack som legger til en kopi av spillbrettet, slik at når brukeren bruker "undo" så vil den bruke .pop() for å hente det forrige mappet. Men her kommer problemet, Java har ingen mulighet for å lage en kopi av objekter slik jeg vil uten videre..Så det er her jeg trenger litt hjelp fra dere som har litt mer kontroll i Java enn meg:)

 

http://pastebin.com/4grixkDv Level (logikken)

http://pastebin.com/U3LGyjN7 ConsoleSokoban (grafikken)

 

Setter stor pris på all tips og hjelp:)

 

 

edit: typo

Endret av Malmo4444
Videoannonse
Annonse
Skrevet

Det hjelper nok ikke stort, men jeg mener å huske at det er ganske komplisert å kopiere et objekt. Du får skrive på nytt i python, så er det enklere å kopiere :-P

Skrevet (endret)

Du kan også serialisere objektene og lagre byte arrayet (evt også til disk hvis du vil persistere mellom kjøringer).

 

Husk isåfall å implementere Serializable i klassen som skal serialiseres.

 

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class ObjectSerializer {

public Serializable bytesToObject(byte[] input) {
	ByteArrayInputStream bais = new ByteArrayInputStream(input);
	ObjectInputStream ois = null;

	try {
		ois = new ObjectInputStream(bais);
		return (Serializable) ois.readObject();
	} catch (IOException e) {
		// TODO Handle
		e.printStackTrace();
	} catch (ClassNotFoundException e) {
		e.printStackTrace();
	} finally {
		if (ois != null) {
			try {
				ois.close();
			} catch (IOException e) {
			}
		}
	}
	return null;
}

public byte[] objectToBytes(Serializable input) {
	ByteArrayOutputStream baos = new ByteArrayOutputStream();
	ObjectOutputStream oos = null;
	try {
		oos = new ObjectOutputStream(baos);
		oos.writeObject(input);
	} catch (IOException e) {
		// TODO Handle
		e.printStackTrace();
	} finally {
		if (oos != null) {
			try {
				oos.close();
			} catch (IOException e) {
			}
		}
	}
	return baos.toByteArray();
}
}

Endret av Kiff
Skrevet

Det er vel tre måter å gjøre det på, du må uantsett skrive logikken for det selv

 

  • En copy constructor
  • En Factory
  • Object.clone()

 

Edit: vær forsiktig med å bruke .clone()

 

 

public Test(Test other) {

this.level = other.level;

this.playerX = other.getPlayerX();

this.playerY = other.getPlayerY();

this.targetY = other.targetY;

this.targetX = other.targetX;

// this.undoStack = other.undoStack;

}

 

 

Nå prøvde jeg å lage en copy constructor. Men når jeg kjører koden så printer den fortsatt ut det samme map'et (som skal visse forrige move).. Håper du kan hjelpe meg med å se hva jeg gjør feil og ikke forstår:)

 

takk:)

Skrevet

Kanskje ikke akkurat det du spør om, men det finnes andre måter i implementere undo på, som er mye mer effektiv. Hvis du f.eks. bare lagrer bevegelsesretning og om du dyttet på noe, så er det smal sak å "reversere" brettet til slik det var før forrige trekk (tastetrykk).

Skrevet (endret)

Lag en ny Map og bruk Map.putAll(Map), ellers har du to referanser til samme objekt:

 

public static void main(String[] args) {

	Map<String, String> map1 = new HashMap<String, String>();
	map1.put("a", "b");

	Map<String, String> firstCopy = map1;
	Map<String, String> secondCopy = new HashMap<String, String>();
	secondCopy.putAll(map1);
	map1.put("c", "d");

	System.out.println(map1.values().size() == firstCopy.values().size()); 
               //^ true, begge peker på samme map
	System.out.println(map1.values().size() == secondCopy.values().size()); 
               //^ false

}

Endret av Kiff
Skrevet

Gjør som javanuben sier. Poenget med denne oppgaven er at du skal huske hvilke trekk som har blitt gjort, og så kjøre de baklengs. Ikke lagre hver eneste gamestate.

Skrevet

Kanskje ikke akkurat det du spør om, men det finnes andre måter i implementere undo på, som er mye mer effektiv. Hvis du f.eks. bare lagrer bevegelsesretning og om du dyttet på noe, så er det smal sak å "reversere" brettet til slik det var før forrige trekk (tastetrykk).

Jepp, du bør sjekke ut "Command pattern", og kapsle hvert trekk inn i eget command objekt, med metoden execute() for å utføre trekket, og undo() for å reversere trekket. Hver gang du gjør et trekk, lag et "Trekk-Objekt", utfør objektets execute(), og føy "Trekk-Objektet" til en command-liste. Hver gang du bruker ønsker å bruke undo(), så henter du siste objektet i command-listen, utfører undo() på "Trekk-objektet" og fjerner det fra listen.

  • Liker 1

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
×
×
  • Opprett ny...