Δημοσιεύτηκε: 05 Μαρ 2012, 02:18
από migf1
Ilias95 έγραψε:
Θα μπορούσε να γίνει one-liner:
Spoiler: show
Μορφοποιημένος Κώδικας: Επιλογή όλων
_Bool pos_isblocked( const int pos, const char tab[] )
{
return (ROW(pos) == 0 || '.' != tab[POSUP(pos)]) && (ROW(pos) == NROWS-1 || '.' != tab[POSDN(pos)]) && (COL(pos) == 0 || '.' != tab[POSLF(pos)]) && (COL(pos) == NCOLS-1 || '.' != tab[POSRT(pos)]);
}

Έτσι θα επιστέψει αμέσως μόλις βρει μία κατεύθυνση που δεν είναι μπλοκαρισμένη.

Yeap :)
Επειδή όμως δεν είμαι σε θέση τώρα να κάνω εκτεταμένο debugging (έχω κοπανήσει κάτι ούζα :lol:) αφήνω και την συνάρτηση στον κώδικα, σε περίπτωση που παρουσιάσει προβλήματα το one-liner ... το οποίο, btw, το υλοποίησα ως macro...
1η πλήρης λύση της άσκησης: http://ideone.com/5bsaB

Τώρα, έφτιαξα και μια 2η υλοποίηση της άσκησης, η οποία θεωρητικά εκτελείται πολύ ταχύτερα (αλλά όπως είπα και πριν, δεν είμαι τώρα σε θέση να κάνω benchmarks, λόγω ούζων :lol:) ...
2η πλήρης λύση της άσκησης (ταχύτερη και πιο λιτή): http://ideone.com/fT57L

Αυτή η 2η υλοποίηση λειτουργεί ως εξής:

Για κάθε τετράγωνο στη θέση pos που επισκέπτεται, καλεί την συνάρτηση...
Μορφοποιημένος Κώδικας: Επιλογή όλων
int avail_count( const int pos, const char tab[], int avail[ NDIRS ] )
η οποία αποθηκεύει μέσα στον πίνακα avail[ NDIRS ] τις θέσεις των ελεύθερων γειτονικών τετραγώνων, κι επιστρέφει το πλήθος τους στη μεταβλητή: navail.

Αν το επιστρεφόμενο πλήθος είναι 0, τότε σημαίνει πως όλα τα γειτονικά τετράγωνα ήταν μπλοκαρισμένα, οπότε τερματίζεται το loop. Αλλιώς, επιλέγεται τυχαία μια θέση του πίνακα avail[NDIRS] από την 0 έως την navail-1 : ( rand() % navail ) και το περιεχόμενο της εκχωρείται στην μεταβλητή pos...
Μορφοποιημένος Κώδικας: Επιλογή όλων
pos = avail[ rand() % navail ];

Η pos είναι πλέον η νέα θέση στον βασικό μας πίνακα tab[] ;)

ΥΓ1. Το const Ηλία απλώς εγγυάται πως τα περιεχόμενα της μεταβλητής δεν μπορούν να αλλάξουν, ούτε και κατά λάθος. Οποιαδήποτε απόπειρα μεταβολής στην τιμή μιας μεταβλητής που έχει οριστεί με πρόθεμα const προκαλεί compiler-error (constant σημαίνει σταθερά, και σε ορισμένες περιπτώσεις μπορείς να τα σκεφτείς ως εναλλακτικές επιλογές των #define ).

Π.χ. στην 2η λύση έχω χρησιμοποιήσει const για να ορίσω την μεταβλητή: NMOVES ίση με το μήκος του string USED (τα γράμματα της αλφαβήτου). Αν το είχα ορίσει με #define στον προ-επεξεργαστή, τότε στη συνθήκη του while-loop...

Μορφοποιημένος Κώδικας: Επιλογή όλων
while ( imove < NMOVES ) ...

θα έτρεχε συνεχώς η συνάρτηση strlen() σε ΚΑΘΕ επανάληψη του loop (η strlen() διατρέχει όλους τους χαρακτήρες του string-ορίσματός της, μέχρι να συναντήσει μηδενικό χαρακτήρα κι επιστρέφει το πλήθος τους). Ο προ-επεξεργαστής κάνει απλό search & replace στον κώδικά σου ότι του έχεις ορίσει στα #define, πριν ξεκινήσει το compilation.

Δηλαδή στην προκειμένη περίπτωση, αν είχα ορίσει το NMOVES με #define...
Μορφοποιημένος Κώδικας: Επιλογή όλων
#define NMOVES   strlen(USED)

τότε η συνθήκη στο while θα μεταφραζόταν ΠΡΙΝ το compilation έτσι...
Μορφοποιημένος Κώδικας: Επιλογή όλων
while ( imove < strlen(USED) ) ...

μέτρημα του μήκους του USED σε κάθε επανάληψη!

Αντίθετα, ορίζοντάς το σαν κανονική μεταβλητή που την αρχικοποιώ ίση με strlen(USED) εξασφαλίζω αφενός πως θα μετρηθεί μια και μόνη φορά το μήκος του USED και θα χρησιμοποιηθεί πλέον ως απλή τιμή στη συνθήκη του loop, και αφετέρου πως η τιμή της NMOVES δεν πρόκειται να αλλάξει καθόλη τη διάρκεια του προγράμματος, ούτε και κατά λάθος.

Υπάρχουν κι άλλες και ουσιώδεις διαφορές μεταξύ const και #define, αλλά υποθέτω θα τα καταλάβεις καλύτερα όταν φτάσεις στο κεφάλαιο που μιλάει αποκλειστικά για τον προ-επεξεργαστή.

ΥΓ2. Όντως πολύ ωραία η άσκηση :)