Προς το περιεχόμενο

[C] - Minesweeper clone


bnvdarklord

Προτεινόμενες αναρτήσεις

2) Υπάρχει καλύτερος τρόπος να μειωθούν οι global μεταβλητές χωρίς να αρχικοποιούνται στο windows layer; Ρωτάω επειδή δεν μου πολυαρέσει η ιδέα να πρέπει το windows layer να ασχολείται με οτιδήποτε τελείως άσχετο με αυτό.(ίσως ενα struct game_state που να εχει μεσα ότι εχω σαν global ετσι ώστε απλά να περνάει αυτο το windows layer και να μην χρειάζεται συνεχως αλλαγες ; ) Και σαν επιπλέον ερώτηση - γιατί οι global μεταβλητές θεωρούνται κακή πρακτική;

Δεν έχω να πω κάτι πάνω σε αυτό το project. Έχω όμως ζήσει τρομερές

στιγμές με global μεταβλητές. Για παράδειγμα, είχα ένα project για fortran

compiler. Άντε έλεγα, δε θα σκεφτώ πως θα σχεδιάσω αυτό τη λειτουργη-

κότητα ορθά, κι έβαζα και μία global. Σε κάποια στιγμή έφτασα να έχω πά-

ρα πολλές global μεταβλητές που πραγματικά έχανα τη μπάλα στο debug-

ging. Έπρεπε να έχω στο μυαλό μου σε κάθε φάση τί τιμή έχει η ΚΑΘΕ

global, μη και προκαλεί παρενέργειες. Όταν έχεις πολλές global μεταβ-

λητές έχεις να σκέφτεσαι τέτοια πράγματα. Είναι πραγματικά εφιάλτης. Σου

μιλάω για μέγεθος κοντά στις 7000 γραμμές. Από ένα σημείο κι έπειτα στα-

μάτησα να βαριέμαι να σκέφτομαι πριν γράψω κώδικα. ΕΠΡΕΠΕ.

 

Στο προηγούμενο εξάμηνο είχα ένα άλλο project (10000+ locs). Έμαθα πολ-

λά από τον compiler. Τώρα η χρήση global μεταβλητών ήταν μετρημένη

και αυτές είχαν σχέση με επιλογές που έδινε ο χρήστης στις netlists (ένα spice

φτιάξαμε). Γενικότερα οργανώθηκε καλύτερα το όλο project με διακριτά

modules και directory-tree εμπνευσμένο από LLVM. Όλα πήγαν καλά. Αν

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

από το 0.

 

Μετά από όλα αυτά που διάβασα στο παρόν thread περί unity-build, δε μπορώ

να δω θετικά, ακόμη και για μικρότερα projects (προσωπική προτίμηση). Αν

και κατάλαβα ότι το έκανες για να το δοκιμάσεις. Απλά γνώμη μου είναι πως

αν δεν κάνει κακό στον συγγραφέα, αυτός που θα το διαβάσει είναι το θύμα.

 

Από προσωπική εμπειρία και από διάβασμα αρκετών open-source αριστουρ-

γημάτων, πάντα προσοχή στο σχεδιασμό και στην αρχιτεκτονική του project.

  • Like 1
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Δημοσ. (επεξεργασμένο)

gon όλες οι global που έχω βάλει είναι πράγματα που θέλω να διατηρώ τιμές μεταξύ frames.

 

Μια λύση για να της βγάλουμε από global είναι αυτό που έκανε ο migf1. Ουσιαστικά τις αρχικοποιεί στον caller(το windows_layer) και τις περνάει ως δείκτες στην μέθοδο που υπολογίζει το κάθε frame.(στο spoiler γρηγορος ψευδοκωδικας της λύσης αυτής)

 

 

 

windows_code:
game_state GameState = {};

while(true)
{
   UpdateGame(..., &GameState);
}

game_code:
struct game_state
{
   //previously global vars here
}

UpdateGame(...) {...};


 

 

 

Αυτή νομίζω είναι μια καλή λύση. Όμως αυτό που λές:

 

"Έπρεπε να έχω στο μυαλό μου σε κάθε φάση τί τιμή έχει η ΚΑΘΕ global μη και προκαλούνε παρενέργειες."

 

