Visualizzazione dei risultati da 1 a 2 su 2
  1. #1

    Esercizio pattern Building

    Ho un esercizio di questo tipo:

    codice:
    Si scriva un programma Java che prenda in input un file contenente una sequenza
    di righe, ognuna contenente le informazioni relative ad un punteggio di giuoco, e
    costruisca la classifica dei primi cento punteggi ottenuti.
    Ogni riga del file contiene una sequenza di opzioni seguiti dai relativi valori.
    Le varie opzioni devo essere interpretate nel modo seguente:
    -nick: seguito da una stringa con il nickname del giocatore (è sempre presente).
    -p: seguito da un intero che indica il punteggio complessivo (è sempre presente).
    -a: seguito da un intero, indica l'età del giocatore.
    -i: seguito da una data, indica la data d'iscrizione del giocatore.
    -n: seguito da un intero, indica il numero di partite giocate dal giocatore.
    -u: seguito da un intero, indica l'ultimo punteggio ottenuto dal giocatore.
    -dp: seguito da una data, indica la data in cui è stato totalizzato il punteggio.
    -bonus: non seguito da alcun valore, indica che il giocatore ha un bonus.
    Tutte le righe finiscono con un punto e virgola preceduto da uno spazio.
    In caso di parimerito deve apparire per primo il giocatore che appare per prima nella
    lista di input.
    Specifiche
    Utilizzare un oggetto Builder per la costruzione degli oggetti contenuti nella
    classifica di giuoco. Gli oggetti contenuti nella classifica devono essere definiti come
    oggetti immutabili
    Utilizzare i metodi toString() per la descrizione degli oggetti.
    Input
    Il file di input contiene una sequenza di righe, ognuna contenente le informazioni
    relative ad un punteggio di giuoco.
    
    Il file di output contiene la classifica dei primi cento giocatori che hanno ottenuto il
    punteggio più alto.
    Ogni riga del file contiene l'informazione su ogni posizione della classifica.
    Il primo elemento di ogni riga è la posizione della classifica racchiuso traparentesi
    quadre e seguito da uno spazio.
    Seguono il nickname del giocatore ed il punteggio ottenuto, separati da una virgola
    e racchiusi tra parentesi tonda.
    I successivi valori sono tutti separati da una virgola e possono non essere presenti.
    In particolare l'ordine e la descrizione dei valori deve seguire l'esempio mostrato di
    seguito.
    [***] (***, ***), nome : ***, *** anni, punteggio ottenuto il ****, *** partite
    giocate, iscritto dal ***, ultimo punteggio ottenuto : ***, bonus utilizzato
    Ora io ho realizzato tutto quanto, solo che credo ci sia un problema, quando leggo il file di input, certi oggetti vengono clonati...non capisco il perchè.
    L'idea è stata di leggere una prima volta il file per sapere quanti giocatori ci sono, e poi in una seconda lettura leggere l'input, costruire l'oggetto ed inserirlo in un array di oggetti.
    Ma mi sembra che vengano clonati perchè facendo una prova e stampandoli con il toString in output mi stampa per più oggetti lo stesso nome, o valori che non dovrebbero esserci.

    Vi posto entrambi i file, in uno vi è la costruzione degli oggetti tramite Building, nell'altra il programma vero e proprio. Temo che l'errore sia nella fase di lettura e costruzione nella classe Intestaallaclassifica.

    codice:
    public class Giocatori
    {
    	private final String nome;
    	private final String nick;
    	private final int p;
    	private final int a;
    	private final String i;
    	private final int n;
    	private final int u;
    	private final String dp;
    	private final boolean bonus;
    	
    	
    	
    	
    	public static class Builder
    	{
    		private final String nick;
    		private final int p;
    		
    		public Builder(String nick, int p)
    		{
    			this.nick=nick;
    			this.p=p;
    		}
    		
    		private String nome="";
    		private int a=-1;
    		private String i="";
    		private int n=-1;
    		private int u=-1;
    		private String dp="";
    		private boolean bonus=false;
    		
    		
    		public Builder nome(String nome)
    		{
    			this.nome=nome;
    			return this;
    		}
    		
    		public Builder a(int a) 
    		{
    			this.a=a;
    			return this;
    		}
    		
    		public Builder i(String i)
    		{
    			this.i=i;
    			return this;
    		}
    		
    		public Builder n(int n)
    		{
    			this.n=n;
    			return this;
    		}
    		
    		public Builder u(int u)
    		{
    			this.u=u;
    			return this;
    		}
    		
    		public Builder dp(String dp)
    		{
    			this.dp=dp;
    			return this;
    		}
    		
    		public Builder bonus(String bonus)
    		{
    			if(bonus.equals("-bonus"))
    			this.bonus=true;
    			return this;
    		}
    		
    		public Giocatori build()
    		{
    			return new Giocatori(this);
    		}
    	}
    	
    	
    	private Giocatori(Builder builder)           //perchè non public?
    	{
    		nick=builder.nick;
    		p=builder.p;
    		a=builder.a;
    		i=builder.i;
    		n=builder.n;
    		u=builder.u;
    		dp=builder.dp;
    		bonus=builder.bonus;
    		nome=builder.nome;
    	}
    	
    	public String toString()
    	{
    		String ret="("+nick+", "+p+")";
    		
    		if(nome.compareTo("")!=0) ret+=", nome : "+nome;
    		if(a!=-1) ret+=", "+a+" anni";
    		if(dp.compareTo("")!=0) ret+=", punteggio ottenuto il "+dp;
    		if(n!=-1) ret+=", "+n+" partite giocate";
    		if(i.compareTo("")!=0) ret+=", iscritto dal "+i;
    		if(u!=-1) ret+=", ultimo punteggio ottenuto : "+u;
    		if(bonus) ret+=", bonus utilizzato";
    		
    		return ret;
    		
    	}
    }
    E poi:

    codice:
    import java.io.*;
    import java.util.StringTokenizer;
    
    
    public class Intestaallaclassifica
    {
    	public static void main(String [] args) throws IOException
    	{
    		FileReader reader=null;
    		FileWriter out=null;
    		BufferedReader buff=null;
    		StringTokenizer info=null;
    		
    			String nome="";
    			String nick="";
    			int p=-1;
    			int a=-1;
    			String i="";
    			int n=-1;
    			int u=-1;
    			String dp="";
    			boolean bonus=false;
    			String contrlbonus="";
    			
    		
    		try
    		{
    			
    			long start=System.currentTimeMillis();
    		
    			out=new FileWriter("output.txt");
    			reader=new FileReader("input.txt");
    			buff=new BufferedReader(reader);
    			
    
    			int count=0;
    			int concorrenti=0;
    			
    			while(buff.readLine()!=null)
    				concorrenti++;
    			
    			reader=new FileReader("input.txt");
    			buff=new BufferedReader(reader);
    			
    			Giocatori [] giocatori=new Giocatori[concorrenti];
    			
    			String parametri="";
    			
    			while(buff.ready())
    			{
    					
    				info=new StringTokenizer(buff.readLine(), " ;");
    				
    				
    				while(info.hasMoreTokens())
    				{
    					parametri=info.nextToken();
    					
    					if(parametri.equals("-nick"))
    					nick=info.nextToken();
    					
    					else if(parametri.equals("-p"))
    					p=(Integer.parseInt(info.nextToken()));
    					
    					else if(parametri.equals("-a"))
    					a=(Integer.parseInt(info.nextToken()));
    					
    					else if(parametri.equals("-i"))
    					i=info.nextToken();
    					
    					else if(parametri.equals("-n"))
    					n=(Integer.parseInt(info.nextToken()));
    					
    					else if(parametri.equals("-u"))
    					u=(Integer.parseInt(info.nextToken()));
    					
    					else if(parametri.equals("-dp"))
    					dp=info.nextToken();
    					
    					else if(parametri.equals("-bonus"))
    					contrlbonus="-bonus";
    					
    					else if(parametri.equals("-nome"))
    						nome=info.nextToken()+" "+info.nextToken();
    					
    					parametri="";
    				}
    				
    				Giocatori giocatore=new Giocatori.Builder(nick, p).nome(nome).a(a).i(i).n(n).u(u).dp(dp).bonus(contrlbonus).build();
    				giocatori[count++]=giocatore;
    			}
    				
    			Giocatori [] classifica =new Giocatori[100];
    			
    			int max;
    			int index;
    			int position=0;
    			int elementi=0;
    			int controllo=0;
    			String valore="";
    			String oggetto;
    		
    			/*while(elementi<100)
    			{		
    				index=0;
    				max=0;	
    				
    				for(int j=0; j<giocatori.length; j++)
    				{
    					
    					
    					valore="";
    					controllo=0;
    						
    					if(giocatori[j]!=null){
    					oggetto=giocatori[j].toString();
    					
    						
    					while(oggetto.charAt(controllo)!=' ')
    						controllo++;
    						controllo++;
    					
    					    while(oggetto.charAt(controllo)!=')')
    					    {
    						valore+=oggetto.charAt(controllo);
    						    controllo++;
    					    }						    
    						
    						if(Integer.parseInt(valore)>max)
    						{
    					         	max=Integer.parseInt(valore);
    						         index=j;
    						}
    					}
    				}
    				
    					elementi++;
    				
    					classifica[position++]=giocatori[index];
    					elementi++;
    					
    					if(index==0)
    					{
    						for(int j=1; j<giocatori.length; j++)
    						giocatori[j-1]=giocatori[j];
    						
    						giocatori[giocatori.length-1]=null;
    					}
    			
    					else if(index==giocatori.length-1)
    					giocatori[index]=null;
    			
    					else 
    					{
    						for(int j=index; j<giocatori.length-2; j++)
    						giocatori[j]=giocatori[j+1];
    				
    						giocatori[giocatori.length-1]=null;
    					}
    				
    			}
    			
    			position=1;*/
    				
    			/*for(int j=0; j<100; j++)
    			{
    				out.write("["+position+"] "+classifica[j].toString()+'\r'+'\n');
    				position++;
    			}
    			*/
    			long end=System.currentTimeMillis();
    			System.out.println("TEMPO TRASCORSO "+(end-start));
    			
    			for(int k=0; k<giocatori.length; k++)
    			System.out.println(giocatori[k].toString());
    			
    		}
    		
    		catch(IOException e)
    		{
    			System.out.println("ERROR");
    		}
    	}
    }

  2. #2
    Utente di HTML.it
    Registrato dal
    Feb 2007
    Messaggi
    4,157

    Re: Esercizio pattern Building

    codice:
    public class Giocatori
    {
    public static class Builder
    	{
    		private final String nick;
    		private final int p;
    		
    		public Builder(String nick, int p)
    		{
    			this.nick=nick;
    			this.p=p;
    		}
    		
    		private String nome="";
    		private int a=-1;
    		private String i="";
    		private int n=-1;
    		private int u=-1;
    		private String dp="";
    		private boolean bonus=false;
    		
    		
    		public Builder nome(String nome)
    		{
    			this.nome=nome;
    			return this;
    		}
    	}
    scusa ma mi spieghi cosa e come funziona questo codice nella logica di programmazione ad oggetti?
    A differenza di quanto fai in C, lo standard per la programmazione ad oggetti vuole che robe del tipo

    builder.p diventino builder.getP() o builder.setP() a seconda del caso in cui devi leggere/scrivere un valore.
    Questo consente, in alcuni casi, di eseguire operazioni accessorie mascherate completamente all'utente (vantaggio più evidente dell'incapsulamento).
    E' prassi, programmando ad oggetti, di adottare questa convenzione nell'uso degli elementi di una classe.

    Un altro consiglio (e aumenti la leggibilità del codice) è dare nomi validi alle variabili: a, p, i ti sono chiari adesso, ma tra una settimana non lo saranno altrettanto e avrai problemi a decifrare il tuo stesso codice. Le sole iniziali vanno bene in cicli(anche se anche lì io tendo a non usarle). Anche se il prof li nomina in quel modo, non so come tu ce la faccia a programmare cosi.

    Poi perchè non fai semplicemente uso di una roba del genere (per assegnare un valore)
    codice:
    Builder builder = new Builder();
    builder.setProperty(value);
    diventa molto più semplice da gestire (anzichè fare la return ecc.) Poi io non vedo l'applicazione del pattern builder, se segui l'esempio che c'è su wikipedia e ti fermi un po' ad usare la logica di programmazione ad oggetti la soluzione arriva.

    Altra domanda: perchè hai fatto un'unica classe? Puoi fare benissimo diverse classi (anzi dovresti perchè hai una classe astratta e le concrete con l'implementazione).
    Attento che STATIC non è sinonimo di IMMUTABILE.
    Static indica che è sempre residente in memoria durante l'esecuzione e soprattutto che tutti possono averne accesso (per non entrare troppo nei dettagli) e possono modificare il valore.
    Altri modificatori (es final) impediscono la modifica.

    Poi hai messo giocatori (costruttore private) non so per quale motivo. In genere il costruttore è private quando si vuole forzare l'utente ad utilizzare altre vie per istanziare la classe, in questo caso non ha molto senso.

    codice:
    	public String toString()
    	{
    		String ret="("+nick+", "+p+")";
    		
    		if(nome.compareTo("")!=0) ret+=", nome : "+nome;
    		if(a!=-1) ret+=", "+a+" anni";
    		if(dp.compareTo("")!=0) ret+=", punteggio ottenuto il "+dp;
    		if(n!=-1) ret+=", "+n+" partite giocate";
    		if(i.compareTo("")!=0) ret+=", iscritto dal "+i;
    		if(u!=-1) ret+=", ultimo punteggio ottenuto : "+u;
    		if(bonus) ret+=", bonus utilizzato";
    		
    		return ret;
    		
    	}
    }
    Un consiglio sulle librerie string (anche qui si vede che hai fatto molta programmazione in C:
    guardando java.lang.String (le API) trovi

    string.trim() --> elimina spazi bianchi inizio e fine stringa
    per cui
    codice:
      if (string.trim().equals("")){
         //DO TRUE CASE
     }
    e
    codice:
      if (string.trim().length == 0){
         //DO TRUE CASE
     }
    equivalgono al tuo controllo con il compare, ma diciamo che il compare è usato più che altro per ordinamenti che per controlli di validità come il tuo (non che sia sbagliato)
    Stai attento che ogni += sulle stringhe significa creare una nuova stringa: in questi casi usa uno
    StringBuilder oppure StringBuffer e fai l'append di ciò che ti interessa.
    Non crea problemi per piccole applicazioni, ma secondo me è non sempre si programma per computer con risorse infinite ed è bene abituarsi ad ottimizzare.
    A parte questo, ok l'inizializzazione

    codice:
    		
    			while(buff.ready())
    			{
    					
    				info=new StringTokenizer(buff.readLine(), " ;");
    				
    				
    				while(info.hasMoreTokens())
    				{
    					parametri=info.nextToken();
    					
    					if(parametri.equals("-nick"))
    					nick=info.nextToken();
    					
    					else if(parametri.equals("-p"))
    					p=(Integer.parseInt(info.nextToken()));
    					
    					parametri="";
    				}
    				
    				Giocatori giocatore=new Giocatori.Builder(nick, p).nome(nome).a(a).i(i).n(n).u(u).dp(dp).bonus(contrlbonus).build();
    				giocatori[count++]=giocatore;
    			}
    è qui che applichi il concetto di builder.
    Hai la classe astratta, in base al contenuto hai l'oggetto builder che costruisce per INTERO il giocatore.
    Ma qui non lo vedo applicato questo concetto.
    Inoltre
    codice:
    if(parametri.equals("-nick"))
    					nick=info.nextToken();
    devi prevedere un else per nick: mai lasciare roba inconsistente, decidi tu quale situazione indica la mancanza del valore.
    codice:
    if (parametri.equals("-nick")) nick = info.nextToken(); 
    else nick = "";
    L'azzeramento ad ogni ciclo è necessario per evitare che il valore del ciclo i-esimo lo usi nel ciclo i+1, ma prevedendo un else per ogni parametro non hai problemi (non è necessario azzerare).
    Ti consiglio di parsare la stringa nel builder (che è lo scopo dell'esercizio).
    codice:
    		Giocatori [] classifica =new Giocatori[100];
    La struttura dinamica aiuta perchè per un piccolo overhead maggiore ti occupa spazio solo per gli oggetti realmente istanziati (e un .size() ti dice quanto è grande la struttura).
    Poi se usi iteratori o cicli foreach scorrere la struttura è banale.
    Infine, conoscendo un po' le strutture, puoi

    1. definire nella tua classe giocatori comparable e quindi far fare l'ordinamento alla classe Collection (operazione già ottimizzata). In questo caso tu vai ad indicare la regola per cui un oggetto viene prima di un altro e utilizzando Collection.sort(collection) hai l'ordinamento. Il risultato finale lo visualizzi in 2 modi: ciclo con stampa toString() per ogni elemento della collection e ti fermi a 100 oppure crei una sublist con gli elementi da 0 a 100
    2. definire la classe comparable e utilizzare strutture che consento l'inserimento ordinamento (se non sbaglio i set) e poi passare alla stampa dei primi 100 (con blocco) oppure ad una subcollection da 0 a 100

    scusami se sono stata prolissa, spero che ti sia chiaro quello che ho detto.

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.