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

Παιχνίδι 2048 σε C


johnny.tifosi

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

Τα branches πάντως αντιστοιχούν σωστά. Θεωρώ ότι δεν θα έχουμε πρόβλημα.

Είναι κάτι συγκεκριμένο που πρέπει να εξέγξω;

Σάμπως ξέρω; :lol: Δεν κρατάς καλού-κακού ένα backup και των 2 branches του blessed πριν τα κάνεις merge? (θα αρχίσει το κράξιμο πάλι ο ημίθεος :P)

 

Btw, έβαλα και τα .gitignore στο remote repo... καλά έκανα άραγε;

 

Για το Lazarus, είχα τη φαεινή ιδέα να το κάνω upgrade πριν λίγες μέρες (είχα μία αρχαία έκδοση 0.9.κάτι) και κατέληξε να μη δουλεύει (δεν έβρισκε τα .cfg της FreePascal). Μόλις χθες κατάφερα και του ξανάκανα ένα clean install στην τελευταία έκδοση.

 

Αλλά με τέτοιο πήξιμο φέτος (ούτε μουσταλευριά να ήμουν!) δεν ξέρω αν θα προλάβω τίποτα. Στη χειρότερη, θα του ρίξω καμιά ματιά μετά τις 16 δίπλα στο κύμα! :D

 

Αυτά είναι :) Κι εγώ πάντως μετά τις 16 θα φύγω (ήταν να φύγω νωρίτερα). Δεν πιστεύω να πας σε καμιά Τζιά ή καμιά Κύθνο, γιατί εγώ μάλλον σε κάποιο από αυτά τα 2 λέω να πάω φέτος.

 

Τον είχα δοκιμάσει τον laz-player. Δεν δούλευε (δεν άνοιγε αρχεία, κλπ), αλλά μια 1η γεύση την πήρα. Αν το κατάλαβα σωστά, το board το ζωγράφιζες χειροκίνητα, σωστά; (όπως έκανε νομίζω κι ο DirectX στο win32 version που είχε ανεβάσει στο νήμα, με το WM_PAINT event).

 

Δεν έχω ιδέα αν είναι πιο εύκολο ή πιο δύσκολο στο lazarus, για την ιστορία όμως εγώ στον GTK+2 player δεν τα ζωγραφίζω χειροκίνητα τα tiles (αντίθετα, στο κανονικό game, τα ζωγραφίζω κι εγώ χειροκίνητα στην κονσόλα).

 

Στον player, ξεκινάω με ένα άδειο 4x4 table-widget (φτιαγμένο στο το Glade) και κατόπιν πάω και το γεμίζω δυναμικά με event-box + label widgets στον κώδικα. Όταν χρειάζεται να γίνει resize το board, κάνω free τα tiles, κάνω resize το table-widget (έχει έτοιμη συνάρτηση το GTK+2 για το resize των table-widgets) και μετά πάω και το ξαναγεμίζω δυναμικά με tiles (event-box + label widgets).

 

Το έκανα έτσι, γιατί για να τα ζωγραφίζω σε canva (drawing widget) έπρεπε να μπλέξω με την Cairo βιβλιοθήκη, που δεν την ξέρω.

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

  • Απαντ. 272
  • Δημ.
  • Τελ. απάντηση

Συχνή συμμετοχή στο θέμα

Συχνή συμμετοχή στο θέμα

Δημοσιευμένες Εικόνες

Σάμπως ξέρω; :lol: Δεν κρατάς καλού-κακού ένα backup και των 2 branches του blessed πριν τα κάνεις merge? (θα αρχίσει το κράξιμο πάλι ο ημίθεος :P)

Μπα δεν κράζω κανέναν. Ο καθένας δουλεύει όπως θέλει :)

 