νομίζω συμβαίνει και στην λύση αυτή. Οι μεταβλητές έπαψαν να είναι global αλλα ουσιαστικά διατηρούν όπως και πριν τις τιμές τους. Ή εννοούσες μήπως κάτι διαφορετικό;

Επεξ/σία από bnvdarklord
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

gon όλες οι global που έχω βάλει είναι πράγματα που θέλω να διατηρώ τιμές μεταξύ frames.

 

Μια λύση για να της βγάλουμε από global είναι αυτό που έκανε ο migf1. Ουσιαστικά τις αρχικοποιεί στον caller(το windows_layer) και τις περνάει ως δείκτες στην μέθοδο που υπολογίζει το κάθε frame.(στο spoiler γρηγορος ψευδοκωδικας της λύσης αυτής)

 

 

 

windows_code:
while(true)
{
   game_state GameState = {};

   UpdateGame(..., &GameState);
}

game_code:

struct game_state
{
   //previously global vars here
}

UpdateGame(...) {...};


 

 

 

Αυτή νομίζω είναι μια καλή λύση. Όμως αυτό που λές:

 

"Έπρεπε να έχω στο μυαλό μου σε κάθε φάση τί τιμή έχει η ΚΑΘΕ global μη και προκαλούνε παρενέργειες."

 

νομίζω συμβαίνει και στην λύση αυτή. Οι μεταβλητές έπαψαν να είναι global αλλα ουσιαστικά διατηρούν όπως και πριν τις τιμές τους. Ή εννοούσες μήπως κάτι διαφορετικό;

 

Εννοώ πως είχα βάλει global μεταβλητές που μεταξύ τους

δεν είχαν κάποια σχέση (βλέπε "κατάσταση παιχνιδιού").

Οπότε μήπως σε κάποιο σημείο έπρεπε να μην τρέξω

κομμάτι κώδικα, ή να τρέξω κομμάτι κώδικα όσο η x και

η y αλλά όχι η z ήταν asserted; Αυτό είναι μπλέξιμο. Από

κάτι τέτοια μαθαίνεις. Άρα δεν εννούσα αυτό που είπες.

 

Φαντάζομαι (και απ' όσο κατάλαβα από τα άλλα μέλη) το

θέμα με τον κώδικά σου είναι ότι τις συνδυάζεις με unity-build.

 

EDIT:

Και πάλι, για να μπορέσεις να υποστηρίξεις σωστά global

μεταβλητές, πρέπει να έχεις στήσει μία σωστή υποδομή

και να είναι προφανές για το τί γίνεται.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

@migf1 Έριξα μια γρήγορη ματιά στις αλλαγές σου και έγω κάποιες απορίες:

 

:)

 

1) Ίσως είναι τελείως θέμα προσωπικό, αλλα πιστευεις αξίζει να κόβονται τα ονόματα μεταβλητών για χάρη του 80-column rule; (πχ gamememory.perm vs gamememory.permanent_storage)

 

Είναι καθαρά προσωπικό θέμα, μέχρι να χρειαστεί να εργαστείς με κάποιο team (είτε επαγγελματικά είτε ερασιτεχνικά), όπου θα αναγκαστείς να ακολουθήσεις το coding-style που χρησιμοποιεί το team.

 

Το κάθε coding-style έχει κάποιο rationale που εξηγεί την λογική για την οποία προτείνει αυτά που προτείνει. Το Eighty Column Rule για παράδειγμα, έχει τα πλεονεκτήματα που αναγράφει εκείνο το link που είχα δώσει σε προηγούμενο ποστ, τα οποία εγώ τα θεωρώ σημαντικά, ειδικά για cross-platform κώδικα. Αλλά η σημαντικότητα των επιχειρημάτων διαφέρει από άνθρωπο σε άνθρωπο.

 

Εγώ που λες θεωρώ πολύ σημαντικό στο ευανάγνωστο του κώδικα αφενός να τηρείται το 80 column rule (εντάξει, αν πάει στο 85-90 δεν χάθηκε κι ο κόσμος) και αφετέρου οι ονομασίες των symbols να είναι όσο το δυνατόν μικρότερες, χωρίς όμως να είναι cryptic.

 

Αν είναι... μισό-cryptic, ένα μικρό σχόλιο στο definition ή/και στο declaration ή ακόμα και inline όπου χρησιμοποιείται το μισο-cryptic σύμβολο, το βρίσκω απείρως πιο ευανάγνωστο από ονομασίες σιδηρόδρομους.

 

