Questa pagina descrive il progetto per il corso di Informatica della Laurea in Matematica per gli appelli dell'anno accademico 2019/2020.
Si consideri una arbitraria scacchiera di dimensioni N x
M
dove N
e M
sono naturali
positivi. Nella scacchiera è presente un singolo pezzo non pedone
degli scacchi (quindi una torre, cavallo, alfiere, donna o re).
Tale singolo pezzo è inizialmente collocato in una casella
arbitraria p1
. Da questa posizione, il pezzo compie una
sequenza di K
mosse secondo le normali regole degli
scacchi, attraversando così le
caselle p1,p2,...,pK,p(K+1)
, tutte distinte (il pezzo
non ritorna mai su una casella attraversata in passato).
Si ha K>=0
, dove il caso degenere K=0
rappresenta la sequenza di zero mosse in cui il pezzo non si muove
dalla posizione iniziale p1
.
Questa sequenza di mosse può essere rappresentata con una matrice
N x M
definita come segue. Nella cella di posizione
pj
è presente il numero j
(con
1<=j<=K+1
). Nelle altre celle la cui posizione non è
stata mai attraversata dal pezzo, si trova il numero zero.
Per esempio, questa matrice rappresenta una sequenza di nove mosse di una torre.
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 9 0 0 1 0 0 0 0 0 2 0 0 0 0 0 0 0 5 0 0 0 0 0 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 0 0 0 0 0 0 0 7 0 0 0 0 0 0 4 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Ovviamente, non tutte le matrici intere rappresentano sequenze di mosse. Chiamiamo quelle che lo fanno "matrici di mosse" (per un dato pezzo).
Il progetto consiste nello scrivere una funzione Java che, dato un pezzo e una matrice intera arbitraria, verifichi se la matrice è una matrice di mosse per il pezzo in questione.
Alcune precisazioni:
int
di Java.
N
e M
.
Si chiede di scrivere una funzione Java avente (esattamente) nome e tipo come segue:
public static boolean testChessMoves(String fileName)
Il parametro indica il nome del file da aprire, contenente il nome del pezzo da considerare e la matrice.
Come risultato, deve essere restituito un booleano, che deve
essere true
se e solo se la matrice è una matrice di
mosse del pezzo, come descritto sopra.
Quando la funzione viene chiamata, vi viene garantito che il file di input è un file di testo con esattamente la forma seguente:
pezzo N M x1,1 x1,2 ... x1,M ... xN,1 xN,2 ... xN,M
dove in prima riga, pezzo
è il nome del pezzo, una
stringa tra le seguenti torre,cavallo,alfiere,donna,re
.
In seconda riga ci sono le dimensioni della matrice: due interi
positivi separati da spazio. Nelle N
righe sottostanti
ci sono i valori della matrice (int
arbitrari xi,j
). Le righe sono separate andando a capo,
mentre su ogni riga i valori sono separati da uno spazio.
In caso di input malformato non corrispondente a quanto scritto
subito sopra (per esempio, pedone
come pezzo, "matrice"
non rettangolare o non N x M
, valore non intero nella
matrice) non si richiede nessun comportamento particolare. Il
programma può dare un risultato qualunque, o anche generare un
errore a tempo di esecuzione.
Si ribadisce che il formato di file di sopra non garantisce nulla
sui valori degli interi nella matrice (a parte la loro
rappresentabilità in un int
). Una matrice di interi
delle dimensioni date che non è una matrice di mosse non causa la
malformatezza dell'input. Su questi input la funzione deve
obbligatoriamente restituire false
.
Ricordatevi che, quando confrontate due String
in Java
come per esempio i nomi dei pezzi, dovete
usare s1.equals(s2)
e non s1 == s2
.
Si chiede di scrivere una singola classe Java Progetto
,
che contenga la funzione testChessMoves
descritta
sopra. In particolare, è
obbligatorio usare come base per il
progetto un progetto Eclipse contenente il il seguente scheletro di
di classe Java.
La classe scheletro va posizionata in un progetto Eclipse come segue.
Create un progetto Eclipse chiamato cognome_matricola
(usate i vostri dati, per esempio
tramaglino_000001
o
de_paperoni_000002
),
e create la classe Progetto
al suo interno nella cartella
src
. Dovete ottenere un file come segue:
zunino_555555/src/Progetto.java
È obbligatorio rispettare la posizione del file della classe come descritto sopra. Dentro quel file potete quindi inserire il codice dello scheletro fornito.
È tassativamente proibito
modificare lo scheletro
nelle parti segnate al suo interno come da non modificare.
In particolare, non si può modificare il tipo o il nome delle
procedure / funzioni all'interno.
In nessun caso il file consegnato dovrà contenere una dichiarazione
package
.
È invece consentito (e consigliabile) definire delle
procedure/funzioni addizionali all'interno della
classe Progetto
. È consentito aggiungere
import
per usare librerie di Java.
È consentito modificare il metodo main
della classe
nello scheletro. Si noti, tuttavia, che tale metodo
potrà essere cancellato e sovrascritto, o comunque
non eseguito, da chi corregge.
Di conseguenza, se si decidono di usare variabili globali,
queste devono essere inizializzate dentro le funzioni
relative ai due esercizi, e non dentro
il main
, in quanto quest'ultimo non verrà eseguito.
Durante la correzione, le funzioni relative agli esercizi verranno chiamate ripetutamente eseguendo (anche) test automatizzati.
Per potere testare più facilmente il vostro progetto, vi viene fornita la seguente libreria Java.
Aggiornamento: abbiamo corretto un bug nell'helper 1.0, che invertiva il numero delle righe con quelle delle colonne. L'helper 1.1 qui sotto include la correzione.
Dopo avere scaricato il file di sopra in una qualunque cartella,
potete inserire la libreria helper nel vostro progetto Eclipse,
selezionando il vostro progetto,
facendo clic destro,
e selezionando dal menù la voce
Build Path -> Add External Archives...
.
Comparirà un finestra dove potete selezionare
il file jar
fornito sopra.
Dopo avere aggiunto la libreria helper al vostro progetto,
all'interno del file Java Progetto.java
potete usare le funzioni della libreria, che mostriamo sotto.
Nello scheletro di progetto che vi forniamo,
trovate già degli esempi su come usarle nel main()
,
dopo avere usato import progetto2019.Helper;
all'inizio del file.
static void Helper.generateMoveFile(String fileName) static void Helper.generateNonMoveFile(String fileName)
La procedura Helper.generateMoveFile
prende come
parametro un nome di file. La procedura crea un file con quel nome (se
già esistente, viene sovrascritto, quindi state attenti a non
cancellare un file con dati importanti). Il file così creato è un
file random del formato atteso dalla vostra
funzione testChessMoves()
, contenente una matrice di
mosse, e sul quale la vostra funzione deve
restituire true
.
Analogamente, Helper.generateNonMoveFile
compie
un'analoga operazione, creando (sovrascrivendo) un file random nello
stesso formato, ma contenente una matrice di interi che non è una
matrice di mosse. Su questo file la
funzione testChessMoves()
, deve quindi
restituire false
.
Usare l'helper non è obbligatorio (anche se fortemente raccomandato).
Se non lo volete usare, per potere compilare lo scheletro
dovete rimuovere dal file sia la riga
import progetto2019.Helper;
che tutti i riferimenti alle funzioni Helper
.
Nota bene: se usate l'helper un certo numero di volte, e se sui file così generati la vostra funzione fornisce il risultato atteso, questo non vuol dire che la funzione sia corretta in tutti i casi possibili. È possibile che, in fase di valutazione del progetto, vengano controllati altri casi, e che su questi si scopra che il vostro codice non funziona correttamente. In altre parole: con i test possiamo solo dimostrare che un programma è scorretto, ma mai che è corretto.
Il progetto verrà valutato secondo i seguenti criteri, che formano un insieme di requisiti sul codice consegnato. Ogni requisito primario è condizione necessaria per il superamento della prova: anche se uno di questi non viene rispettato, la prova non è superata. I requisiti secondari devono essere generalmente rispettati. Nel caso ci siano solo minori violazioni di tali requisiti, la prova è comunque superata. Violazioni gravi possono comunque causare il non superamento della prova.
Requisiti tecnici (primario). La soluzione consegnata deve seguire lo scheletro di progetto fornito sopra, modificato nel modo descritto sopra.
Devono inoltre essere rispettati questi requisiti:
Progetto
, i nomi o i tipi delle procedure/funzioni
segnate come da non modificare.
Non ci deve essere nessuna dichiarazione di
package
della classe.
Progetto
come descritto
sopra nel vostro progetto eclipse.
new File(fileName)
usa il parametro, mentre
new File("fileName")
usa un nome prefissato.
main
invece può interagire con l'utente, se desiderato
(ma comunque come detto sopra il codice del main
può essere ignorato da noi durante i test.)
Il non rispettare questi requisiti tecnici può causare il fallimento dei nostri test automatizzati, ed in tal caso la prova non sarà superata.
Correttezza (primario).
Non ci devono essere errori a tempo di compilazione: il programma deve
compilare. Non ci devono essere errori a tempo di esecuzione: il
programma non deve generare eccezioni (per
esempio, DivisionByZero
oppure ArrayIndexOutOfBounds
) quando eseguito su un input
ben formato. Il programma deve dare l'output desiderato su qualunque
input compatibile con la specifica.
Nota bene:
Nel caso il programma sia scorretto, non è compito di chi corregge
fare il debugging,
ovvero identificare la causa dell'errore e suggerire una modifica
per rimuoverla. Anche quando tale causa fosse nota a chi corregge,
non verrà comunicata allo studente, in quanto sarebbe come suggerire
una parte non banale della soluzione della prova. Infatti, capita
frequentemente che correggere l'errore dopo averlo
individuato diventi banale ("devo usare x
, e non
x+1
"), e che la prova di conseguenza consista prevalentemente
nella ricerca dell'errore.
Corollario:
se provando il programma su un insieme di input campione si riscontrano
già errori di correttezza, chi corregge non è tenuto ad esaminare
il codice del programma.
Leggibilità (secondario). Il codice deve essere scritto in modo tale da permettere ad un altro programmatore di comprenderne la logica. Non è sufficiente che il codice "funzioni", o che sia chiaro a chi lo ha scritto. Per aiutare la lettura del codice da parte di altri, si consiglia di usare dei nomi di variabile e di funzione appropriati, strutturare il codice adeguatamente (dove ha senso, meglio dividere una funzione lunga in più funzioni ausiliarie), e di inserire dei commenti.
Non commentate come state calcolando qualcosa, commentate piuttosto cosa state calcolando. Per esempio, il seguente commento è altamente inutile:
// incremento i i++;
Al contrario, il seguente aiuta a comprendere il codice:
// passo a coordinate polari rho = Math.sqrt(x*x + y*y); theta = Math.atan2(y, x);
Per potere partecipare allo scritto di un appello di esame, il progetto deve essere consegnato entro le date indicate nell'elenco degli appelli d'esame. La consegna si svolge mandando una email avente esattamente le seguenti caratteristiche.
zunino_555555/src/Progetto.java
zunino_555555/README.txt
Se avete dubbi sul testo del progetto, ovvero su che cosa vi sta venendo chiesto, chiedete pure delucidazioni per email o a ricevimento. Se invece avete dubbi sulla soluzione dell'esercizio, ovviamente non possiamo suggerirvi nulla.
Il progetto non viene svolto in un ambiente "controllato" come per esempio avviene per un esame scritto, ma vi viene lasciata libertà di svolgerlo dove e quando preferite (compatibilmente con le scadenze). Per esempio, potete usare i laboratori quando liberi, o farlo su un vostro computer personale.
Il progetto è individuale, non di gruppo. Tuttavia, vi è consentito discutere del progetto con altre persone per scambiarsi opinioni a riguardo. Non è consentita, ovviamente, la copia di pezzi di codice inerenti al progetto da uno studente all'altro. Allo stesso modo, farsi fare il progetto da un'altra persona è considerato equivalente a copiare. In caso di dubbi sull'autenticità del progetto, ci riserviamo la possibilità di convocarvi per un colloquio sul codice che avete consegnato, anche dopo l'esame scritto.
Vi è consentito di "copiare" invece pezzi di codice che vi abbiamo fornito noi, o di "tradurre in Java" dei pezzi di codice che potreste trovare su qualche libro o tutorial online, e che non siano soluzioni degli esercizi proposti o di una loro parte significativa. Nei casi consentiti dovete obbligatoriamente citare la fonte in un commento nel codice.
Il discutere del progetto su forum di discussione su Internet o simili non è vietato a prescindere, ma è soggetto alle stesse regole della comunicazione tra altri studenti. Inoltre, se iniziate una discussione su un forum riguardo al progetto, dovete obbligatoriamente dichiarare 1) che l'esercizio in questione è un progetto di esame, e 2) che non desiderate che qualcuno vi scriva una soluzione al posto vostro. Se anche chiarendo ciò qualcuno vi risponde includendo del codice, voi non potete includerlo nel progetto.
Se la matrice contiene solo zeri, non è una matrice di mosse e
il risultato del test deve essere
false
. Infatti, dati i vincoli sopra (numero mosse
K>=0
e sequenza di mosse p1,p2,...,pK,p(K+1)
),
qualunque sequenza di mosse contiene almeno la posizione iniziale
p1
, e quindi un (unico) 1
deve essere
sempre presente in una matrice di mosse.
Una matrice con solo zeri tranne per una singola cella con un 1
è una matrice di mosse per qualunque pezzo.
Se preferite, potete usare anche caratteristiche di Java non viste a lezione (costrutti diversi come gli oggetti, librerie non viste a lezione purché incluse tra quelle standard di Java), anche se il progetto si può svolgere benissimo senza. Dovete però comprendere il codice che state usando: se venite chiamati ad un colloquio (vedi sopra) vi può essere chiesto di spiegarlo.
Informatica - Teaching - Home
Roberto Zunino, 2019