Gå til innhold

Duplisere objekter i Java (Sokoban)


Anbefalte innlegg

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
Lenke til kommentar
Videoannonse
Annonse

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
Lenke til kommentar

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:)

Lenke til kommentar

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).

Lenke til kommentar

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
Lenke til kommentar

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
Lenke til kommentar

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å
  • Hvem er aktive   0 medlemmer

    • Ingen innloggede medlemmer aktive
×
×
  • Opprett ny...