Archivi tag: esercizio

Array bidimensionali: esercizio alta difficoltà (soluzione)

Ecco la soluzione all’esercizio di difficoltà media proposto nell’articolo Array bidimensionali.

Esercizio

Partendo dalla soluzione all’esercizio di difficoltà media, sareste in grado di modificarlo ulteriormente per fare in modo che la griglia non sia necessariamente 8×8?

Continua la lettura di Array bidimensionali: esercizio alta difficoltà (soluzione)

Array bidimensionali: esercizio media difficoltà (soluzione)

Ecco la soluzione all’esercizio di difficoltà media proposto nell’articolo Array bidimensionali.

Esercizio:

Siete in grado di modificare lo script affinché, ad esempio, modificando i valori all’interno di size() mi venga disegnata sempre una scacchiera di 8×8 che occupi l’intera grandezza della finestra (anche quando non è quadrata)?

Continua la lettura di Array bidimensionali: esercizio media difficoltà (soluzione)

Array di oggetti: Bouncing Ball, parte 4

È finalmente arrivato il momento di mettere insieme quanto imparato nell’ultimo mese, programmazione ad oggettiarray, e di concludere il nostro esercizio Bouncing Ball. La domanda a cui oggi daremo, finalmente, risposta è sempre la stessa: come faccio a creare decine o centinaia di oggetti?

Un array di oggetti

Riprendiamo il codice dell’esercizio Bouncing Ball dove l’avevamo lasciato. Il primo passo è dichiarare un array di oggetti di tipo Ball.

La prima riga del nostro programma serviva per dichiarare una variabile di tipo Ball (il nostro oggetto) di nome myBall.

Ball myBall;

Sostituiamo questa riga di codice con un array di oggetti: per mantenere il mio codice chiaro e leggibile modifico anche il nome della variabile da myBall (che identifica un oggetto solo) a myBalls, utilizzando il plurale.

Ball[] myBalls;

Nella funzione setup() dove, precedentemente, inizializzavo l’oggetto ora devo dichiarare grandezza del mio array. Decido di avere a disposizione 100 oggetti:

myBalls = new Ball[100];

Non mi resta che inizializzare tutti gli oggetti richiamando il constructor all’interno della nostra classe, per sveltire, utilizzo un ciclo for:

for(int i = 0; i < myBalls.length; i++) {
 myBalls[i] = new Ball(random(width), random(height), random(0.5 ,5), random(0.5, 5));
 }

Debugging di un array di oggetti

Con l’ultima porzione di codice abbiamo riempito il nostro array occupando tutte e 100 le caselle con 100 oggetti differenti assegnando a ciascuno di essi, grazie alle funzioni random, la posizione X e Y e la velocità sull’asse orizzontale e verticale.

Se volessimo essere sicuri di averlo fatto nel modo corretto, potremmo pensare di utilizzare, come abbiamo sempre fatto finora, la funzione println(myBalls);

Debugging an Array in Processing

Come potete vedere nell’immagine, il testo riportato nella console non è per niente chiaro. Trattandosi di un array, proviamo a sostituire println con printArray:

Processing: using printArray

Un risultato leggermente migliore: vediamo che ci sono effettivamente 100 oggetti, numerati da 0 a 99, ma facciamo ancora fatica a capire se il contenuto del nostro array è corretto.

Accedere alle variabili interne agli oggetti

Nei nostri esercizi relativi agli oggetti abbiamo imparato a usare la dot notation per richiamare i metodi all’interno degli oggetti. La riga di codice myBall.display() serviva per richiamare la funzione display() contenuta nell’oggetto creato precedentemente.

Utilizzando lo stesso metodo possiamo accedere anche alle variabili interne all’oggetto: scrivendo, ad esempio, myBall.ellipseX; verrà restituito il valore di ellipseX.