Απλά μου φαίνεται παράξενο να φοβάται κάποιος και να θέλει "να κρατήσει backup" όταν ένα git repo είναι το ίδιο ένα backup των πάντων από την αρχή μέχρι και τώρα. Για παράδειγμα αυτή τη στιγμή το master βρίσκεται στο commit c1b73d2. Όσα merge (σωστά ή λάθος) και να γίνουν, οποιοσδήποτε κάνει checkout το c1b732d2, έχει κατ ουσίαν το backup που λες.

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

Σάμπως ξέρω; :lol: Δεν κρατάς καλού-κακού ένα backup και των 2 branches του blessed πριν τα κάνεις merge? (θα αρχίσει το κράξιμο πάλι ο ημίθεος :P)

Λέω να το κάνουμε the git way. Το πολύ-πολύ να χρειαστεί μετά να ...μάθουμε και το git reset (ή revert, δεν είμαι σίγουρος ποιο από τα δύο είναι).

Τι λες;

 

Btw, έβαλα και τα .gitignore στο remote repo... καλά έκανα άραγε;

 

Θα δείξει... :P

 

 

 

Αυτά είναι :) Κι εγώ πάντως μετά τις 16 θα φύγω (ήταν να φύγω νωρίτερα). Δεν πιστεύω να πας σε καμιά Τζιά ή καμιά Κύθνο, γιατί εγώ μάλλον σε κάποιο από αυτά τα 2 λέω να πάω φέτος.

Μπα, εγώ εδώ, Κρήτη. Για πολλούς λόγους...

 

 

 

Τον είχα δοκιμάσει τον laz-player. Δεν δούλευε (δεν άνοιγε αρχεία, κλπ), αλλά μια 1η γεύση την πήρα. Αν το κατάλαβα σωστά, το board το ζωγράφιζες χειροκίνητα, σωστά; (όπως έκανε νομίζω κι ο DirectX στο win32 version που είχε ανεβάσει στο νήμα, με το WM_PAINT event).

Όχι, έχει ένα DrawGrid component. Απλά του δίνω πόσα rows/columns θα έχει όταν φορτώνω το .sav και μετά το χειρίζομαι με τις δικές του μεθόδους. Του δίνεις και μία callback να καλέσει όταν χρειάζεται να κάνει draw κάποιο cell, και εκεί κάνεις χειροκίνητα draw στον canvas. Αλλά το Canvas object είναι χυδαία "εύκολο" στο Lazarus.

 

Πάντως ναι, δεν δουλεύει ακόμα, ούτε τα βασικά δεν κάνει. Είχα μείνει στο σχεδιασμό του interface.

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

Merged. Κι ο (imi)Θεός βοηθός! :D

 

Κάνε το όπως νομίζεις καλύτερα, εσύ είσαι ο maintainer (και ο ημίθεος ο σύμβουλος) :)

Πάω να την πέσω παίδες, καληνυχτίζω... αύριο πάλι :)

 

Καλή ξεκούραση! :)

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

Επειδή βλέπω ότι σου φαίνονται λίγες οι υπό-εντολές του git και δεν έχεις χορτάσει, να θυμηθώ να γράψω για το squashing όταν τα κάνει merge (βασικά και τώρα μπορώ αν χρησιμοποιήσω το δικό σου repo αλλά βαριέμαι τώρα :))

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

 

 

 

Αλλά με τέτοιο πήξιμο φέτος (ούτε μουσταλευριά να ήμουν!) δεν ξέρω αν θα προλάβω τίποτα. Στη χειρότερη, θα του ρίξω καμιά ματιά μετά τις 16 δίπλα στο κύμα! :D

κάτι μου λέει ότι θα βρεις και ποιο ενδιαφέροντα πράγματα να κοιτάξεις... :P

 

 

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

...

Οποιαδήποτε παρατήρηση για bugs είναι κάτι παραπάνω από ευπρόσδεκτη!

...

Προσθέτω συνημμένο με τον κώδικα και εκτελέσιμο. Καλή διασκέδαση!

