condizionale

intraprendere azioni diverse in base alla veridicità di una espressione

Con o senza sconto?

Cerchiamo di realizzare il programma che gestisca gli sconti per la nota catena di supermercati Conrad: fornito dall'utente l'importo dello scontrino, applicare (oppure no) uno sconto del 5%. Il programma dovrà quindi verificare la presenza dello sconto: se deve essere applicato si eseguirà il calcolo, altrimenti... niente. L'utente può indicare al programma la presenza dello sconto tramite un apposito pulsante che permetta di essere spuntato. Il suo scopo è lontano dallo scopo di un normale pulsante: nel momento in cui si preme non si vuole eseguire un'azione ma solo mettere la spunta (se prima non ci fosse stata) oppure toglierla (se al momento del click fosse già presente). Nel momento in cui l'utente premerà l'effettivo pulsante per avviare l'elaborazione, il programma andrà a verificare se il pulsante di spunta è – appunto – spuntato o meno.

Il pulsante di spunta si chiama – in JavaFX – CheckBox e viene dichiarato allo stesso modo degli altri oggetti grafici, quindi:

CheckBox scontoPresente = new CheckBox();

Dove inserisci tale dichiarazione? Così nel metodo start():

public class Sconto extends Application { 
  @Override
  public void start(Stage primaryStage) {
    CheckBox scontoPresente = new CheckBox();

Oppure così direttamente nella classe fuori dai qualsiasi metodo?

public class Sconto extends Application { 
  CheckBox scontoPresente = new CheckBox();
  @Override
  public void start(Stage primaryStage) {

La scelta giusta è di inserirlo al livello di classe (fuori dai metodi) perché con quest'oggetto il programma interagirà sia al momento della sua disposizione nella finestra sia nel momento in cui l'utente avvia il calcolo, quindi alla pressione del pulsante.

Nel metodo start() inseriremo anche il testo che dovrà visualizzare in quanto per ora comparirebbe il solo quadratino senza alcunché di spiegazione. La tecnica per impostare il testo di un oggetto è sempre la stessa: usare il metodo setText("testo") che nel nostro esempio sarà:

scontoPresente.setText("applica sconto");

In alternativa potremmo usare il sistema più compatto che fa indicare il testo direttamente alla costruzione dell'oggetto:

CheckBox scontoPresente = new CheckBox("applica sconto");

La funzione che andremo a scrivere non appena verrà premuto il pulsante di avvio al calcolo si dovrà chiedere se c'è la spunta sullo sconto. In caso affermativo toglie il 5% dalla quantità indicata altrimenti la cifra spesa rimarrà immutata. Osserva che il programma non sa a priori, cioè nel momento in cui tu lo stai scrivendo, se ci sarà o no lo sconto; serve quindi che tutte le istruzioni del calcolo siano eseguite solo ed esclusivamente se tale fatto sarà verificato. Per questo si utilizza l'istruzione if, in italiano SE. La logica di funzionamento è la seguente:

SE fatto da verificare è vero ALLORA fai tutto ciò che serve FINE SE

che applicato all'esempio in questione diviene

SE è presente la spunta su scontoPresente ALLORA fai il calcolo dello sconto sottrai tale sconto FINE SE

Se quanto sopra scritto in italiano è chiaro puoi passare direttamente alla versione Java che è pari pari quello sopra riportato a meno della scrittura nello specifico linguaggio:

if( scontoPresente.isSelecteded() ) {
   //fai il calcolo dello sconto
   //sottrai lo sconto dal costo
}

Saltano subito all'occhio alcune cose sulla if ed una sulla spunta. Cominciamo da quest'ultima: il metodo isSelected() vale vero se è visuazzata la spunta, altrimenti varrà falso; questo vuol dire che la parte contenuta nelle parentesi tonde letteralmente la puoi leggere così: "c'è la spunta sull'oggetto scontoPresente". Passiamo all'if: il fatto da verificare è sempre racchiuso nelle parentesi tonde. Dell'espressione che qui si va a scrivere si dovrà sempre poter dire se questa è vera o falsa; nell'esempio infatti si dice che scontoPresente è spuntato, tale espressione diciamo che è vera se in effetti la spunta c'è altrimenti è falsa.

L'espressione che deve essere valutata da if si chiama condizione e – come detto – è sempre racchiusa tra parentesi tonde. A seguire osservi delle parentesi graffe: proprio come quando hai scritto le tue funzioni, le graffe racchiudono una sequenza di istruzioni. Nel nostro caso raccoglieranno tutte e sole quelle istruzioni che dovranno essere eseguite nel caso in cui la condizione è vera. Ciò vuol dire che se invece la condizione è falsa, ossia non c'è la spunta, tali istruzioni non vanno eseguite.

Il programma, in definitiva e a meno delle importazioni di rito è il seguente:

public class Sconto extends Application { 
   TextField scontrino = new TextField();
   CheckBox scontoPresente = new CheckBox();
   TextField daPagare = new TextField();
    
   @Override
   public void start(Stage primaryStage) {
      Button sconta = new Button();
      Text l_scontrino = new Text();
      Text l_daPagare = new Text();
      sconta.setText("Verifica e sconta");
      scontoPresente.setText("Diritto allo sconto del 5%");
      l_scontrino.setText("Scontrino €");
      l_daPagare.setText("A pagare €");
      sconta.setOnAction(e -> calcolaSconto() );
      GridPane pannello = new GridPane();
      pannello.setHgap(10);
      pannello.setVgap(7);
      pannello.add(l_scontrino, 0, 0);
      pannello.add(scontrino, 1, 0);
      pannello.add(sconta, 0, 1);
      pannello.add(scontoPresente, 1, 1);
      pannello.add(l_daPagare, 0, 2);
      pannello.add(daPagare, 1, 2);
      
      Scene scene = new Scene(pannello, 350, 200);  
      
      primaryStage.setScene(scene);
      primaryStage.setTitle("Valuta lo sconto");
      primaryStage.show();
   }

   public void calcolaSconto() {
      int soldi, sconto;
      soldi=Integer.parseInt(scontrino.getText());
      if(scontoPresente.isSelected()) {
         sconto = soldi * 5 / 100;
         soldi = soldi - sconto;
      }
      daPagare.setText ("" + soldi);
   }
        
   public static void main(String[] args) {
      launch(args);
   }
}

if

A questo punto introduciamo formalmente l'istruzione if:

L'istruzione if è composta da 3 parti: una condizione, un corpo_if e un corpo_else secondo la sintassi:
if( condizione ){
  corpo_if;
} else {
  corpo_else;
}
La condizione è una espressione booleana, se vale true implicherà l'esecuzione del corpo_if e se vale false l'esecuzione del corpo_else. La parte else con relativo corpo è opzionale.

Da notare che verrà eseguito il corpo_if o corpo_else e mai entrambe e che la parte else non ha una condizione perché il corpo_else viene eseguito se la condizione dell'if risulta falsa, non c'è bisogno di scrivere una ulteriore condizione. Una cosa che potrebbe non sembrare ovvia: all'interno del corpo dell'if o dell'else potremmo trovare nuovamente un if.

Quanto vale y alla fine di questo frammento di programma?

int x=7;
int y=0;
if(x<5){
  y=3;
}else{
  if(x>=2){
    y=1;
  }else{
    y=2;
  }
}
0no, il valore della y viene modificato 1 2no, giustamente si va nella parte else dell'if esterno ma poi... 3no, x non è minore di 5

Espressioni booleane

Nell'esempio precedente abbiamo usato come condizione lo stato di un pulsante (selezionato oppure no) ma questa è soltanto una possibilità. Possiamo utilizzare una qualsiasi espressione di cui sia possibile dire se è vera o falsa (attenzione, il "vero/falso" non ha nulla a che fare con il "corretto/sbagliato"): queste espressioni si chiamano "espressioni booleane" e in Java e il loro valore può essere soltanto true o false con il significato che è facile immaginare. Ad esempio l'espressione 4<2 vale false mentre 3<7 vale true.

Una espressione booleana si può ottenere sia combinando valori numerici che combinando valori booleani, andiamo avanti con ordine.

Operatori di confronto

Gli operatori di confronto hanno come argomento due valori numerici (ad eccezione di uguale e diverso che operano anche su operandi boolean) e restituiscono come risultato un valore boolean.

==
a == b
a è uguale a b, vale true se a ha lo stesso valore di b
!=
a != b
a è diverso da b, vale true se a non ha lo stesso valore di b
>
a > b
a è maggiore di b, vale true se a è maggiore a b
>=
a >= b
a è maggiore o uguale a b, vale true se a è maggiore o uguale a b
<
a < b
a è minore di b, vale true se a è minore di b
<=
a <= b
a è minore o uguale a b, vale true se a è minore o uguale a b

Volume del cubo

Poniamo per esempio di voler realizzare un programma che calcoli il volume di un cubo a patto che l'utente non inserisca un valore negativo come misura del lato. Il nostro programma ha una casella di testo che si chiama cLato in cui l'utente inserirà la misura del lato e una etichetta che si chiama eVolume in cui visualizzeremo il risultato. Se l'utente scriverà un numero negativo nell'etichetta scriveremo "errore: lato negativo".

public void calcolaVolume(){
  String testoLato = cLato.getText();
  int lato = Integer.parseInt(testoLato);
  int volume;
	
  if( lato < 0 ){
    eVolume.setText("errore: lato negativo"); 
  } else {
    volume = lato * lato * lato;
    eVolume.setText(""+volume);
  }
}

In questo caso l'espressione booleana è lato < 0 che varrà true se ad esempio il lato è lungo "-7" e false se ad esempio il lato misura "8".

Per esercizio costruisci il programma e verificane il funzionamento.

Pari o dispari?

Matematica: dato un numero, dire se questi è pari o dispari. È noto che per essere pari è necessario che sia divisibile per 2. Detto così sembra di difficile soluzione: ci chiediamo allora quando un numero è divisibile per 2 e la risposta sarà: un numero è divisibile per 2 se il resto della divisione (stiamo parlando di divisione tra numeri interi) è 0, altrimenti non è divisibile per 2, quindi non è pari e cioè è dispari:

SE il resto della divisione tra il numero e 2 è uguale a 0 ALLORA scrivi "il numero è pari" ALTRIMENTI scrivi "il numero è dispari" FINE SE

La parte else in un condizionale...

è obbligatoriano, può essere omessa deve specificare la condizione contraria dell'ifno, l'else non ha una condizione: viene eseguita se la condizione dell'if è falsa è opzionale

In Java per calcolare il resto si usa l'operatore %. Ad esempio 17%10 dà come risultato 7, 8%3 dà come risultato 2 e 55%5 dà come risultato 0. Bene. Posto di aver già realizzato la funzione start(), scriviamo qui la funzione del calcolo:

public void verificaPari() {
   int num;
   num = Integer.parseInt(numero.getText());  //numero è il nome della TextBox con il dato di input
   if(num%2 == 0) {
      messaggio.setText("il numero è pari");  //messaggio è il nome della Label per la risposta
   } else {
      messaggio.setText("il numero è dispari");
   }
}

Operatori logici

Servono ad esprimere fatti abbastanza comuni come ad esempio: "un voto è un numero maggiore di zero e minore o uguale a dieci", hanno come operandi dei valori booleani e come risultato un valore booleano.

||
or, "oppure". Vale true se uno dei due operandi è true.
||truefalse
truetruetrue
falsetruefalse
true || false vale true
&&
and, "e". Vale true se entrambe i due operandi sono true.
&&truefalse
truetruefalse
falsefalsefalse
true && false vale false
!
not, "non". Inverte il valore di verità che lo segue, lavora su un singolo operando.
!
truefalse
falsetrue
!true vale false

Quanto vale true && (!false) ?

false true

Sembrano complicati? Proviamo a scrivere il programma che controlla se un valore inserito è un possibile voto o meno, il dato lo leggiamo dalla casella cVoto e il risultato lo scriviamo in eRisposta:

public void controllaVoto(){
  String testoVoto = cvoto.getText();
  int voto = Integer.parseInt(testoVoto);
	
  if( voto>0 && voto<=10 ){
    eVolume.setText(voto + " è un voto"); 
  } else {
    volume = lato * lato * lato;
    eVolume.setText(voto + " non è un voto");
  }
}

Quanto vale l'espressione voto>0 && voto<=10 se voto vale 8?

falseno, il voto è maggiore di 0 e anche minore o uguale a 10 erroreno, l'espressione è sintatticamente corretta true

Quanto vale l'espressione voto<1 || voto>10 se voto vale 8?

trueno, il voto non è minore di uno e neanche maggiore di 10 erroreno, l'espressione è sintatticamente corretta false

Quale delle seguenti espressioni è di tipo boolean?

4+5no, il risultato è 9 che è un int 3**7no, non ha un tipo perché è sbagliata 4>3si, per la precisione vale true

In Java gli operatori logici vengono valutati con una tecnica chiamata "a corto circuito" o "valutazione minima" che sta a significare che se l'operando sinistro è sufficiente per stabilire il risultato l'altro non viene neanche valutato. Prendiamo per esempio l'espressione 4==2+2 || 78==12 visto che 4==2+2 è vera e che per l'operatore or se un operando vale true anche il risultato vale true la parte 78==12 non viene neanche considerata.

Radio

La casella di spunta si adopera in genere per attivare o meno una certa opzione. Caso diverso invece è il bisogno di fornire all'utente una rosa di possibilità tra cui poterne scegliere esattamente una. Questo significa che quando si apre il programma una scelta deve essere già impostata e sarà poi l'utente – eventualemente – a modificarla. La soluzione è l'uso dei pulsanti radio (RadioButton in JavaFX). L'esempio classico è maschio o femmina: ogni utente apparterrà al primo od al secondo caso; il programma, al momento della visualizzazione ( in start() ), può proporre maschio e poi eventualmente chi lo usa lo cambierà.

Modifichiamo il programma di saluto visto nelle prime sezioni in modo tale che dia un messaggio diverso a seconda che chi lo sta usando è maschio o femmina. Innanzi tutto la dichiarazione è ormai intuitiva (RadioButton nomePulsante = new RadioButton()), così come il metodo per impostarne il testo ( nomePulsante.setText("testo da visualizzare")) e quello per verificare se un dato pulsante radio è selezionato (nomePulsante.isSelected()). Va invece detto che per impostare una selezione su di un pulsante radio si usa il metodo setSelected() e nelle parentesi va indicato true (vero) o false (falso) la presenza della scelta; in altre parole se il pulsante lo vogliamo selezionato scriveremo nomePulsante.setSelected(true) e per averlo non selezionato scriveremo nomePulsante.setSelected(false) e – nota bene – quest'ultimo metodo vale pari anche per le CheckBox; puoi quindi mettere o togliere spunte direttamente da programma come meglio credi. Passiamo finalmente al codice:

TextField nome = new TextField();
RadioButton maschio = new RadioButton();
RadioButton femmina = new RadioButton();
TextField saluto = new TextField();

@Override
public void start(Stage primaryStage) {
   Button dimmiCiao = new Button();
   ToggleGroup genere = new ToggleGroup();
   Label lNome = new Label();
   Label lSaluto = new Label();
   dimmiCiao.setText("Ti voglio salutare");
   maschio.setText("Maschio");
   femmina.setText("Femmina");
   maschio.setToggleGroup(genere);
   femmina.setToggleGroup(genere);
   maschio.setSelected(true);
   lNome.setText("Ti chiami");
   lSaluto.setText("Dirò");
   dimmiCiao.setOnAction( e -> saluta() );
   GridPane pannello = new GridPane();
   pannello.setHgap(10);
   pannello.setVgap(7);
   pannello.add(lNome, 0, 0);
   pannello.add(nome, 1, 0);
   pannello.add(maschio, 0, 1);
   pannello.add(femmina, 1, 1);
   pannello.add(dimmiCiao, 0, 2);
   pannello.add(lSaluto, 0, 3);
   pannello.add(saluto, 1, 3);
   
   Scene scene = new Scene(pannello, 550, 200);        
   primaryStage.setTitle("Ancora saluti...");
   primaryStage.setScene(scene);
   primaryStage.show();
}

public void saluta(){
   if(maschio.isSelected()){
      saluto.setText ("Egregio sig. " + nome.getText() + " benvenuto!");
   } else {
      saluto.setText ("Gentile sig.ra " + nome.getText() + " benvenuta!");
   }
}

Come si controlla la presenza della spunta su una casella CheckBox?

usando il metodo check()questo metodo non esiste per l'oggetto CheckBox usando i metodo add()questo metodo si usa per aggiungere un elemento ad esempio ad un GridPane usando il metodo isSelected() usando il metodo setScene()questo metodo si usa ad per aggiungere la scena ad un oggetto Stage

Un'ultima questione nel programma appena scritto che sicuramente avrai già osservato: l'oggetto ToggleGroup. In una finestra ci possono essere vari gruppi di pulsanti radio, ad esempio uno indica il genere (maschio/femmina) ed un altro l'essere maggiorenne/minorenne. È per noi intuitivo che l'essere maschio o femmina porta alla selezione di una delle due possibilità e non ha alcuna influenza sull'altra scelta, quella della maggiore età; non è ovvio però per il computer che quindi non sa quali sono i pulsanti legati da un senso logico e quali sono invece indipendenti. Per questo si crea un gruppo di pulsanti e poi si dice ai singoli pulsanti a quale gruppo appartengono, in ogni gruppo soltanto un pulsante può essere selezionato (es: se si seleziona "femmina" maschio viene automaticamente deselezionato). Se ci sono più gruppi si dichiarano più oggetti ToggleGroup e ciascun pulsante radio andrà legato al proprio gruppo. Per legare un pulsante radio ad un gruppo è sufficiente usare il metodo setToggleGroup() in questo modo:

nomePulsanteRadio.setToggleGroup(nomeGruppo);

Esercizio: il fantomatico dott. Finger ha inventato la formula per calcolare il peso ideale a partire dall'altezza, dal genere (maschio o femmina) e dalla corporatura: prima si calcola l'altezza divisa per 60 nel caso in cui si pratica attività sportiva, altrimenti l'altezza va divisa per 120. La quantità così ottenuta la chiameremo a. Si riprende poi l'altezza e si toglie 100 nel caso in cui è un uomo o si toglie 112 nel caso in cui è una donna. Il risultato lo chiameremo b. Indicheremo ora l'indice di Finger (e lo chiameremo iFinger) il risultato della somma tra le quantità a e b. Il peso ideale si ottiene – in fine – dividendo l'indice di Finger per 1,1 se la corporatura è piccola; per 0,95 se la corporatura è grande mentre nulla si fa (equivarrebbe a dividere per 1) per la normale corporatura.

Esercizio: Scrivi un programma che al suo avvio estrae un numero casuale e poi chiede all'utente di indovinare il numero estratto. Se l'utente non indovina il programma deve dire se il numero estratto è più grande o più piccolo.

Il frammento di programma

x = (int)(Math.random()*10);

estrae un numero a caso tra 0 e 10, 10 escluso (quindi tra 0 e 9).

Esercizio: Realizza un programma per la macchinetta del parcheggio: l'utente dovrà indicare il numero di ore che intende trattenersi. Se si vuole tenere la macchina al coperto c'è un'aggiunta di spesa di €5,00. Bisogna anche scegliere che mezzo parcheggiare: un camion costa (all'ora) €10,00, un camper cosa €5,00 ed un'automobile costa €3,50. Può altresì scegliere di parcheggiare per l'intera giornata: pagherà il costo di 5 ore. Mostrare il totale.

Esercizio: Realizza un programma per la gestione del Teenager's Bar: l'utente può scegliere un tipo di bevanda tra o il caffè (€0,80) o il succo d'arancia (€1,10) o il prosecco (€2,05). Può chiedere quante tazze/bicchieri ne vuole. Può altresì volere il servizio al tavolo che però gli costerà il 5% in più. Se sceglie di riconsegnare i vuoti al banco otterrà uno sconto di €0,50. Mostrare la spesa del cliente.

Esercizio: La palestra NewLook ha bisogno di un programma per il conteggio delle calorie bruciate. Per questo l'utente inserirà il numero di km percorsi. L'utente dovrà scegliere se quel percorso è stato fatto o a nuoto (km*21) o di corsa (km*12) o in bici (km*7) ottenendo le calorie bruciate. Se l'utente indossava bracciali per aumentare lo sforzo, le calorie realmente bruciate si ottengono moltiplicando il risultato ottenuto per 1,18. Analogo per le cavigliere moltiplicando per 1,35.

Esercizio: Le gite che entrano allo zoo di Mistoia pagano in base alla scuola degli studenti. Per coloro che non hanno la prenotazione si avrà un aggravio di €4,50 indipendentemente dai partecipanti. Se i ragazzi sono delle elementari ciascuno spende €6,00; se sono delle medie ciascuno spende €8,50 mentre delle superiori €9,50. Gli accompagnatori spendono la metà degli alunni. In fine, nei mesi invernali si ha uno sconto di €0,50 a ragazzo (no agli accompagnatori).