Dal momento che, però, non stiamo lavorando con un singolo oggetto ma con un array abbiamo due possibilità:

  1. accedere ai dati di un oggetto specifico: println(myBalls[34].ellipseX);
  2. utilizzare la variabile contatore nel nostro ciclo for per visualizzarli tutti

Aggiungiamo questa riga di codice all’interno del nostro ciclo for:

println("["+i+"] - ellipseX: " + myBalls[i].ellipseX);

Ed ecco che il risultato è finalmente comprensibile:

Processing accessing variables in objects

Bouncing Balls, parte 4

Concludiamo modificando il codice contenuto in draw() per vedere tutte e cento le nostre sfere rimbalzare sullo schermo.

Ball[] myBalls;

void setup() {
  size(700, 500);
  myBalls = new Ball[100];
  for(int i = 0; i < myBalls.length; i++) {
    myBalls[i] = new Ball(random(width), random(height), random(0.5 ,5), random(0.5, 5));
  }  
}

void draw() {
  background(0);
  for(int i = 0; i < myBalls.length; i++) {
    myBalls[i].display();
    myBalls[i].move();
    myBalls[i].checkEdges();
  } 
}

Non ho incluso il codice della classe Ball perché non è stata toccata nemmeno una riga di codice. Se avete fatto tutto correttamente, il risultato sarà il seguente:

Bouncing Ball Final

Esercizio: Bouncing Ball, parte 3 (OOP)

Se vi siete persi gli articoli precedenti, qui trovate la parte 1 e la parte 2 di questo esercizio. Con questo post non aggiungeremo niente di nuovo al nostro programma ma rivedremo per intero il codice per trasformarlo in una versione ad oggetti.

Bouncing Ball Object Oriented

Per prima cosa aggiungiamo una nuova Tab che chiameremo Ball, come la classe che creeremo:

class Ball {
 
}

Per non dimenticarci il constructor, aggiungiamo subito la sintassi necessaria:

class Ball {
 Ball() {
 }
}

A questo punto facciamo copia-incolla delle porzioni di codice che, nel nostro sketch principale, riguardano la nostra palla: ricordatevi di portare nella classe sia le variabili che le funzioni.

Questo è il risultato finale:

class Ball {
  int ellipseX;
  int ellipseY;
  int speedX;
  int speedY;

  Ball() {
    ellipseX = 0;
    ellipseY = height/2;
    speedX = 1;
    speedY = 1;
  }

  void display() {
    ellipse(ellipseX, ellipseY, 50, 50);
  }

  void move() {
    ellipseX = ellipseX + speedX;
    ellipseY = ellipseY + speedY;
  }

  void checkEdges() {
    if (ellipseX > width || ellipseX < 0) {
      speedX = speedX * -1;
    }
    if (ellipseY > height || ellipseY < 0) {
      speedY = speedY * -1;
    }
  }
}
Ball myBall;

void setup() {
  size(700, 500);
  myBall = new Ball();
}

void draw() {
  background(0);
  myBall.display();
  myBall.move();
  myBall.checkEdges();
}

Aggiungiamo constructor

Miglioriamo la nostra classe creando dei nuovi constructor a cui possiamo passare delle variabili. Come già fatto nell'esempio del post precedente, conviene sostituire il data type delle variabili da integer float.

class Ball {
  // VARIABILI
  float ellipseX;
  float ellipseY;
  float speedX;
  float speedY;
  
  // CONSTRUCTOR
  Ball() {
    ellipseX = random(width);
    ellipseY = random(height);
    speedX = 1;
    speedY = 1;
  }
  
  Ball(float _ellipseX) {
    ellipseX = _ellipseX;
    ellipseY = random(height);
    speedX = 1;
    speedY = 1;
  }
  
  Ball(float _ellipseX, float _ellipseY) {
    ellipseX = _ellipseX;
    ellipseY = _ellipseY;
    speedX = 1;
    speedY = 1;
  }
  