Στο παράδειγμα που αναφέρεις, στον δικό σου κώδικα έγραφες για παράδειγμα:

            GameMemory.TransientStorage = (uint8_t*)GameMemory.PermanentStorage + GameMemory.PermanentStorageSize;
Tο παρακάτω:

            gamememory.trans = (uint8_t*)gamememory.perm + gamememory.permsize;
εκτός του ότι το βρίσκω πολύ πιο λιτό & ευανάγνωστο, είναι και πολύ πιο βολικό για το 80 column rule. Βασικά η μνήμη είναι έτσι κι αλλιώς "storage", οπότε δεν χάνεται η ουσία αν το αφαιρέσουμε από την ονομασία. Έτσι κι αλλιώς δεν πρόκειται να εμφανιστεί ποτέ μόνο του, αλλά πάντα σε συνδυασμό με ένα memory var (το gamememory εδώ) αφού αποτελεί field του.

 

Ενδεχομένως θα ήταν ακόμα πιο ευανάγνωστο ως:

game_memory.trans
αλλά κάτι τέτοιο αντιτίθεται στο επιλεγμένο coding-style (όπου lowercase multiple word ξεχωρισμένες με _ παραπέμπουν σε functions και όχι σε μεταβλητές.

 

Άλλη εναλλακτική, που θα ήταν συνεπής και με το coding-style, είναι η:

gameMemory.trans
αλλά προσωπικά προσπαθώ να αποφεύγω όσο μπορώ το capitalization στις μεταβλητές (γενικώς το capitalization το θέλω μόνο στα DataTypes αν είναι δυνατόν).

 

Ακόμα καλύτερα θα ήταν:

            memory.trans = (uint8_t*)memory.perm + memory.permsize;
και βασικά όταν είμαι μέσα σε function όπου εννοείται πως μιλάμε για το game-memory, γράφω αυτό το τελευταίο. Π.χ. στον ορισμό της συνάρτησης: void game_update_and_render(). Αλλά στη δήλωσή της, το γράφω ως gamememory το όρισμα, επειδή οι δηλώσεις συνήθως είναι το μέρος που μπαίνει το documentation, οπότε είναι καλύτερα να είναι explicit.

 

Βέβαια στην WinMain() που γίνεται instantiate η game-memory είμαι και πάλι explicit και την ορίζω ως gamememory τη μεταβλητή (αφού σκέτο memory είναι πολύ γενικό).

 

Θα μπορούσα να το μικρύνω ακόμα περισσότερο χωρίς να γίνει έκπτωση στην κατανόηση, π.χ. gamemem, αλλά προτίμησα μια μέση λύση που πιθανότατα είναι πιο κοινώς αποδεκτή

 

Τώρα σχετικά με τα perm και trans (αντί για PermanentStorage και TransientStorage), αυτά μπορούν να χαρακτηριστούν έως και cryptic (ούτε καν μισο-cryptic δηλαδή) αλλά άπαξ και πας στον ορισμό τους και δεις το σχόλιο που τα εξηγεί /* perm: permanent storage, trans: transient storage */ νομίζω είναι αδύνατον να ξεχάσεις τι σημαίνουν από εκεί και πέρα. Και θεωρώ τα υπόλοιπα πλεονεκτήματα αυτής της λιτότητας πιο σημαντικά από το να πάω μια φορά στον ορισμό ενός miso-cryptic συμβόλου για να δω τι σημαίνει (εκτός πια αν μιλάμε για ακρότητες, π.χ. αντί για perm & trans να έχει κάποιος ας πούμε prm & trn :P).

 

Έπειτα υπάρχουν και ιδιωματισμοί που είναι εν πολλοίς αυτοματοποιημένοι μέσα στο μυαλό των devs. Για παράδειγμα, στην FillGameBoard() έγραφες:

	for (int Index = 0; Index < Board.Width*Board.Height; Index++)
	{
		...
	}
	...
	for (int Mine = 0; Mine < NumberOfMines; Mine++)
	{
		...
	}
	...
Αυτό το βρίσκω πολύ πιο δυσανάγνωστο συγκριτικά με το παρακάτω μετά τις αλλαγές που έκανα:

	for (int i=0; i < _g_board.width *_g_board.height; i++)
	{
		...
	}
	...
	for (int i=0; i < nmines; i++)
	{
		...
	}
	...
διότι οι μετρητές στις λούπες μέτρησης είναι ιδίωμα να χρησιμοποιούνται ως i, j, k. Το σε τι αναφέρονται, προκύπτει από το condition της λούπας. Δηλαδή, στη μεν 1η λούπα είναι φανερό πως μετράμε tiles (κελιά) του board, ενώ στην 2η λούπα είναι φανερό πως μετράμε νάρκες (btw, το nsomething είναι επίσης ιδωματικό, ιδιαίτερα στη στάνταρ C, όπου το n μπροστά στο something σημαίνει πλήθος από something).

 

Επιπρόσθετα, άσχετα με τους ιδωματισμούς, λόγω του συγκεκριμένου coding-style στην 1η λούπα βλέπουμε άμεσα πως τα πλάτος και το ύψος του board είναι ορισμένα ως global μεταβλητές με internal linkage. Αυτό είναι πολύ χρήσιμο αν χτυπηθούμε από global side-effects, να μπορούμε με μια ματιά να βλέπουμε μέσα στις συναρτήσεις τι είναι global και τι όχι, καθώς και το αν είναι internally ή externally global στο εκάστοτε source-module. Μια επιπλέον πρακτική είναι να τις δηλώνουμε μέσα στην συνάρτηση ως extern τις global μεταβλητές που θέλουμε να χρησιμοποιήσουμε (αλλά αυτό από μόνο του δεν σου δίνει hint για το αν έχουν internal ή external linkage).

 

2) Υπάρχει καλύτερος τρόπος να μειωθούν οι global μεταβλητές χωρίς να αρχικοποιούνται στο windows layer; Ρωτάω επειδή δεν μου πολυαρέσει η ιδέα να πρέπει το windows layer να ασχολείται με οτιδήποτε τελείως άσχετο με αυτό.(ίσως ενα struct game_state που να εχει μεσα ότι εχω σαν global ετσι ώστε απλά να περνάει αυτο το windows layer και να μην χρειάζεται συνεχως αλλαγες ; ) Και σαν επιπλέον ερώτηση - γιατί οι global μεταβλητές θεωρούνται κακή πρακτική;