Είπα σήμερα να δω λίγο τον κώδικα, αλλά δυστυχώς δεν μου είναι ελκυστικός. Δεν ξέρω αν έχεις το χρόνο και το ενδιαφέρον για κάτι τέτοιο, αλλά νομίζω θα μπορούσες να ασχοληθείς 1-2 ώρες για να τον κάνεις πιο ευανάγνωστο και πιο δομημένο.

 

H χρήση κενών είναι πολύ βασική στο beautification του κώδικα, και στις compiled γλώσσες δεν προκαλεί runtime overhead. Για παράδειγμα οι συναρτήσεις σου random_in_range() και insert() που τώρα είναι έτσι...

 

 

/* Random integer generator within a semi-open interval [min, max) */
int random_in_range (unsigned int min, unsigned int max)
{
  int base_random = rand(); /* in [0, RAND_MAX] */
  if (RAND_MAX == base_random) return random_in_range(min, max);
  /* now guaranteed to be in [0, RAND_MAX) */
  int range       = max - min,
      remainder   = RAND_MAX % range,
      bucket      = RAND_MAX / range;
  /* There are range buckets, plus one smaller interval
     within remainder of RAND_MAX */
  if (base_random < RAND_MAX - remainder) {
    return min + base_random/bucket;
  } else {
    return random_in_range (min, max);
  }
}

/*function to insert numbers to empty slots*/
void insert(int array[size][size]) {
	/*printf("Entered function insert\n");*/
	int i,j,newi,newj,newnum,flag;
	/*check if there is an empty cell to insert number*/
	flag=0;
	for (i=0; i<size; i++) {
		for (j=0; j<size; j++) {
			if (array[i][j]==0) {
				flag=1;
			}
		}
	}
	if (flag==1) {
		do {
			newi=random_in_range(0,size);
			newj=random_in_range(0,size);
			/*printf("I'm in the loop!\n");*/
		} while (array[newi][newj]!=0);
		/*insert new number: 90% chance of 2, 10% chance of 4*/
		i=rand() %10;
		if (i==9) {
			newnum=4;
		}
		else {
			newnum=2;
		}
		array[newi][newj]=newnum; 
	}
}

 

μπορούν να γίνουν beautified σε κάτι τέτοιο:

 

 

/**
 * Random integer generator within a semi-open interval [min, max)
 */
int random_in_range( unsigned int min, unsigned int max )
{
	int base_random = rand(); /* in [0, RAND_MAX] */
	if ( RAND_MAX == base_random ) {
		return random_in_range(min, max);
	}

	/* now guaranteed to be in [0, RAND_MAX) */
	int range = max - min,
	remainder = RAND_MAX % range,
	bucket    = RAND_MAX / range;

	/* There are range buckets, plus one smaller interval
	 * within remainder of RAND_MAX
	 */
	if ( base_random < RAND_MAX - remainder ) {
		return min + base_random/bucket;
	}
	return random_in_range (min, max);
}

/**
 * Function to insert numbers to empty slots
 */
void insert( int array[SIZE][SIZE] )
{
	/*printf("Entered function insert\n");*/
	int i,j, newi,newj,newnum, flag;

	/* check if there is an empty cell to insert number */
	flag = 0;
	for (i=0; i < SIZE; i++) {
		for (j=0; j < SIZE; j++) {
			if ( array[i][j] == 0 ) {
				flag = 1;
			}
		}
	}
	if ( flag == 1 ) {
		do {
			newi = random_in_range( 0, SIZE);
			newj = random_in_range( 0, SIZE );
			/*puts( "I'm in the loop!" );*/
		} while ( array[newi][newj] != 0 );

		/* insert new number: 90% chance of 2, 10% chance of 4 */
		i = rand() %10;
		if ( i == 9 ) {
			newnum = 4;
		}
		else {
			newnum = 2;
		}
		array[newi][newj] = newnum; 
	}
}

 

