PDA

View Full Version : [JAVA]Utilizzare oggetti solo in presenza di un altro.


maxxpower
15-05-2012, 17:39
Buonasera a tutti,

Perdonatemi per il titolo lungo ma ho cercato di essere il più esplicito possibile.

Sto lavorando ad un progettino per il mio corso di java che consiste in una sorta di avventura grafica (molto approssimativa) in cui un personaggio passa di stanza in stanza trovando degli oggetti che può utilizzare (sfruttandone i vari metodi quindi);

L'unico mio dilemma è che da specifiche del progetto alcuni oggetti,ad esempio una Porta, possono essere utilizzati (per esempio aperti,visto come metodo apri()) della porta,solo in presenza di un altro oggetto di tipo Chiave ad esempio.


Ho pensato ad una soluzione del genere:



public class Porta implements Openable,Examinable {


protected long keyval=321456L;
protected boolean isOpen = false;

@Override
public void apri(Usable u) throws WrongKeyException{

if (u instanceof Key && ((Key) u).keyval==this.keyval) {



if (isOpen) {

return;
}

isOpen = true;

}

throw new WrongKeyException();

}

@Override
public void chiudi() {

isOpen = false;

}

@Override
public String esamina(){

return "Questa è una porta!";

}

@Override
public void apri() {
// TODO Auto-generated method stub

}

}





Potrebbe funzionare? Considerate che l'eventuale personaggio sostanzialmente potrà effettuare le azioni presenti negli oggetti del gioco (richiamandone quindi i metodi),ed avrà un inventario, in cui dovrà esserci ovviamente una chiave.

PGI-Bis
15-05-2012, 18:43
E' corretto gestire la cosa con un'eccezione, nel senso che logicamente non fa una piega; l'eccezione è il prodotto del mancato verificarsi di una condizione per cause non controllabili nell'ambito in cui la condizione è richiesta: la porta sa che si apre con una chiave ma non ha modo di sapere perché la chiave sia sbagliata quindi ripassa la palla al chiamante, sperando che lui possa farci qualcosa.

C'è un problema di verificabilità nel momento in cui il metodo apri dichiara di accettare uno Usable e genera un'unica eccezione per due casi diversi: uno quando lo Usable non sia un Key e uno quando lo Usable sia un Key ma della specie sbagliata.

L'intoppo sta nel fatto che se per una svista logica il tuo codice dovesse passare uno Usable che non sia un Key otterresti un errore uguale al caso, diverso, in cui sia un Key ma non quello giusto. E' una di quelle cose che in fase di debug ti fa restare perplesso (del genere "oh, son sicuro che la chiave è giusta, come mai spari l'eccezione..." e poi scopri che il problema è che la chiave giusta non era mai passata al metodo apri).

Non è sbagliato lo Usable (chi mi dice che la porta non sia apribile con un "grimaldello del nano trallallà"), è il rilascio dell'eccezione che dovrebbe essere il più specifico possibile.

maxxpower
15-05-2012, 20:29
Perfetto, grazie mille per il consiglio.

un chiarimento: avendo specificato nel "super-metodo" dell'interfaccia apri(usable u) throws Exception posso aggiungere un'altra eccezione a quella già dichirata nella signature giusto,lanciandola con un ulteriore controllo sul keyvalue?


secondo chiarimento: il codice è logicamente compatibile con quello che cerco?

Ovvero che per aprire una porta ho bisogno di una chiave che il personaggio ha in un inventario. Quello che non mi torna in ciò che ho scritto è come riuscire a togliere la chiave dall'inventario( e questo è facile) e poi graficamente (con un Jbutton) passare quella chiave come parametro al metodo apri della porta.

spero di essermi spiegato.

grazie di cuore per l'aiuto,purtroppo sto imparando ancora..

VICIUS
15-05-2012, 21:39
Io metterei come tipo di ritorno della funzione apri() un boolean e poi ritornerei vero o falso per segnalare se la porta si è aperta o meno. Il lancio di una eccezione dovrebbe significare qualcosa di assurdo che la funzione non sa o non può gestire.

Poi fa attenzione che dopo isOpen = true; ci va un return per uscire dalla funzione. Altrimenti tutte le volte che la porta si apre viene lanciata anche l'eccezione WrongKeyException;

maxxpower
15-05-2012, 22:05
Io metterei come tipo di ritorno della funzione apri() un boolean e poi ritornerei vero o falso per segnalare se la porta si è aperta o meno. Il lancio di una eccezione dovrebbe significare qualcosa di assurdo che la funzione non sa o non può gestire.

Poi fa attenzione che dopo isOpen = true; ci va un return per uscire dalla funzione. Altrimenti tutte le volte che la porta si apre viene lanciata anche l'eccezione WrongKeyException;

non converrebbe tornare un messaggio a quel punto?


cmq correggo subito il return..hai ragione..

VICIUS
15-05-2012, 22:34
non converrebbe tornare un messaggio a quel punto?
Cosa intendi di preciso per messaggio?

maxxpower
15-05-2012, 23:13
Una stringa. Che contenga ad esmepio "la porta è stata aperta!"

un boolean forse non è molto utile da questo punto di vista;anche se magari,visto che avrò bisogno di una gestione grafica forse è più facile da utilizzare di una stringa.

PGI-Bis
16-05-2012, 00:51
Non vanno bene nè il booleano nè la stringa: in Java si usano le eccezioni esattamente per il caso di specie. Usare il valore restituito sarebbe sbagliato nello stesso senso in cui in italiano è sbagliato usare il presente quando ci va il congiuntivo: il senso si capisce ma c'è qualcosa che non va.