Αυτό εδώ το link έχει μια αρκετά πλήρη σύνοψη των + και των - των καθολικών μεταβλητών.

Με το να τις μαζέψεις όλες μαζί σε ένα struct, το βασικό που κερδίζεις είναι πως τις κάνεις πιο ευδιάκριτες μέσα στις συναρτήσει που τις χρησιμοποιείς.

Π.χ.:

struct GlobalExtern {
   int foo, boo, moo;
} globextern;   // globals with external linkage

static struct GlobalIntern {
   int koo, loo, noo;
} globintern;   // globals with internal linkage

...
void func( void )
{
    globextern.foo = 10;
    globintern.noo = 1000;
    ...
}
που ενδεχομένως σε γλιτώνει από coding-style τρικς τύποι g_ και _g_

 

Το βασικό πρόβλημα όμως δεν είναι να τις μαζέψεις, αλλά να περιορίσεις τα side-effects. Με άλλα λόγια να περιορίσεις να τις χρησιμοποιείς απευθείας μέσα στις συναρτήσεις. Αντί αυτού, μπορείς να έχεις κανονικές μεταβλητές που τις ορίζεις π.χ. στο application entry point (στην main() όταν μιλάμε για στάνταρ C/C++) και να τις περνάς ως ορίσματα σε όποιες συναρτήσεις τις χρειάζονται. Με αυτόν τον τρόπο έχεις μεγαλύτερο έλεγχο στο πότε και που πειράζεις τα περιεχόμενα της εκάστοτε μεταβλητής. Και επιλέγεις εσύ πότε θέλεις να τις περνάς by-value και πότε by-reference.

 

3) Υπάρχει κάποιος λόγος που έκανες ZeroMemory στο game memory πριν το allocation, ή καθαρά τυπικά; Μιας και στις επόμενες γραμμές αρχικοποιούνται τα στοιχεια του struct.

