Visualizzatore Pedine

di il
2 risposte

Visualizzatore Pedine

Salve a tutti, apro questo topic per segnalare un problema riscontrato durante l'esecuzione del codice postato direttamente qui sotto.
Più precisamente L'errore a tempo d'esecuzione consiste nella mancata visualizzazione delle pedine sul campo da gioco.
Ho provato a lanciare qualche test senza alcun riscontro concreto, pur essendo quasi certamente sicuro che l'errore riesiede nella chiamata del metodo addRobot(Robot r) della classe Battlefield che molto probabilmente non fa il suo dovere.
Mi appello al vostro saggio aiuto allegando oltre al mio codice, anche il testo da cui esso è tratto in modo che possiate fare luce sui miei dubbi senza perdere troppo tempo. Grazie Mille in anticipo!

Testo Esercizio:
Una software house deve ristrutturare un gioco elettronico in cui diversi tipi di robot si sfidano nel tentativo di occupare l'intero campo di battaglia rappresentato da una matrice bidimensionale di tasselli ciascuno di posizione (modellata dalla classe Position) univoca. Nel campo ci sono due tipologie di robot, i walker ed i chaser, modellati dalle corrispondenti classi Walker e Chaser. Il campo e` invece modellato dalla classe Battlefield, che gestisce due mappe (le variabili di istanza posizione2walker e posizione2chaser) che associano ad una posizione la presenza di un robot (di uno dei due tipi citati). Dopo una fase iniziale in cui il campo di gioco viene parzialmente riempito ubicando casualmente diversi esemplari dei due tipi di robot, il gioco si articola come una sequenza di passi in cui tutti i robot seguono la stessa “trafila”: si cerca una eventuale nuova posizione da occupare adiacente a quella corrente, il robot genera un copia di se stesso per occupare la nuova posizione. Per finire, si incrementa la sua longevita`, un intero pari a 0 all'atto della creazione di un robot e poi incrementato di passo in passo. Il gioco esegue la logica di tutti i robot presenti sul campo di gioco secondo un ordinamento scelto causalmente.