Se il metodo è "apri" e la porta non si apre è chiaro che s'è verificata un'eccezione. Se "apri" ma non si apre e non rilascia un'eccezione allora non è più "apri" ma "provaAdAprire", che è tutta un'altra cosa.

maxxpower
16-05-2012, 09:31
Non vanno bene nè il booleano nè la stringa: in Java si usano le eccezioni esattamente per il caso di specie. Usare il valore restituito sarebbe sbagliato nello stesso senso in cui in italiano è sbagliato usare il presente quando ci va il congiuntivo: il senso si capisce ma c'è qualcosa che non va.

Se il metodo è "apri" e la porta non si apre è chiaro che s'è verificata un'eccezione. Se "apri" ma non si apre e non rilascia un'eccezione allora non è più "apri" ma "provaAdAprire", che è tutta un'altra cosa.


Perfetto. Allora adesso aggiungo l'ulteriore eccezione per il Keyval Errato della chiave.

Il mio dubbio resta sempre se sto agendo correttamente per quanto riguarda la clausola del progetto che dice "alcuni oggetti possono essere usati con altri, come una chiave su una porta o una gettone telefonico su una cabina"

Nella classe key così come ho scritto ora non avrei bisogno di nulla...forse solo di un metodo usa...che magari prenda in input una Porta p su cui richiamare il metodo apri(this)?

PGI-Bis
16-05-2012, 10:00
Per risolvere il problema devi considerare la questione in un contesto più ampio del semplice rapporto chiave-porta. Se ci limitiamo a quello infatti esistono una pluralità di soluzioni equivalente e la decisione circa quale sia preferibile è arbitraria.

Ti servono più informazioni per decidere e quelle informazioni le ricavi dai meccanismi più generali del programma.

Ad esempio, come fa il tuo programma a decidere che l'utente sta cercando di aprire una porta?

maxxpower
16-05-2012, 15:06
Il progetto prevede una GUI in cui il personaggio principale del gioco è interpretato da me stesso...all'interno della stanza ho un certo numero di oggetti di diverso tipo e con diverse azioni che posso fare su di essi...come ad esempio la porta e la chiave..ma c'è anche un baule per dire..o un passaggio segreto,tutti gli oggetti hanno dei metodi..ovvero possono essere esaminati,utilizzati,aperti/chiusi,spenti/accesi

Il personaggio può compiere alcune azioni precise...che sono corrispondenti ai metodi degli oggetti...con qualche extra come l'azione parla..

quindi dovrei tramite gui cliccare sull'oggetto porta..che mi darà alcuni comandi...ad esempio apri...

spero di essermi spiegato.

Grazie veramente di cuore per l'aiuto..:)

PGI-Bis
16-05-2012, 18:11
E' una descrizione "sociologica" ma a noi ne servirebbe una più misurabile - in fondo dobbiamo farci un programma :).

Prova ad immaginare il programma dal punto di vista delle attività, del "ciò che capita", quando l'utente interagisce con un oggetto. Diamo quindi per scontato che il meccanismo di interazione sia già definito.

il giocatore interagisce con un oggetto. Questo "evento", a chi è notificato? Che informazioni deve portarsi dietro per poter essere gestito? Come è gestito?

Esempio di un possibile ragionamento, una speculazione su come potrebbero andare le cose:

il programma rileva, in qualche modo, l'interazione dell'utente con l'oggetto X
l'interazione è notificata al "modulo di gestione delle interazioni" M.
M ricava X dalla notifica
Da X, M prende la lista di azioni possibili, le mostra all'utente e attende una risposta
Ricevuta la risposta R, M esegue l'azione R.A su X

Funzionerebbe? Diciamo che X è una Porta R è "Apri" e R.A corrisponde all'invocazione del metodo "apri" sull'oggetto Porta.

Ci sarebbe un intoppo, giusto? La porta ha bisogno di una chiave.

Generalizzando, le azioni che io posso dover eseguire su un oggetto X in base ad una risposta R (cioè alla scelta di un'azione A esebuigile sull'oggetto con cui interagisco) possono richiedere degli argomenti.

Da dove li piglio? Funzionerebbe se introducessimo una seconda fase dopo la scelta della risposta:

Da X, M prende la lista di azioni possibili, le mostra all'utente e attende una risposta
Ricevuta la risposta R, ottengo l'argomento P per l'esecuzione dell'azione R.A dall'applicazione di R.A.B all'inventario dell'utente ed eseguo R.A(P, X)

Funziona stavolta?

interazione -> porta
scegli azione -> Porta.AzioneApri
scegli argomento -> chiave = Porta.AzioneApri.argomento(inventario)
esegui azione -> Porta.AzioneApri.esegui(porta, chiave)

E' chiaro che qui all'interno di "esegui" troveremmo scritto qualcosa tipo:

porta.apri(chiave)

e non ci sarebbe la necessità di avere un metodo chiave.usa(porta) che dica poi... porta.apri(chiave), sarebbe una ripetizione.

In questa particolare configurazione, il metodo "usa" di chiave non serve. Ma questa configurazione è idonea a gestire il sistema di interazione tra elementi che serve al tuo programma?

Eh eh, bisogna vedere. Quali altri tipi di elementi che interagiscono tra loro avresti? Funzionerebbe il sistema anche con quelli?