Όχι. Βασικά δεν έχω αξιωθεί να ασχοληθώ με τη λογική του κώδικα γενικώς. Όπου είχες {} έβαλα memeset() ή ZeroMemory(), ανάλγα αν ήταν στο win32_minesweepr.c ή όχι.

 

ΥΓ. Τελικά τον έφταξα και pure C τον κώδικα. Εκτός από τα typdefs ήθελαν αλλαγή και τα enums, τα values των οποίων μπορείς να τα κάνεις απευθείας access ως class attributes στην C++, ενώ στην C πρέπει να τα ορίσεις έξω από τα struct. Έφτιαξα κι ένα 2ο makefile που κάνει compile τα .cpp ως C99, αλλά εντάξει δεν είναι τώρα αυτές αλλαγές για να σηκώσω νέο zip. Όταν αποφασίσω να φτιάξω cross-platform UI, θα σε ρωτήσω πράγματα να μου εξηγήσεις. Βασικά πρέπει πρώτα να κάτσω να δω λιγάκι και τη λογική του κώδικά σου :P

  • Like 2
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Ευχαριστώ για την απάντηση.

 

Στο μόνο που διαφωνώ είναι αυτά περι μετρητών σε λούπα - εμένα μου φαίνεται πιο ευανάγνωστο να μην είναι i,j,k κτλ :Ρ Περισσότερο μαλιστα σε περιπτώσεις που χρησιμοποιείται ο μετρητής μεσα στην λούπα για κάποιο σκοπό.

 

Όταν αποφασίσω να φτιάξω cross-platform UI, θα σε ρωτήσω πράγματα να μου εξηγήσεις. Βασικά πρέπει πρώτα να κάτσω να δω λιγάκι και τη λογική του κώδικά σου :P

Φυσικά. Αν και νομίζω ότι πέρα από τα structs που περνάς στην GameUpdateAndRender δεν χρειάζεται να ξέρεις κάτι αλλο περι λογικής κώδικα εκτός από το win32_minesweeper.cpp.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Ευχαριστώ για την απάντηση.

No problem ρε συ. Άλλωστε είμαι γνωστός... σεντονάς :lol:

 

Στο μόνο που διαφωνώ είναι αυτά περι μετρητών σε λούπα - εμένα μου φαίνεται πιο ευανάγνωστο να μην είναι i,j,k κτλ :Ρ Περισσότερο μαλιστα σε περιπτώσεις που χρησιμοποιείται ο μετρητής μεσα στην λούπα για κάποιο σκοπό.

Ναι, οκ. Έχω κι εγώ προτιμήσεις που αντιτίθενται σε κοινές πρακτικές. Απλώς τα βασικά idioms μιας γλώσσα είναι πολύ χρήσιμο τουλάχιστον να τα ξέρεις, γιατί τα βλέπεις σχεδόν σε όλους τους κώδικες. Για αυτό και εχουν εντυπωθεί ως αυτοματισμοί σε όσους ασχολούνται επί μακρόν με μια γλώσσα. Το συκεκριμένο idiom πάντως υπάρχει σχεδόν σε όλες τις δημοφιλείς, compiled γλώσσες.

 

Φυσικά. Αν και νομίζω ότι πέρα από τα structs που περνάς στην GameUpdateAndRender δεν χρειάζεται να ξέρεις κάτι αλλο περι λογικής κώδικα εκτός από το win32_minesweeper.cpp.

Θα κάτσω να τα δω κάποια στιγμή με ησυχία. Βασικά θέλω να δω πως συνδέεις τα πράγματα μεταξύ τους (για αυτό με "χαλάνε" οι πολλές καθολικές.. με προϊδεάζουν ότι θα πρέπει να ρίξω πολύ ψάξιμο :P).

Πάντως αν βρεις χρόνο και δεν βαριέσαι, βάλε πάνω από κάθε συνάρτηση μια μικρή περίληψη του τι κάνει. Επίσης γράψε κάποια στιγμή είτε μέσα στον κώδικα είτε σε κάνα ποστ εδώ, τυη λογική με την οποία κάνεις parse το sprite-sheet (αν κι ενδεχομένως να προκύπτει εύκολα από τον κώδικα... δεν τον έχω κοιτάξει καθόλου).

 

