ΕΡΓΑΣΤΗΡΙΟ 11 - Απαντήσεις

Σχετικά έγγραφα
printf Οι κωδικοί (format codes) του printf για διάφορους τύπους δεδοµένων είναι:

Λύσεις για τις ασκήσεις του lab5

scanf() scanf() stdin scanf() printf() int float double %lf float

ΣΕΤ ΑΣΚΗΣΕΩΝ 3. Προθεσµία: Τετάρτη 7/12/2016, 21:00

ΣΕΤ ΑΣΚΗΣΕΩΝ 3. Προθεσµία: 18/12/12, 22:00

Βαθμός Σχόλια. lab PASS 1194 PASS 1238 PASS 1239 PASS

ΣΕΤ ΑΣΚΗΣΕΩΝ 3. Προθεσµία: 5/12/10, 23:59

ΣΕΤ ΑΣΚΗΣΕΩΝ 3. Προθεσµία: Πέµπτη 17/12/2015, 22:00

Βαθμός Σχόλια. lab5 PASS PASS PASS PASS PASS. Οριακά PASS - Καλή δουλειά

ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ ΥΠΟΛΟΓΙΣΤΩΝ & ΥΠΟΛΟΓΙΣΤΙΚΗ ΦΥΣΙΚΗ

Βαθμός Σχόλια. lab6 PASS PASS. - Πολύ καλή δουλειά, αλλά προσπάθησε να κάνεις την άσκηση χρησιµοποιώντας συναρτήσεις από το string.

Επαναληπτικές δοµές. µτ α.τ. Όχι. ! απαγορεύεται µέσα σε µία ΓΙΑ να µεταβάλλουµε τον µετρητή! διότι δεν θα ξέρουµε µετά πόσες επαναλήψεις θα γίνουν

ΣΕΤ ΑΣΚΗΣΕΩΝ 4. Προθεσµία: 13/1/13, 22:00

ΣΕΤ ΑΣΚΗΣΕΩΝ 4. Προθεσµία: 22/12/2016, 21:00

Κεφάλαιο Αλφαριθµητικές Σειρές Χαρακτήρων (Strings)

ΠΑΝΕΠΙΣΤΗΜΙΟ ΘΕΣΣΑΛΙΑΣ ΣΧΟΛΗ ΘΕΤΙΚΩΝ ΕΠΙΣΤΗΜΩΝ ΤΜΗΜΑ ΠΛΗΡΟΦΟΡΙΚΗΣ

Στη C++ υπάρχουν τρεις τύποι βρόχων: (a) while, (b) do while, και (c) for. Ακολουθεί η σύνταξη για κάθε μια:

Sheet2 Α.Μ FAIL. οριακό PASS. - Έπρεπε να χρησιµοποιήσετε συναρτήσεις από τη string.h

Πρόβληµα : Πώς θα λύναµε αυτό το πρόβληµα αν είχαµε µόνο χαρτί και µολύβι, και κάποιος µας έλεγε τους αριθµούς προφορικά?

ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ Η/Υ Ακαδημαϊκό έτος ΤΕΤΡΑΔΙΟ ΕΡΓΑΣΤΗΡΙΟΥ #4

ΕΝΤΟΛΕΣ ΕΠΑΝΑΛΗΨΗΣ. for (παράσταση_1; παράσταση_2; παράσταση_3) εντολή επόμενη εντολή

Κεφάλαιο 5ο: Εντολές Επανάληψης

Προγραµµατισµός Ι ΕΡΓΑΣΤΗΡΙΟ 5 ΕΡΓΑΣΤΗΡΙΟ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ I, ΑΚΑΔΗΜΑΪΚΟ ΕΤΟΣ

Γλώσσα Προγραμματισμού C. Προγραμματισμός HY: Γλώσσα Προγραμματισμού C. Γρήγορος Πίνακας Αναφοράς Σύνταξης. Εισήγηση #4. Επαναληπτικές δομές:

Πανεπιστήµιο Θεσσαλίας, THMMY HY120, Σεπτέµβριος 2015 ΟΝΟΜΑΤΕΠΩΝΥΜΟ:

ΣΕΤ ΑΣΚΗΣΕΩΝ 3. Προθεσµία: 7/1/2014, 22:00

ΣΕΤ ΑΣΚΗΣΕΩΝ 2. Προθεσµία: 15/11/10, 23:59

for for for for( . */

ΘΕΜΑΤΑ ΕΞΕΤΑΣΗΣ ΚΑΙ ΑΠΑΝΤΗΣΕΙΣ

ΣΕΤ ΑΣΚΗΣΕΩΝ 4. Προθεσμία: 17/1/14, 22:00

Προγραμματισμός Ι (ΗΥ120)

Πίνακες. 1 Πίνακες. 30 Μαρτίου 2014

Η πρώτη παράμετρος είναι ένα αλφαριθμητικό μορφοποίησης

Εισαγωγή στον Προγραµµατισµό. Πανεπιστήµιο Θεσσαλίας Τµήµα Ηλεκτρολόγων Μηχανικών και Μηχανικών Η/Υ

lab13grades Άσκηση 2 -Σωστά απελευθερώνετε ολόκληρη τη λίστα και την κεφαλή

Κεφάλαιο 8.7. Πολυδιάστατοι Πίνακες ( ιάλεξη 18) ιδάσκων: ηµήτρης Ζεϊναλιπούρ

Sheet2. Σωστή, και µπράβο που µεριµνήσατε για λίστες διαφορετικών µεγεθών.

Εισαγωγή στον Προγραμματισμό

H ΓΛΩΣΣΑ C. Μάθηµα 7: Πίνακες. ηµήτρης Ψούνης

ΣΕΤ ΑΣΚΗΣΕΩΝ 4. Προθεσµία: 8/1/12, 22:00

ΑΣΚΗΣΗ 2: ΔΟΜΗ ΠΡΟΓΡΑΜΜΑΤΟΣ C, ΧΕΙΡΙΣΜΟΣ ΜΕΤΑΒΛΗΤΩΝ ΚΑΙ ΣΥΝΑΡΤΗΣΕΙΣ ΕΙΣΟΔΟΥ ΚΑΙ ΕΞΟΔΟΥ

Οι εντολές ελέγχου της ροής ενός προγράμματος.

Παράδειγμα 2. Λύση & Επεξηγήσεις. Τέλος_επανάληψης Εμφάνισε "Ναι" Τέλος Α2

int array[10]; double arr[5]; char pin[20]; Προγραµµατισµός Ι

3ο σετ σημειώσεων - Πίνακες, συμβολοσειρές, συναρτήσεις

Εισαγωγή στους Αλγόριθμους και τον Προγραμματισμό. 3η Διάλεξη Είσοδος Δεδομένων Συνθήκες Βρόχοι Παραδείγματα

ΣΕΤ ΑΣΚΗΣΕΩΝ 2. Προθεσµία: 15/11/09, 23:59

Επεξεργασία Αρχείων Κειµένου

lab7 PASS -Δεν έχεις καθόλου σχόλια! Διάβασε το φυλλάδιο. PASS -Πολύ καλή εργασία µε σωστά και επεξηγηµατικά σχόλια. -Πρόσεξε την στοίχισή σου!

ΣΕΤ ΑΣΚΗΣΕΩΝ 1. Προθεσµία: 3/12/2018, 23:59

Παρακάτω δίνεται o σκελετός προγράμματος σε γλώσσα C. Σχολιάστε κάθε γραμμή του κώδικα.

Διάλεξη 3η: Τύποι Μεταβλητών, Τελεστές, Είσοδος/Έξοδος

ΠΑΝΕΠΙΣΤΗΜΙΟ ΘΕΣΣΑΛΙΑΣ ΣΧΟΛΗ ΘΕΤΙΚΩΝ ΕΠΙΣΤΗΜΩΝ ΤΜΗΜΑ ΠΛΗΡΟΦΟΡΙΚΗΣ

ΣΕΤ ΑΣΚΗΣΕΩΝ 2. Προθεσµία: 25/11/12, 22:00

ΣΕΤ ΑΣΚΗΣΕΩΝ 3 ΕΡΓΑΣΤΗΡΙΟ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ I, ΑΚΑΔΗΜΑΪΚΟ ΕΤΟΣ Προθεσµία: 10/12/2014, 22:00

ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ Η/Υ Ακαδημαϊκό έτος ΤΕΤΡΑΔΙΟ ΕΡΓΑΣΤΗΡΙΟΥ #5

H ΓΛΩΣΣΑ C. Μάθηµα 15: Είσοδος/Έξοδος: Συναρτήσεις Εισόδου. ηµήτρης Ψούνης

ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ Η/Υ Ακαδημαϊκό έτος ΤΕΤΡΑΔΙΟ ΕΡΓΑΣΤΗΡΙΟΥ #3

CE 120. Φροντιστήριο 14/10/2011

EΒ ΟΜΑ Α 4 Η. οµές επανάληψης while και do while

Κεφάλαιο 8.7. Πίνακες & Συναρτήσεις ( ιάλεξη 17) ιδάσκων: ηµήτρης Ζεϊναλιπούρ

lab14grades ΑΕΜ ΒΑΘΜΟΣ ΣΧΟΛΙΑ

6. ΠΙΝΑΚΕΣ & ΑΛΦΑΡΙΘΜΗΤΙΚΑ

char name[5]; /* define a string of characters */

H ΓΛΩΣΣΑ C. Μάθηµα 1: Το Πρώτο µας Πρόγραµµα σε C. ηµήτρης Ψούνης

Εισαγωγή στην C. Μορφή Προγράµµατος σε γλώσσα C

ΣΕΤ ΑΣΚΗΣΕΩΝ 1. Προθεσµία: Τρίτη 10/11/2015, 22:00

Οικονοµικό Πανεπιστήµιο Αθηνών. Τµήµα Πληροφορικής. Φθινοπωρινό Εξάµηνο Δοµές Δεδοµένων - Εργασία 2. Διδάσκων: E. Μαρκάκης

Γλώσσα Προγραμματισμού C

lab7grades -Σωστή χρήση της sprintf -Σωστά ανιχνεύετε τον χαρακτήρα που πρέπει να αφαιρέσετε. -Σωστή µεταφορά στοιχείων µια θέση αριστερά.

Κεφάλαιο 8.6. Πίνακες ΙI ( ιάλεξη 16) ιδάσκων: ηµήτρης Ζεϊναλιπούρ

Προγραµµατισµός Ι ΕΡΓΑΣΤΗΡΙΟ 3 ΕΡΓΑΣΤΗΡΙΟ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ I, ΑΚΑΔΗΜΑΪΚΟ ΕΤΟΣ

Α. unsigned int Β. double. Γ. int. unsigned char x = 1; x = x + x ; x = x * x ; x = x ^ x ; printf("%u\n", x); Β. unsigned char

ΠΡΟΓΡΜΜΑΤΑ ΣΕ C. Γράψτε σε γλώσσα προγραμματισμού C τη συνάρτηση:

ΣΕΤ ΑΣΚΗΣΕΩΝ 2. Προθεσµία: 27/11/11, 22:00

lab10grades - Το αποτέλεσµα της τοµής θα έπρεπε να εµφανίζετε µέσα σε εισαγωγικά "Helo".

Κεφάλαιο 8.7. Πολυδιάστατοι Πίνακες (Διάλεξη 19)

ΣΕΤ ΑΣΚΗΣΕΩΝ 4 ΕΡΓΑΣΤΗΡΙΟ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ I, ΑΚΑΔΗΜΑΪΚΟ ΕΤΟΣ Προθεσµία: 9/1/2015, 22:00

Εισαγωγή στον Προγραµµατισµό. Διάλεξη 3 η : Επίλυση Προβληµάτων Χειµερινό Εξάµηνο 2011

C: Από τη Θεωρία στην Εφαρµογή 2 ο Κεφάλαιο

Προγραμματισμός Ι. Είσοδος/Έξοδος. Δημήτρης Μιχαήλ. Ακ. Έτος Τμήμα Πληροφορικής και Τηλεματικής Χαροκόπειο Πανεπιστήμιο

Επανάληψη για τις Τελικές εξετάσεις. (Διάλεξη 24) ΕΠΛ 032: ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ ΜΕΘΟΔΩΝ ΕΠΙΛΥΣΗΣ ΠΡΟΒΛΗΜΑΤΩΝ

Επανάληψη για τις Τελικές εξετάσεις

Κεφάλαιο : Επαναλήψεις (for, do-while)

Η γλώσσα προγραμματισμού C

Προγραµµατισµός Ι ΕΡΓΑΣΤΗΡΙΟ 2 ΕΡΓΑΣΤΗΡΙΟ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ I, ΑΚΑΔΗΜΑΪΚΟ ΕΤΟΣ

Ο πιο κάτω πίνακας περιγράφει σε ποιες περιπτώσεις χρησιμοποιούμε τους τρεις πιο πάνω τρόπους:

Προγραµµατισµός Ι ΕΡΓΑΣΤΗΡΙΟ 5 ΕΡΓΑΣΤΗΡΙΟ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ I, ΑΚΑΔΗΜΑΪΚΟ ΕΤΟΣ

Προγραμματισμός Η/Υ Ι (Χρήση της C) 6 η Θεωρία ΜΟΝΟΔΙΑΣΤΑΤΟΙ ΠΙΝΑΚΕΣ

ΑΝΑΠΤΥΞΗ ΕΦΑΡΜΟΓΩΝ Κεφάλαιο 2 ο Να περιγραφεί η δομή επανάληψης Αρχή_επανάληψης Μέχρις_ότου

Κεφάλαιο Αλφαριθμητικές Σειρές Χαρακτήρων (Strings) (Διάλεξη 20) 1) Strings στη C