που νομίζω τις κάνει πολύ πιο ευανάγνωστες. Υπάρχουν διάφορα online & offline εργαλεία για αυτόματο ή ημι-αυτόματο beautification (https://www.google.com/?hl=en&gws_rd=ssl#hl=en&q=code+beautifier+for+c) αλλά το ιδανικό είναι το κάνεις μόνος σου.

 

Σχετικά με τη δόμηση του κώδικα, είδα για παράδειγμα πως τον κώδικα του "undo array initialization" τον επαναλαμβάνεις αυτούσιο σε διάφορα σημεία του προγράμματος. Μπορείς λοιπόν να τον κάνεις μια ξεχωριστή συνάρτηση. Γενικώς, πράγματα που χρησιμοποιούνται συχνά αυτούσια ή με λίγες αλλαγές, συμφέρει να τα κάνεις συναρτήσεις με κατάλληλες παραμέτρους (όπως π.χ. τον κώδικα που έχεις για τις κινήσεις UP, DOWN, LEFT & RIGHT).

 

ΥΓ. Τελικά όντως δεν υπάρχει επιλογή για διακοπή του παιχνιδιού (quit), έτσι δεν είναι;

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

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

@migf1
δεν έχω βάλει quit γιατί απλά μπορώ να κλείνω το παράθυρο. δεν βρίσκω κάποια χρησιμότητα. σχετικά με το beautification ούτε αυτό με ενδιέφερε αλλά μιας και είναι απλό θα το κάνω καποια στιγμή. επίσης καλό είναι να γράψω μια συνάρτηση με το initialization των undo arrays γιατι όντως επαναλαμβάνεται πολύ.

@imitheos
την συνάρτηση την έχω αντιγράψει από το stackoverflow, δεν έχω ιδέα πως δουλεύει :P

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

Μόλις έκανα ένα pull-request. Έχουν προστεθεί σχόλια στα gui_statusbar.c/.h & gui_dialogs.c/.h

Μην κάνεις τέτοια. Δεν είδες τι έλεγε ότι θα το κοιτάξει δίπλα στο κύμα ? Θα αφήσει τα μωρά στη θάλασσα και θα μπαίνει στα tablets να κάνει merge :)

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

Τη βλέπω εγώ τη μοίρα μου... Το τελευταίο merge θα το κάνω ενώ με περιμένει η οικογένεια στ' αμάξι! :P

 

 

@imitheos, το πολύ-πολύ αν τον πιάσει ο οίστρος και στείλει πολλά requests, να φωνάξω κανένα μωρό να βοηθήσει την κατάσταση... Να κάνουμε μαζί τα merges! ;)

 

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

Καλημέρα και χρόνια πολλά!

 

Τη βλέπω εγώ τη μοίρα μου... Το τελευταίο merge θα το κάνω ενώ με περιμένει η οικογένεια στ' αμάξι! :P

 

 

@imitheos, το πολύ-πολύ αν τον πιάσει ο οίστρος και στείλει πολλά requests, να φωνάξω κανένα μωρό να βοηθήσει την κατάσταση... Να κάνουμε μαζί τα merges! ;)

 

Χε χε... την άλλη βδομάδα θα φύγω κι εγώ, οπότε θα ησυχάσουμε όλοι μαζί :) Προφανώς θα πάρω λάπτοπ μαζί μου, αλλά μάλλον θα έχω κι εγώ καλύτερα πράγματα να κάνω από το να γράφω σχόλια στον κώδικα του player :lol:

 

Πέρα από την πλάκα, όταν επιστρέψεις ρίξε μια ειδοποίηση εδώ, για να σου κάνω pull-request με όλα τα pending commits. Πιθανότατα θα το προχωρήσω λιγάκι ακόμα και σήμερα και μέσα στο ΣΚ. Θα τα κάνω μονάχα push στο fork μου, κι όταν επιστρέψεις θα σου κάνω ένα pull-request για όλα μαζί.

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

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

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

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

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

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

Σύνδεση

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

Συνδεθείτε τώρα

  • Δημιουργία νέου...