  Ball(float _ellipseX, float _ellipseY, float _speedX) {
    ellipseX = _ellipseX;
    ellipseY = _ellipseY;
    speedX = _speedX;
    speedY = 1;
  }
  
  Ball(float _ellipseX, float _ellipseY, float _speedX, float _speedY) {
    ellipseX = _ellipseX;
    ellipseY = _ellipseY;
    speedX = _speedX;
    speedY = _speedY;
  }
  
  // METODI
  void display() {
    ellipse(ellipseX, ellipseY, 50, 50);
  }

  void move() {
    ellipseX = ellipseX + speedX;
    ellipseY = ellipseY + speedY;
  }

  void checkEdges() {
    if (ellipseX > width || ellipseX < 0) {
      speedX = speedX * -1;
    }
    if (ellipseY > height || ellipseY < 0) {
      speedY = speedY * -1;
    }
  }
}

A questo punto non ci resta che sperimentare se funziona tutto correttamente provando a passare delle variabili alla nostra classe:

myBall = new Ball(random(width), random(height), 5, 10);

Esercizio: Bouncing Ball, parte 2

Prima di procedere con la lettura di questo post, assicuratevi di aver letto la prima parte: Esercizio: Bouncing Ball, parte 1. Avete provato a trovare la soluzione al quesito posto alla fine dell’articolo?

Bouncing Ball

Eravamo rimasti con un cerchio che, una volta disegnato sullo schermo, si muoveva da destra verso sinistra e, una volta raggiunto il bordo, invertiva il suo moto tornando indietro. Una volta raggiunto il bordo destro, però, proseguiva il suo moto sparendo dalla nostra vista.

Per fare in modo che il cerchio rimbalzi avanti e indietro, è sufficiente aggiungere una semplice condizione:

if(ellipseX > width || ellipseX < 0)

Ecco quindi il codice completo:

int ellipseX;
int ellipseY;
int speedX = 1;

void setup() {
  size(700, 500);
  ellipseX = 0;
  ellipseY = height/2;
}

void draw() {
  background(0);
  ellipse(ellipseX, ellipseY, 50, 50);
  if(ellipseX > width || ellipseX < 0) {
    speedX = speedX * -1;
  }
  ellipseX = ellipseX + speedX;
  println("EllipseX: " + ellipseX + " SpeedX: " + speedX);
}

Aggiungiamo anche l'asse verticale

Ora che la nostra "palla" si muove solo sull'asse X, implementiamo il movimento anche sull'asse verticale. La variabile ellipseY è già presente nel nostro codice, dobbiamo solo creare una nuova variabile speedY e ricopiare parte del codice modificando solo i parametri necessari:

int ellipseX;
int ellipseY;
int speedX = 1;
int speedY = 1;

void setup() {
  size(700, 500);
  ellipseX = 0;
  ellipseY = height/2;
}

void draw() {
  background(0);
  ellipse(ellipseX, ellipseY, 50, 50);
  if(ellipseX > width || ellipseX < 0) {
    speedX = speedX * -1;
  }
  if(ellipseY > height || ellipseY < 0) {
    speedY = speedY * -1;
  }
  ellipseX = ellipseX + speedX;
  ellipseY = ellipseY + speedY;
  //println("EllipseX: " + ellipseX + " SpeedX: " + speedX);
}

Utilizzando delle variabili per controllare la velocità, variando un numero possiamo modificare l'andamento della nostra palla. Se assegniamo a speedX o speedY un valore iniziale di 5, il cerchio si muoverà molto più velocemente.

Eliminando background(0) all'inizio del blocco di codice draw(), potrete tenere monitorato il movimento della vostra palla sullo schermo, come mostrato nell'immagine qui sotto:

Bouncing ball: eliminiamo background(0) dalla funzione draw()

A questo punto il nostro sketch è pronto per essere migliorato utilizzando funzioni e oggetti; nel prossimo post scopriremo come rendere il nostro codice modulare.