Διδάσκων: Κωνσταντίνος Κώστα Διαφάνειες: Δημήτρης Ζεϊναλιπούρ

3 ο Εργαστήριο Μεταβλητές, Τελεστές

2ο ΓΕΛ ΑΓ.ΔΗΜΗΤΡΙΟΥ ΑΕΠΠ ΘΕΟΔΟΣΙΟΥ ΔΙΟΝ ΠΡΟΣΟΧΗ ΣΤΑ ΠΑΡΑΚΑΤΩ

ΗΜΙΟΥΡΓΙΑ ΠΑΙΧΝΙ ΙΟΥ ΣΤΟ SCRATCH ΒΗΜΑ ΠΡΟΣ ΒΗΜΑ

Διαδικασιακός Προγραμματισμός

Δομημένος Προγραμματισμός

Εντολές Επανάληψης. int sum = 0, i=1; sum += i++ ; sum += i++ ; Η πράξη αυτή θα πρέπει να επαναληφθεί Ν φορές!

ΣΕΤ ΑΣΚΗΣΕΩΝ 1. Προθεσµία: Τρίτη 4/11/2014, 22:00

Προγραμματισμός Η/Υ (ΤΛ2007 )

Transcript:

Με µαύρο τα κοµµάτια από την εκφώνηση. Με µπλε απαντήσεις κι επεξηγήσεις. Με κόκκινο τα πιο συχνά λάθη που είδαµε. Άσκηση Παρασκευής ΕΡΓΑΣΤΗΡΙΟ 11 - Απαντήσεις Σε αυτή την άσκηση θα γράψετε ένα πρόγραµµα που αποθηκεύει πληροφορίες για τους χαρακτήρες ενός παιχνιδιού (sprites) και τη θέση τους στην οθόνη. Κατασκευάστε ένα struct το οποίο αναπαριστά ένα sprite. Για την ακρίβεια, περιέχει τα πεδία: ζωή (ακέραιος) όνοµα χαρακτήρα (συµβολοσειρά, δεν περιέχει κενά, µέγιστο µέγεθος NAME_SIZE) συντεταγµένες πάνω αριστερά γωνίας (ακέραιοι) συντεταγµένες κάτω δεξιά γωνίας (ακέραιοι) Κατασκευάζουµε το παρακάτω struct: struct spritet { int life; char name[name_size]; int left_x, left_y, right_x, right_y; ; Για το NAME_SIZE βλέπουµε πιο κάτω στην εκφώνηση ότι προτείνεται η τιµή 100, οπότε προσθέτουµε στο πρόγραµµά µας και το απαραίτητο #define. Γράψτε µια συνάρτηση main στην οποία: ορίζετε ένα πίνακα από sprites, µεγέθους MAX_SLOTS Εφόσον χρειαζόµαστε πίνακα για να αποθηκεύσουµε τα στοιχεία των sprites, και ένα sprite αναπαρίσταται από τον τύπο struct sprite που κατασκευάσαµε, θα ορίσουµε πίνακα από struct spritet: struct spriteτ slots[max_slots]; Προσθέτουµε στο πάνω µέρος του αρχείου και το #define για το MAX_SLOTS. Μέχρι να γεµίσει ο πίνακας ή να µην υπάρχουν άλλα δεδοµένα, Εδώ χρειάζεται µια επανάληψη, εφόσον µας λέει "µέχρι να γεµίσει ο πίνακας". Το "δεν υπάρχουν άλλα δεδοµένα" το αφήνουµε προς το παρόν και θα ασχοληθούµε µε αυτό αργότερα. Η ουσιαστική παρατήρηση εδώ είναι ότι το πότε θα τελειώσει η επανάληψη δεν εξαρτάται αποκλειστικά από την τιµή κάποιου µετρητή, αλλά και από κάποιο γεγονός (αν υπάρχουν άλλα δεδοµένα), άρα είναι πιο κατάλληλη η χρήση while ή dowhile. Επιλέγουµε do-while διότι τουλάχιστον µία φορά θα ερωτηθεί ο χρήστης του προγράµµατος και θα τρέξει το πρόγραµµα. Για να ξέρουµε πότε γέµισε ο πίνακας, θα κρατήσουµε ένα µετρητή για το πόσες καταχωρήσεις έχουν γίνει µέχρι στιγµής. Αρχικά έχουµε µηδέν καταχωρήσεις. Άρα, int num_sprites = 0; while (num_sprites < MAX_SLOTS);

Δηµιουργεί µια προσωρινή µεταβλητή τύπου struct sprite στην οποία θα αποθηκεύσει τα παρακάτω δεδοµένα πριν ελέγξει αν πρέπει ή όχι να εισαχθούν στον πίνακα. Πριν εισάγουµε ένα νέο sprite στον πίνακα, πρέπει να έχουµε επιβεβαιώσει ότι δεν υπάρχει επικάλυψη µε άλλο sprite στον χώρο. Εποµένως, δε γίνεται να αποθηκεύουµε τα δεδοµένα απευθείας στον πίνακα. Πρέπει να τα βάλουµε σε µια προσωρινή µεταβλητή, κι αν τελικά δούµε ότι πρέπει να αποθηκευτούν, τα αντιγράφουµε. struct spritet new_sprite; εκτυπώνει το µήνυµα Enter sprite name: και διαβάζει το όνοµα του sprite. Το όνοµα του sprite δεν έχει κενά σύµφωνα µε τις προδιαγραφές που δόθηκαν νωρίτερα, εποµένως µπορούµε να χρησιµοποιήσουµε scanf. Είναι δεκτή και η χρήση fgets, αν θεωρήσουµε ότι κάθε στοιχείο δίνεται σε νέα γραµµή, αλλά πρέπει να προσέξουµε: Πριν την fgets χρειάζεται µια getchar για να καταναλώσει το \n που έχει ξεµείνει από την είσοδο του κωδικού νωρίτερα. Η scanf δε χρειάζεται κάτι τέτοιο. ΠΡΟΣΟΧΗ: Εδώ έγιναν αρκετά λάθη στις ασκήσεις που είδαµε. Διαβάζουµε συµβολοσειρά, εποµένως πρέπει να δώσουµε κατάλληλο format string ώστε να διαβαστεί σωστά και να µην υπάρχει πιθανότητα για buffer overflow. Λάθος 1: scanf("%s", new_sprite.name); Δεν υπάρχει όριο στο format string και µπορεί να διαβαστεί µεγαλύτερο string από όσο χώρο έχουµε στο course_name. Λάθος 2: scanf("%100s", new_sprite.name); Yπάρχει όριο στο format string αλλά είναι λάθος. Επιτρέπει να διαβαστούν µέχρι και 100 χαρακτήρες, το οποίο σηµαίνει ότι το \0 θα αποθηκευτεί στη θέση 101, ένα byte έξω από τα όρια του πίνακα. Λάθος 3: scanf("%s", &new_sprite.name); Η scanf παίρνει ως παράµετρο τη διεύθυνση στην οποία θέλουµε να µας αποθηκεύσει αυτό που διάβασε. Το new_sprite.name είναι ήδη η διεύθυνση στην οποία θα αποθηκευτεί το string, εποµένως δε βάζουµε & Το σωστό είναι να καταστευαστεί ένα format string µε χρήση της sprintf όπως έχουµε δει στο µάθηµα κι έχουµε κάνει σε προηγούµενα εργαστήρια. Κάντε το! εκτυπώνει χαρακτήρα αλλαγής γραµµής και το µήνυµα Enter life points: και διαβάζει τον κωδικό µιας αίθουσας. printf("\nenter life points: "); scanf("%d", &new_sprite.life); εκτυπώνει το µήνυµα Enter bounding box lx,ly-rx,ry: εκτυπώνει το µήνυµα Enter bounding box lx,ly-rx,ry: και διαβάζει τις συντεταγµένες του νοητού ορθογωνίου που περικλείει το sprite. Οι συντεταγµένες δίνονται µε τη µορφή lx,ly-rx,ry όπου lx,ly είναι η πάνω αριστερά γωνία και rx,ry η κάτω δεξιά. Η scanf λειτουργεί προσπαθώντας να ταιριάξει αυτό που προσδιορίσαµε στο format string µε αυτό που βλέπει να έρχεται από το πληκτρολόγιο. Εφόσον εµείς πρόκειται να γράψουµε στο πληκτρολόγιο έναν ακέραιο, ένα κόµµα, έναν ακέραιο, µια παύλα και ξανά έναν ακέραιο, ένα κόµµα, έναν ακέραιο, αυτό ακριβώς πρέπει να προσδιορίσουµε και στο format string: scanf("%d,%d-%d,%d", &new_sprite.left_x, &new_sprite.left_y, &new_sprite.right_x, &new_sprite.right_y); Ελέγχει αν υπάρχει άλλο sprite που καταλαµβάνει τον ίδιο χώρο. Αν ναι, τότε το νέο sprite ΔΕΝ εισάγεται, αλλά κάθε ήδη υπάρχον που επικαλύπτεται απο το νέο ΚΑΙ έχει χαµηλότερη ζωή από το νέο, χάνει ένα πόντο ζωής (εφόσον αυτή είναι θετική) και το πρόγραµµα εκτυπώνει το µήνυµα "A" beat "B" (L) ακολουθούµενο από χαρακτήρα αλλαγής γραµµής. Α είναι το όνοµα του νέου sprite, Β του ήδη υπάρχοντος και L η ζωή του B. Μην ξεχάσετε τα " " γύρω από το κάθε όνοµα. Αν όχι, τότε το νέο sprite εισάγεται στην επόµενη διαθέσιµη θέση του πίνακα και το πρόγραµµα εκτυπώνει το µήνυµα Added "A" (L) ακολουθούµενο από χαρακτήρα αλλαγής γραµµής όπου Α το όνοµα του νέου sprite και L η ζωή του.

Εδώ είναι το αλγοριθµικό κοµµάτι της άσκησης: Έχουµε ένα νέο sprite. Το αν θα καταχωρηθεί στον πίνακα η όχι, εξαρτάται από το αν υπάρχουν επικαλύψεις µε άλλα sprites. Άρα σίγουρα πρέπει να ελέγξουµε την επικάλυψη του µε τα υφιστάµενα sprites που είναι αποθηκευµένα στον πίνακα Ένα συχνό λάθος που γινόταν εδώ ήταν να πηγαίνει το loop µέχρι MAX_SLOTS. Αυτό δεν έχει νόηµα και θα βγάλει λάθος αποτελέσµατα γιατί οι θέσεις του πίνακα από το num_slots µέχρι το MAX_SLOTS περιέχουν σκουπίδια. Για να δούµε τώρα τι πάει µέσα στο loop. Γνωρίζουµε ότι αν υπάρχει έστω και µια επικάλυψη µε άλλο sprite, δε µπορεί να γίνει η κράτηση, και δε χρειάζεται να συνεχίσουµε τον έλεγχο. Η συνθήκη ελέγχου είναι η άρνηση της συνθήκης ελέγχου που περιγράφεται στην τελευταία σελίδα της εκφώνισης. Άρα: if(!(new_sprite.left_x > sprites[i].right_x sprites[i].left_x > new_sprite.right_x new_sprite.left_y < sprites[i].right_y sprites[i].left_y < new_sprite.right_y) ) { /* μείωση της ζωής κατά 1 ΜΟΝΟ για τα sprites με χαμηλότερη ζωή */ if( new_sprite.life > sprites[i].life) { sprites[i].life -; printf("\ %s\ beat \ %s\ (%d)", new_sprite.name, sprites[i].name, sprites[i].life); /* εκτύπωση µηνυµατος για overlap */ break; /* γιατί δεν χρειάζεται να κάνουµε άλλους ελέγχους */ Αυτό τακτοποιεί την περίπτωση που ανιχνεύουµε επικάλυψη. Να δούµε τώρα την περίπτωση που δεν υπάρχει. Για να ξέρουµε στα σίγουρα ότι δεν υπαρχει καµία επικάλυψη, πρέπει να έχουµε ελέγξει ΟΛΕΣ τις ήδη υπάρχουσες καταχωρήσεις και να µην έχουµε βρει κάτι. Με άλλα λόγια, πρέπει να έχει τελειώσει η εκτέλεση του for και να έχουµε βγει κανονικά (όχι από το break). Πώς µπορούµε να ξεχωρίσουµε αν το loop τερµάτισε πρόωρα (λόγω break) ή κανονικά (λόγω συνθήκης)? Αν έχει βγει λόγω break τότε το i θα είναι σίγουρα µικρότερο του num_sprites. Αν έχει βγει λόγω συνθήκης, τότε βγήκε ακριβώς τη στιγµή που η συνθήκη έγινε ψευδής, δηλαδή όταν το i έγινε ίσο µε num_reserved. Αν λοιπόν συνέβη αυτό, αποθηκεύουµε στον πίνακα το νέο sprite, εκτυπώνουµε το µήνυµα και αυξάνουµε τον αριθµό των κρατήσεων. Παρατηρήστε πώς εφόσον έχουµε ακριβώς num_sprites κρατήσεις, αυτές βρίσκονται στις θέσεις 0 έως και num_sprites-1 του πίνακα, άρα η νέα κράτηση θα µπει στη θέση num_sprites. if (i == num_sprites) { sprite[num_sprites] = new_sprite; num_sprites++; printf("added \ %s\ (%d)\n", new_sprite.name, new_sprite.life);

Ένα πολύ συχνό ΛΑΘΟΣ εδώ ήταν το παρακάτω: if (/* επικάλυψη */) { printf("..."); /* εκτύπωση µηνυµατος για overlap */ break; else { /* όχι επικάλυψη */ slots[num_sprites] = new_sprite; num_sprites++; printf("...\n"); Σε αυτό τον κώδικα παίρνουµε τελική απόφαση για το αν πρέπει να γίνει καταχώρηση του νέου sprite η όχι από το ΠΡΩΤΟ στοιχείο που ελέγχουµε. Πιθανόν ελέγχοντας το πρώτο sprite να µην υπάρχει επικάλυψη, αλλά να υπάρχει στο δεύτερο ή στο τρίτο κ.ο.κ. πράγµα που ο παραπάνω κώδικας αγνοεί. Καλεί µια συνάρτηση η οποία παίρνει ως παραµέτρους τον πίνακα κρατήσεων και το πλήθος κρατήσεων κι εκτυπώνει τα περιεχόµενά του (δείτε πώς παρακάτω). Ας αφήσουµε προς το παρόν τη συνάρτηση για µετά... Εκτυπώνει το µήνυµα More (y/n)? και διαβάζει ένα χαρακτήρα. Αν αυτός είναι y ή Y, συνεχίζει η επανάληψη, αν είναι n ή N τερµατίζει η είσοδος δεδοµένων, ενώ σε κάθε άλλη περίπτωση επαναλαµβάνει αυτό το βήµα. Εδώ θέλουµε µια µικρή επανάληψη που να διαβάζει ένα χαρακτήρα από το χρήστη, και βεβαιώνει ότι είναι ένας εν των n, N, y, N. Για να µην έχουµε τεράστια συνθήκη, µπορούµε να µετατρέπουµε πάντα το χαρακτήρα σε µικρό αφού τον διαβάσουµε, ώστε να ελέγχουµε µόνο για n, y: scanf(" %c", &go_on); go_on = tolower(go_on); while (go_on!= 'y' && go_on!= 'n'); Συχνά λάθη εδώ: Λάθος 1: Πολλοί ξέχναγαν το κενό πριν το %c, παρόλο που είναι κάτι που έχει εξηγηθεί σε αρκετά προηγούµενα εργαστήρια! Λάθος 2: Χρήση αντί για && στη συνθήκη, µε αποτέλεσµα να µη λειτουργεί σωστά. Αν βάλουµε και το go_on είναι για παράδειγµα 'y', τότε το go_on!= 'n' θα βγει αληθές και η επανάληψη θα συνεχίσει, ενώ δεν πρέπει! Εναλλακτικά, µπορείτε να γράψετε scanf(" %c", &go_on); go_on = tolower(go_on); while (!(go_on == 'y' go_on == 'n')); Εδώ επανερχόµαστε στη συνθήκη τερµατισµού του εξωτερικού while. Το loop συνεχίζει να εκτελείται εφόσον το go_on είναι y. Μπορούµε είτε να προσθέσουµε µια συνθήκη if σε αυτό το σηµείο που να κάνει break αν το go_on είναι 'n' είτε να προσθέσουµε στην αρχική συνθήκη του while το && ( go_on == 'y') δηλ. while (num_sprites < MAX_SLOTS && ( go_on == 'y');.

Γράψτε µια συνάρτηση η οποία παίρνει ως παραµέτρους τον πίνακα από sprites και το πλήθος τους κι εκτυπώνει χαρακτήρα αλλαγής γραµµής, µετά τα έγκυρα περιεχόµενα του πίνακα όπως περιγράφουµε πιο κάτω, και τέλος πάλι χαρακτήρα αλλαγής γραµµής: Για κάθε χαρακτήρα παιχνιδιού εκτυπώνει το µήνυµα N: L (LX,LY)-(RX,RY) ακολουθούµενο από χαρακτήρα αλλαγής γραµµής, όπου N το όνοµα του χαρακτήρα, L οι πόντοι ζωής του, και LX,LY κι RX,RY οι συντεταγµένες της πάνω αριστερά και κάτω δεξιά γωνίας αντίστοιχα. Δεδοµένης της παραπάνω περιγραφής, το prototype της συνάρτησης θα είναι: void print_sprites(struct spritet s[], int size) { int i; printf("\n"); for(i=0; i<size; i++) { printf("%s: %d (%d,%d)-(%d,%d)\n", s[i].name, s[i].life, s[i].left_x, s[i].left_y, s[i].right_x, s[i].right_y); printf("\n"); Ολοκληρώνουµε την υλοποίησή της, η οποία διατρέχει τον πίνακα µέχρι το num_reserved κι εκτυπώνει τα στοιχεία των κρατήσεων, και την καλούµε στη main, στο σηµείο που ζητά η εκφώνηση: print_reservations(slots, num_sprites); Συχνά λάθη εδώ ήταν παντελής άγνοια του πώς περνάµε πίνακα ως παράµετρο συνάρτησης (παρόλο που το κάναµε στο lab10) και κλήση της συνάρτησης σε λάθος σηµείο: πρέπει να εκτελείται σε κάθε επανάληψη, ακριβώς πριν εκτυπωθεί το µήνυµα More (y/n)? και όχι µόνο µια φορά στο τέλος του προγράµµατος. Παρατηρήσεις: Χρησιµοποιήστε 100 για NAME_SIZE και 10 για MAX_SLOTS.