Le due tipologie di robot hanno proprieta` in comune (come la posizione e la longevita`), ma finiscono per differenziarsi per il comportamento: i walker (in blu sul display di visualizzazione) si limitano ad occupare una posizione libera adiacente a quella corrente in ciascun passo, oppure a rimanere fermi in assenza di posizione libere, mentre i chaser (in arancione) cercano di occupare una delle posizioni gia` occupate da un robot di una tipologia avversaria se nelle immediate adiacenze, mentre rimangono fermi in caso contrario.

CODICE:

Classe Chaser
package it.uniroma3.EsameGiugno2015;

public class Chaser extends Robot {

	
	public Chaser(Position p) {
		super(p);
	}
	
	@Override
	public void passo(Battlefield field) {
		Position nuova = this.decidiMossa(field);
		if (nuova!=null) {
			Robot clone = new Chaser(nuova);
			field.addRobot(clone);
		}
		this.incrementaLongevita();
	}
	
	
	public Position decidiMossa(Battlefield field) {
		Robot inseguito = cercaAvversario(field);
		if (inseguito==null) 
			return null; /* nessuno da inseguire: stai fermo */
		else return inseguito.getPosizione();
	}

	private Robot cercaAvversario(Battlefield field) {
		for(Position p : field.adiacenti(this.getPosizione())) {
			Robot vicino = field.getRobot(p);
			if (isAvversario(vicino)) {
				return vicino;
			}
		}
		return null;
	}

	private boolean isAvversario(Object avvistato) {
		return true ; /* è sicuramente un Walker??? per ora SI! */
	}

}
Classe Walker:
package it.uniroma3.EsameGiugno2015;


public class Walker extends Robot {

	
	public Walker(Position p) {
		super(p);
	}
	
	@Override
	public void passo(Battlefield field) {
		Position nuova = this.decidiDoveAndare(field);
		if (nuova!=null) {
			Robot clone = new Walker(nuova);
			field.addRobot(clone);
		}
		this.incrementaLongevita();
	}
	
	public Position decidiDoveAndare(Battlefield field) {
		Position corrente = this.getPosizione();
		Position libera = field.posizioneLiberaVicino(corrente);
		return libera; // verso una posizione libera
					   // tutto occupato: fermo
	}

}
Classe Robot
package it.uniroma3.EsameGiugno2015;

public abstract class Robot {

	private Position posizione;
	private int longevita;

	public Robot(Position p) {
		this.posizione = p;
		this.longevita = 0;

	}
	public Position getPosizione() {
		return this.posizione;
	}
	
	public int incrementaLongevita() {
		return ++this.longevita;
	}
	
	public int getLongevita() {
		return this.longevita;
	}
	
	public abstract void passo(Battlefield field);

		
}
Classe Battlefield
package it.uniroma3.EsameGiugno2015;

import java.util.*;

public class Battlefield {

	static final private Class<?>[] TIPOLOGIE = { Walker.class, Chaser.class } ;

	static final private int NUMERO_TIPOLOGIE = TIPOLOGIE.length;

	static final private double OCCUPAZIONE_INIZIALE = 0.01d; // 1%

	private int dim;

	private Random random;

	private Map<Position, Robot> posizione2Robot;


	public Battlefield(int dimensione) {
		this.dim = dimensione;
		this.posizione2Robot = new HashMap<Position,Robot>();
		this.random = new Random();
	}

	public void addRobot(Robot r) {	
		this.posizione2Robot.put(r.getPosizione(), r);
	}


	public Robot getRobot(Position p) {
		return posizione2Robot.get(p);
	}

	public Collection<Robot> getAllRobot() {
		return this.posizione2Robot.values();
	}

	@SuppressWarnings("rawtypes")
	public Map<Class, Set<?>> raggruppaRobotPerTipo() {
		// (vedi DOMANDA 3)
		return null;
	}

	public List<?> getRobotOrdinatiPerPosizione() {
		// (vedi DOMANDA 4)
		return null;
	}

	public SortedSet<?> getRobotOrdinatiPerLongevita() {
		// (vedi DOMANDA 6)
		return null;
	}

	public List<Position> adiacenti(Position perno) {
		final List<Position> adiacenti = new LinkedList<>();
		int x = perno.getX();
		int y = perno.getY();

		for(int i = -1; i<2; i++) {
			for(int j = -1; j<2; j++) {
				Position adiacente = new Position(x+i, y+j);
				if (inCampo(adiacente))
					adiacenti.add(adiacente);
			}
		}
		adiacenti.remove(perno);  // coincidono: quindi non sono adiacenti

		Collections.shuffle(adiacenti); /* ordine casuale */
		return adiacenti;
	}

	private boolean inCampo(Position p) {
		return  p.getX()>=0 && p.getX()<this.dim && 
				p.getY()>=0 && p.getY()<this.dim  ;

	} 

	public Position posizioneLiberaVicino(Position posizione) {
		for(Position p : this.adiacenti(posizione)) {
			if (this.isLibera(p)) {
				return p;
			}
		}
		return null;
	}

	public boolean isLibera(Position posizione) {
		return ( this.getRobot(posizione)==null );
	}

	public int getDimensione() {
		return this.dim;
	}

	public void riempi() {
		long numeroIniziale = Math.round(OCCUPAZIONE_INIZIALE * dim * dim);
		for(int i=0 ; i<numeroIniziale; i++) {
			int x = this.random.nextInt(this.dim);
			int y = this.random.nextInt(this.dim);
			Position posizione = new Position(x, y);
			if (this.isLibera(posizione)) {
				switch (this.random.nextInt(NUMERO_TIPOLOGIE)) {
				case 0: Robot chaser = new Chaser(posizione);
				this.addRobot(chaser);
				break;
				case 1: Robot walker = new Walker(posizione);
				this.addRobot(walker);
				break;
				//case: NUMERO_TIPOLOGIE-1...
				default: throw new IllegalStateException();
				} 
			}
		}
	}
}
Classe Display
package it.uniroma3.EsameGiugno2015;


import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;

import javax.swing.*;

public class Display extends JFrame {

	static final private long serialVersionUID = 1L;
	static final private String LABEL_PASSO = "Passo: ";

	private JLabel stepLabel;
	private FieldView fieldView;
 
	private Color getColore(Battlefield field, Position posizione) {
		Object t = field.getRobot(posizione);
		if (t==null) t = field.getRobot(posizione);
		if (t==null) return Color.white;

		if (t.getClass() == Chaser.class)
			return Color.orange;
		if (t.getClass() == Walker.class)
			return Color.blue;			

		throw new IllegalStateException("Mi aspettavo di dover scegliere il colore di un robot! "
				+ " invece ho trovato "+t.getClass()+"!");

	}

	public Display(int dimensione) {
		this.setDefaultCloseOperation(EXIT_ON_CLOSE);
		this.setTitle("Battlefield");
		this.stepLabel = new JLabel(LABEL_PASSO, JLabel.CENTER);        
		this.setLocation(50, 50);
		this.fieldView = new FieldView(dimensione, dimensione);
		Container contents = getContentPane();
		contents.add(stepLabel, BorderLayout.NORTH);
		contents.add(fieldView, BorderLayout.CENTER);
		this.pack();
		this.setVisible(true);
	}

	public void aggiornaSchermata(int passo, Battlefield field) {
		if (!isVisible())
			setVisible(true);

		this.stepLabel.setText(LABEL_PASSO + passo);
		this.fieldView.preparePaint();

		for(int x=0; x<field.getDimensione(); x++) {
			for(int y=0; y<field.getDimensione(); y++) {
				Position p = new Position(x, y);
				Color colore = this.getColore(field, p);
				fieldView.drawMark(y, x, colore);                
			}
		}
		this.fieldView.repaint();
	}

	private class FieldView extends JPanel  {
		private static final long serialVersionUID = 1L;

		private final int GRID_VIEW_SCALING_FACTOR = 6;
		private int gridWidth, gridHeight;
		private int xScale, yScale;
		private Dimension size;
		private Graphics g;
		private Image fieldImage;

		public FieldView(int height, int width) {
			gridHeight = height;
			gridWidth = width;
			size = new Dimension(0, 0);
		}

		public Dimension getPreferredSize() {
			return new Dimension(gridWidth * GRID_VIEW_SCALING_FACTOR,
					gridHeight * GRID_VIEW_SCALING_FACTOR);
		}

		public void preparePaint() {
			if(! size.equals(getSize())) {  
				size = getSize();
				fieldImage = fieldView.createImage(size.width, size.height);
				g = fieldImage.getGraphics();

				xScale = size.width / gridWidth;
				if(xScale < 1) {
					xScale = GRID_VIEW_SCALING_FACTOR;
				}
				yScale = size.height / gridHeight;
				if(yScale < 1) {
					yScale = GRID_VIEW_SCALING_FACTOR;
				}
			}
		}

		public void drawMark(int x, int y, Color color) {
			g.setColor(color);
			g.fillRect(x * xScale, y * yScale, xScale-1, yScale-1);
		}

		public void paintComponent(Graphics g) {
			if(fieldImage != null) {
				g.drawImage(fieldImage, 0, 0, null);
			}
		}
	}
}
Classe Main
package it.uniroma3.EsameGiugno2015;


import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Main {

	static final private int PASSI 		= 40;
	static final private int DIMENSIONE = 50;

	private Battlefield field;
	private Display display;
	
	public Main() {
		this.field = new Battlefield(DIMENSIONE);
		this.display = new Display(DIMENSIONE);
		this.field.riempi();
	}

	public void run() {
		for(int i=0; i<PASSI; i++) {
			
			
			final List<Robot> allRobot = new ArrayList<>(this.field.getAllRobot());
			Collections.shuffle(allRobot);
			for(Robot c : allRobot) {
				c.passo(field);
			}

			
			this.display.aggiornaSchermata(i, this.field);
			
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
	
	public static void main(String[] args) {
		new Main().run();
	}

}
Classe Position
package it.uniroma3.EsameGiugno2015;


/*
 * Da sistemare. Vedi PositionTest.
 * (vedi DOMANDA 1)
 */
public class Position {
	
	private int x, y;

	public Position(int x, int y){
		this.x = x;
		this.y = y;
	}

	public int getX() {
		return this.x;
	}

	public int getY() {
		return this.y;
	}
		
	public String toString() {
		return this.x+"-"+this.y;
	}

}
P.S: Casomai abbiate bisogno anche del Codice Originale, non esitate a chiedere;
Grazie Ancora.

2 Risposte

  • Re: Visualizzatore Pedine

    UP! mi ero dimenticato HashCode e Equals per la gestione dei duplicati. xD
  • Re: Visualizzatore Pedine

    Quindi hai risolto?

    In effetti al momento getRobot() di battlefield ti restituisce sempre null, perché crei sempre nuove posizioni che passi alla mappa, non arriva mai la stessa posizione...
Devi accedere o registrarti per scrivere nel forum
2 risposte