Anyway, όταν το αποφασίσω, θα σε ρωτήσω για τυχόν απορίες μου. Thanks!

  • Like 1
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Απλώς τα βασικά idioms μιας γλώσσα είναι πολύ χρήσιμο τουλάχιστον να τα ξέρεις, γιατί τα βλέπεις σχεδόν σε όλους τους κώδικες. Για αυτό και εχουν εντυπωθεί ως αυτοματισμοί σε όσους ασχολούνται επί μακρόν με μια γλώσσα. Το συκεκριμένο idiom πάντως υπάρχει σχεδόν σε όλες τις δημοφιλείς, compiled γλώσσες.

 

Δεν είναι idiom αυτό το πράγμα. http://en.wikipedia.org/wiki/Programming_idiom

 

Idiom είναι π.χ. να γράφεις Javascript και αντί για

if (foo) result = foo;
else result = bar;

να γράφεις

result = foo || bar
  • Like 1
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Η ουσία δεν είναι αν λέγεται idiom ή όχι. Πες το pattern αν σε ικανοποιεί καλύτερα. Η ουσία είναι πως όλος ο πλανήτης τα index και τα counter variables στα for-loops τα γράφει i, j, k, ... (άντε, idx και count ή row και col, ενίοτε).

 

Κάτι που btw προέρχεται από τα μαθηματικά. Αρχικά υιοθετήθηκε στην fortran από ότι θυμάμαι, μετά στην C και μετά σε όλες τις υπόλοιπες γλώσσες.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Η ουσία είναι πως όλος ο πλανήτης τα index και τα counter variables στα for-loops τα γράφει i, j, k, ...

Άλλα έλεγες εσυ πιο πριν : :P

 

 

 

Αντίσταση στα "το κάνουμε για να το κάνουμε, χωρίς να υπάρχει ουσιαστικός λόγος".

 

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Τα ίδια έλεγα. Ο ουσιαστικός λόγος εδώ είναι πως κάνει τον κώδικα σημαντικά πιο ευανάγνωστο στην συντριπτική πλειοψηφία όσων τον διαβάσουν, τουλάχιστον όσων έχουν κάποια εμπειρία στον προγραμματισμό (και σε αυτό το context είναι αδιάφορο αν ονομάζεται idiom, pattern, ή όπως αλλιώς).

 

Ακόμα κι αυτό όμως είναι προαιρετικό. Όλα είναι suggestions, δεν είναι υποχρεωτικά.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Η ουσία δεν είναι αν λέγεται idiom ή όχι. Πες το pattern αν σε ικανοποιεί καλύτερα. Η ουσία είναι πως όλος ο πλανήτης τα index και τα counter variables στα for-loops τα γράφει i, j, k, ... (άντε, idx και count ή row και col, ενίοτε).

 

Για κάποιον άλλο όμως η ουσία μπορεί να είναι ο αγώνας κόντρα στην ημιμάθεια.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Εγώ νομίζω ότι δεν είναι πάντα πιο ευανάγνωστα αλλά πάει ανα περίπτωση. Για παράδειγμα αν ήθελα πάρω συνδυασμούς rgb χρωμάτων σε κάποιο range και να κάνω κάποια πράξη στα χρώματα αυτά, νομίζω είναι πιο ευανάγνωστο οι μετρητές να είναι red, green και blue. Εντάξει το index που είχα βάλει αντί για σκέτο i ήταν χαζό, αλλά σίγουρα υπάρχουν περιπτώσεις που έχει νόημα να ξεφύγεις από το κλασσικό. 

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Ναι, δεν είναι πάντα πιο ευανάγνωστα. Για αυτό έκανα σαφές εξαρχής πως αναφέρομαι σε for-loops για απλούς μετρητές ή για απλούς indexers (τέτοια ήταν τα δικά σου).

 

Εγώ π.χ. όταν βλέπω να μην χρησιμοποιούνται i,j,k αυτόματα η 1η μου σκέψη είναι μήπως αυτό το loop κάνει κάτι πιο πολύπλοκο (ειδικά αν είναι σε μεγάλα ή/και nested loops).

  • Like 1
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε

Πρέπει να είστε μέλος για να αφήσετε σχόλιο

Δημιουργία λογαριασμού

Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!

Δημιουργία νέου λογαριασμού

Σύνδεση

Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.

Συνδεθείτε τώρα
  • Δημιουργία νέου...