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

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


johnny.tifosi

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

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

Καλησπέρα,

 

πωρώθηκα πρόσφατα με το 2048 και σκέφτηκα με τις λίγες γνώσεις C που έχω και συμπληρώντας τα δύσκολα (χρωματιστό κείμενο, διάβασμα arrow keys) με κώδικα που βρίσκω στο google να γράψω ένα απλό προγραμματάκι με το DevC++ που να παίζει σε κονσόλα εκτυπώνοντας κέιμενο.

 

Έχω γράψει σχεδόν όλο τον κώδικα. Αυτό που λέιπει είναι οι υπολογισμοί που κάνει το παιχνιδι σε κάθε μια από τις 4 κινήσεις (πάνω κατω αριστερά δεξιά) διαβάζοντας τα βελάκια. Για την ακρίβεια, ξεκίνησα γράφοντας τον κώδικα για το "πανω" και το πρόγραμμα δεν αντιδρά. Πατώντας τα άλλα τρια βελάκια που δεν κάνουν τίποτα προς το παρόν το προγραμμα προχωρά κανονικά και βάζει νέο αριθμό στον πίνακα.

 

Παραθέτω τον κώδικα εδώ: https://github.com/johnnytifosi/2048/blob/master/main.c

το επίμαχο σημείο είναι στις γραμμές 118-147, μπορεί όμως να πέφτει και σε infinite loop από την γεννήτρια τυχαίων αριθμών ψάχνοντας νέο άδειο κελί. επλίζω ότι ο σχολιασμός του κώδικα είναι επαρκής, έτσι κι αλλιώς είναι αρκετά σύντομος. Οποιαδήποτε βοήθεια είναι ευπρόσδεκτη.

 

edit: συγγνώμη για το διπλό θέμα. ας σβηστεί από τους mods

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

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

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

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

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


void print(int x) {
HANDLE hConsole;
    int k;
if (x==0) {
k=15;}
else if (x==2) {
k=112;}
else if (x==4) {
k=48;}
else if (x==8) {
k=32;}
else if (x==16) {
k=208;}
else if (x==32) {
k=192;}
else if (x==64) {
k=64;}
else {
k=224;}
    hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(hConsole, k);
    if (x<10) {
     printf(" %d ",x);}
    else if (x<100) {
     printf(" %d ",x);}
    else if (x<1000) {
     printf(" %d ",x);}
    else {
     printf(" %d",x);}
    SetConsoleTextAttribute(hConsole, 7);
}
 

για κάποιο λογο ολα αυτα τα magic numbers μεσα στα if else μου φαινονται άσχημα. 

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

Καλησπέρα,

 

πωρώθηκα πρόσφατα με το 2048 και σκέφτηκα με τις λίγες γνώσεις C που έχω και συμπληρώντας τα δύσκολα (χρωματιστό κείμενο, διάβασμα arrow keys) με κώδικα που βρίσκω στο google να γράψω ένα απλό προγραμματάκι με το DevC++ που να παίζει σε κονσόλα εκτυπώνοντας κέιμενο.

 

Έχω γράψει σχεδόν όλο τον κώδικα. Αυτό που λέιπει είναι οι υπολογισμοί που κάνει το παιχνιδι σε κάθε μια από τις 4 κινήσεις (πάνω κατω αριστερά δεξιά) διαβάζοντας τα βελάκια. Για την ακρίβεια, ξεκίνησα γράφοντας τον κώδικα για το "πανω" και το πρόγραμμα δεν αντιδρά. Πατώντας τα άλλα τρια βελάκια που δεν κάνουν τίποτα προς το παρόν το προγραμμα προχωρά κανονικά και βάζει νέο αριθμό στον πίνακα.

 

Παραθέτω τον κώδικα εδώ: https://github.com/johnnytifosi/2048/blob/master/main.c

το επίμαχο σημείο είναι στις γραμμές 118-147, μπορεί όμως να πέφτει και σε infinite loop από την γεννήτρια τυχαίων αριθμών ψάχνοντας νέο άδειο κελί. επλίζω ότι ο σχολιασμός του κώδικα είναι επαρκής, έτσι κι αλλιώς είναι αρκετά σύντομος. Οποιαδήποτε βοήθεια είναι ευπρόσδεκτη.

 

edit: συγγνώμη για το διπλό θέμα. ας σβηστεί από τους mods

Το πρόβλημα φαίνεται να είναι πως δεν καθαρίζεις τον temp πριν από κάθε iteration στήλης. Με ένα memset(temp, 0, size * sizeof(int) ); δείχνει πως έστρωσε.

 

Πέρα από αυτό, μου βγήκαν λιγάκι τα μάτια για να διαβάσω τον κώδικά σου (έως πολύ :P). Και τα σχόλια δεν θα έλεγα ότι βοήθησαν ιδιαίτερα. Χρειάστηκε να καθαρογράψω αρκετό από την κώδικά σου μέχρι να βγάλω άκρη.

 

Anyway, αφού έβγαλα άκρη τελικά, ψιλο-πορώθηκα και το συνέχισα λιγάκι.

 

Κώδικας: 2048.c

 

 

#include <stdio.h>
#include <stdlib.h>
//#include <conio.h>
#include <time.h>
#include <windows.h>

#include "my.h"

#define SIZE 4

/* --------------------------------------------------------------
 * 
 * --------------------------------------------------------------
 */
void board_init( int board[SIZE][SIZE] )
{
	memset( board, 0, SIZE*SIZE * sizeof(int) );
}

/* --------------------------------------------------------------
 * Print specified board element in colors and with correct spacing
 * --------------------------------------------------------------
 */
void board_print_elem_at( int board[SIZE][SIZE], int i, int j )
{
	HANDLE  hConsole;
	int elem = board[i][j];
	int k;

	switch ( elem )
	{
		case 0:
			k = 15;
			break;
		case 2:
			k = 112;
			break;
		case 4:
			k = 48;
			break;
		case 8:
			k = 32;
			break;
		case 16:
			k = 208;
			break;
		case 32:
			k = 192;
			break;
		case 64:
			k = 64;
			break;
		default:
			k = 224;
			break;
	}
	hConsole = GetStdHandle( STD_OUTPUT_HANDLE );
	SetConsoleTextAttribute( hConsole, k );

	if ( elem < 10) {
		printf( "  %d  ", elem );
	}
	else if ( elem < 100 ) {
		printf( "  %d ", elem );
	}
	else if ( elem < 1000 ) {
		printf( " %d ", elem );
	}
	else {
		printf( " %d", elem );
	}
	fflush( stdout );

	SetConsoleTextAttribute(hConsole, 7);
}

/* --------------------------------------------------------------
 * 
 * --------------------------------------------------------------
 */
void board_print( int board[SIZE][SIZE] )
{
	int i,j;

	for (i=0; i < SIZE; i++) {
		for (j=0; j < SIZE; j++) {
			board_print_elem_at( board, i,j );
		}
		putchar( '\n' );
	}
}

/* --------------------------------------------------------------
 * Insert a random number at a random empty slot of the board
 * --------------------------------------------------------------
 */
void board_generate_elem( int board[SIZE][SIZE], int *nempty )
{
	int i, j;
	do {
		i = rand() % SIZE;
		j = rand() % SIZE;
	} while ( 0 != board[i][j] );
	
	board[i][j] = 0 == rand() % 2 ? 2 : 4;  /* val must be 2 or 4 */
	(*nempty)--;
}

/* --------------------------------------------------------------
 * Return 1 (true) if at least one upwards move is available to be
 * played, so the caller can generate a new board element. If no
 * move played, or no more moves are available, the function returns
 * 0 (false).
 * --------------------------------------------------------------
 */
int do_key_up( int board[SIZE][SIZE], int *score, int *nempty )
{
	int i,j,k;
	int temp[SIZE] = {0};
	int played = 0;

	/* for every column */
	for ( j=0; j < SIZE; j++)
	{
		/* if 2 consecutive cells contain 0 and non-0 in
		 * any order, then a move is available
		 */
		for (i=0; i < SIZE-1; i++) {
			if ( 0 == board[i][j] && 0 != board[i+1][j] ) {
				played = 1;
				break;
			}
		}

		/* backup non-zero elems into temp buf, and zero them */
		memset( temp, 0, SIZE * sizeof(int) );
		for (i=0, k=0; i < SIZE; i++) {
			if ( 0 != board[i][j] ) {
				temp[k++] = board[i][j];
				board[i][j] = 0;
			}
		}

		/* in temp, merge adjacent equal cells (if temp has at
		 * least one equal adjacent pair, then a move is available)
		 */
		for (k=0; k < SIZE-1; k++)
		{
			if ( 0 == temp[k] ) {
				continue;
			}
			if ( temp[k] == temp[k+1] ) {
				temp[k] += temp[k+1];
				temp[k+1] = 0;
				(*score) += temp[k];
				k++;
				(*nempty)++;
				played = 1;
				
			}
		}

		/* copy all non-zero elems of temp
		 * back to the current column (j),
		 * without any gaps between them
		 */
		for (k=0,i=0; k < SIZE; k++)
		{
			if ( 0 != temp[k] ) {
				board[i++][j] = temp[k];
			}
		}

		/* If after the merging, there are still equal
		 * adjacent cells, played is set to 1 (true) so
		 * the caller can generate a new board element.
		 * The new merging will happen the next time
		 * this function is called.
		 */
		for (i=0; i < SIZE-1; i++)
		{
			if ( 0 == board[i][j] ) {
				continue;
			}
			if ( board[i][j] == board[i+1][j] ) {
				played = 1;
				break;
			}
		}

	}

	return played;
}

/* --------------------------------------------------------------
 *
 * --------------------------------------------------------------
 */
int do_key_down( int board[SIZE][SIZE], int *score, int *nempty )
{
	puts( "DOWN" );
	return 0;
}

/* --------------------------------------------------------------
 *
 * --------------------------------------------------------------
 */
int do_key_left( int board[SIZE][SIZE], int *score, int *nempty )
{
	puts( "LEFT" );
	return 0;
}

/* --------------------------------------------------------------
 *
 * --------------------------------------------------------------
 */
int do_key_right( int board[SIZE][SIZE], int *score, int *nempty )
{
	puts( "RIGHT" );
	return 0;
}

/* --------------------------------------------------------------
 *
 * --------------------------------------------------------------
 */
/**
 * run this program using the console pauser
 * or add your own getch, system("pause")
 * or input loop
 */

int main( void )
{
	int board[SIZE][SIZE];   /* the 4x4 matrix */
	int played;              /* was a move played? */
	int nempty;              /* number of currently empty slots */
	int score;
	int key;                     /* user keypress (see my.h) */
	unsigned int keymask = 0x00; /* indicates Arrow and/or Function Keys */

	score = 0;
	played = 1;  /* true */
	nempty = SIZE * SIZE;

	srand( time( NULL ) );   /* seed PRNG with current time */

	board_init( board );
	board_generate_elem( board, &nempty );
	board_generate_elem( board, &nempty );

	while ( 0 != nempty )
	{
		my_cls();
		board_print( board );
		printf( "Score: %d\n", score );

		key = my_getch( &keymask );
		if ( MY_KEY_ESCAPE == key ) {
			break;
		}

		if ( keymask & MY_KEYMASK_ARROW )
		{
			//puts( "arrow key" );

			switch( key )
			{
				case MY_KEY_UP:
					played = do_key_up(
							board,
							&score,
							&nempty
							);
					break;

				case MY_KEY_DOWN:
					played = do_key_down(
							board,
							&score,
							&nempty
							);
					break;

				case MY_KEY_LEFT:
					played = do_key_left(
							board,
							&score,
							&nempty
							);
					break;

				case MY_KEY_RIGHT:
					played = do_key_right(
							board,
							&score,
							&nempty
							);
					break;
			}

			printf( "played: %d\n", played );
			if ( played ) {
				board_generate_elem( board, &nempty );
			}
		}
	}

	my_cls();
	board_print( board );
	printf( "Score: %d\n", score );

	puts( "GAME OVER" );
	system( "pause" );

	return 0;
}

 

Τα getch() και cls() τα χρησιμοποιώ από ένα πρόχειρο 2ο αρχείο που το λέω my.c, και τα πήρα σχεδόν copy & paste από ένα cross-platform console user interface που είχα φτιάξει παλαιότερα σε C++ (δεν το έχω ολοκληρώσει)...

 

Κώδικας: my.h

 

 

#ifndef MY_H
#define MY_H

/* Determine compilation OS */
#if defined(_WIN32) || defined(_WIN64) || defined(__WINDOWS__) || defined(__TMY_OS_WIN__)
	#define MY_OS_WINDOWS

#elif defined(__linux__) || defined(__linux) || defined(linux) || defined(__gnu_linux__)
	#define MY_OS_LINUX

#elif defined(__unix__) || defined(__unix) || defined(unix) 	\
|| defined(__CYGWIN__) || ( defined(__APPLE__) && defined(__MACH) )
	#define MY_OS_UNIX

#else
	#define MY_OS_UNKNOWN

#endif

/* -------------
 * Includes
 * -------------
 */

#if defined( MY_OS_WINDOWS )
	#include <conio.h>
	#include <windows.h>

#elif defined( MY_OS_UNIX ) || defined( MY_OS_LINUX )
	#include <sys/ioctl.h>
	#include <termios.h>
	#include <unistd.h>
#endif

/* -------------
 * Constants
 * -------------
 */

enum {	/* unbufferd i/o related constants & masks */

	MY_KEYMASK_RESET   = 0x00,
	MY_KEYMASK_ARROW   = (1 << 0),	// 0x01
	MY_KEYMASK_FKEY    = (1 << 1),	// 0x02
	MY_KEYMASK_UNKNOWN = (1 << 2),	// 0x04

	MY_KEY_NUL	 = 0,
	MY_KEY_ESCAPE    = 27,
	MY_KEY_ENTER     = 13,
	MY_KEY_SPACE     = 32,

	MY_KEY_UP        = 72,
	MY_KEY_DOWN      = 80,
	MY_KEY_LEFT      = 75,
	MY_KEY_RIGHT     = 77,
	MY_KEY_INSERT    = 82,
	MY_KEY_DELETE    = 83,
	MY_KEY_HOME      = 71,
	MY_KEY_END	 = 79,
	MY_KEY_PAGE_UP   = 73,
	MY_KEY_PAGE_DOWN = 81,

	MY_KEY_BACKSPACE = 8,

	MY_KEY_F1        = 59,
	MY_KEY_F2        = 60,
	MY_KEY_F3        = 61,
	MY_KEY_F4        = 62,
	MY_KEY_F5        = 63,
	MY_KEY_F6        = 64,
	MY_KEY_F7        = 65,
	MY_KEY_F8        = 66,
	MY_KEY_F9        = 67,
	MY_KEY_F10       = 68,
	MY_KEY_F11       = 133,
	MY_KEY_F12       = 134
};

#ifndef MY_C
extern int my_getch( unsigned int *outKeyMask );
extern int my_cls( void );
#endif

#endif

 

Κώδικας: my.c

 

 

#define MY_C

#include <stdio.h>
#include "my.h"

/* --------------------------------------------------------------
 * 
 * --------------------------------------------------------------
 */
int my_getch( unsigned int *outKeyMask )
{
	int key;

	*outKeyMask = MY_KEYMASK_RESET;

#if defined( MY_OS_WINDOWS )
	/* on Windows platforms */

	key = getch();
	if ( 0 == key ) /* FunctionKey*/
	{
		*outKeyMask |= MY_KEYMASK_FKEY;
		key = getch();
	}
	else if ( 224 == key /* ArrowKey */
	){
		*outKeyMask |= MY_KEYMASK_ARROW;
		key = getch();
	}

#elif defined( MY_OS_UNIX ) || defined( MY_OS_LINUX )
	/* on Linux & Unix platforms */

	#define MY_MAGIC_MAX_CHARS 18

	struct termios	oldt, newt;
	unsigned char	keycodes[ MY_MAGIC_MAX_CHARS ] = {'\0'};
	int		count;

	/* get the terminal settings for stdin */
	tcgetattr( STDIN_FILENO, &oldt );

	/* we want to keep the old setting to restore them at the end */
	newt = oldt;

	/* ? */
	newt.c_cc[ VMIN  ] = MY_MAGIC_MAX_CHARS;
	newt.c_cc[ VTIME ] = 1;
	newt.c_iflag &= ~(IXOFF);

	/* disable canonical mode (buffered i/o) and local echo */
	newt.c_lflag &= ~(ECHO | ICANON);

	/* set the new settings */
//	tcsetattr( STDIN_FILENO, TCSAFLUSH, &newt );
	tcsetattr( STDIN_FILENO, TCSANOW, &newt );

	count = read( fileno(stdin), keycodes, MY_MAGIC_MAX_CHARS );
	if ( 1 == count )
	{
		key = keycodes[0];
		if ( '\r' == key || '\n' == key ) {
			key = MY_KEY_ENTER;
		}
		else if ( '\b' == key || 127 == key ) {
			key = MY_KEY_BACKSPACE;
		}
	}
	else
	{
		if ( '\r' == keycodes[0] || '\n' == keycodes[0] ) {
			key = MY_KEY_ENTER;
		}

		// arrow keys
		else if (0 == memcmp(&keycodes[1], "[A", count-1) ) {
			*outKeyMask |= MY_KEYMASK_ARROW;
			key = MY_KEY_UP;
		}
		else if (0 == memcmp(&keycodes[1], "[B", count-1) ) {
			*outKeyMask |= MY_KEYMASK_ARROW;
			key = MY_KEY_DOWN;
		}
		else if (0 == memcmp(&keycodes[1], "[C", count-1) ) {
			*outKeyMask |= MY_KEYMASK_ARROW;
			key = MY_KEY_RIGHT;
		}
		else if (0 == memcmp(&keycodes[1], "[D", count-1) ) {
			*outKeyMask |= MY_KEYMASK_ARROW;
			key = MY_KEY_LEFT;
		}

		// insert & delete keys
		else if (0 == memcmp(&keycodes[1], "[2~", count-1) ) {
			*outKeyMask |= MY_KEYMASK_ARROW;
			key = MY_KEY_INSERT;
		}
		else if (0 == memcmp(&keycodes[1], "[3~", count-1) ) {
			*outKeyMask |= MY_KEYMASK_ARROW;
			key = MY_KEY_DELETE;
		}

		// home & end keys
		else if (0 == memcmp(&keycodes[1], "OH", count-1) ) {
			*outKeyMask |= MY_KEYMASK_ARROW;
			key = MY_KEY_HOME;
		}
		else if (0 == memcmp(&keycodes[1], "OF", count-1) ) {
			*outKeyMask |= MY_KEYMASK_ARROW;
			key = MY_KEY_END;
		}

		// page-up & page-down keys
		else if (0 == memcmp(&keycodes[1], "[5~", count-1) ) {
			*outKeyMask |= MY_KEYMASK_ARROW;
			key = MY_KEY_PAGE_UP;
		}
		else if (0 == memcmp(&keycodes[1], "[6~", count-1) ) {
			*outKeyMask |= MY_KEYMASK_ARROW;
			key = MY_KEY_PAGE_DOWN;
		}

		// FKEYS
		else if (0 == memcmp(&keycodes[1], "OP", count-1) ) {
			*outKeyMask |= MY_KEYMASK_FKEY;
			key = MY_KEY_F1;
		}
		else if (0 == memcmp(&keycodes[1], "OQ", count-1) ) {
			*outKeyMask |= MY_KEYMASK_FKEY;
			key = MY_KEY_F2;
		}
		else if (0 == memcmp(&keycodes[1], "OR", count-1) ) {
			*outKeyMask |= MY_KEYMASK_FKEY;
			key = MY_KEY_F3;
		}
		else if (0 == memcmp(&keycodes[1], "OS", count-1) ) {
			*outKeyMask |= MY_KEYMASK_FKEY;
			key = MY_KEY_F4;
		}
		else if (0 == memcmp(&keycodes[1], "[15~", count-1) ) {
			*outKeyMask |= MY_KEYMASK_FKEY;
			key = MY_KEY_F5;
		}
		else if (0 == memcmp(&keycodes[1], "[17~", count-1) ) {
			*outKeyMask |= MY_KEYMASK_FKEY;
			key = MY_KEY_F6;
		}
		else if (0 == memcmp(&keycodes[1], "[18~", count-1) ) {
			*outKeyMask |= MY_KEYMASK_FKEY;
			key = MY_KEY_F7;
		}
		else if (0 == memcmp(&keycodes[1], "[19~", count-1) ) {
			*outKeyMask |= MY_KEYMASK_FKEY;
			key = MY_KEY_F8;
		}
		else if (0 == memcmp(&keycodes[1], "[20~", count-1) ) {
			*outKeyMask |= MY_KEYMASK_FKEY;
			key = MY_KEY_F9;
		}
		else if (0 == memcmp(&keycodes[1], "[24~", count-1) ) {
			*outKeyMask |= MY_KEYMASK_FKEY;
			key = MY_KEY_F12;
		}

		// other multi-character ANSI escape sequences
		else {
			*outKeyMask |= MY_KEYMASK_UNKNOWN;
			key = -(int)keycodes[count-1];
		}
	}

	/* restore the former settings */
	tcsetattr ( STDIN_FILENO, TCSANOW, &oldt );

#else 	/* On Unsupported Platforms, fall-back to bufferd getchar() */
	key = getchar();
#endif

	return key;
}

/* -----------------------------------------------------
 * Cross-platform function to clear the standard output.
 *
 * It works both on the Windows console and on terminals that
 * support ANSI escape sequences (that is on most Unix/Linux
 * terminals).
 * --------------------------------------------------------------
 */
int my_cls( void )
{
#if defined( MY_OS_WINDOWS )

	HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
	COORD coordScreen = {0, 0};	/* home for the cursor */
	DWORD cCharsWritten;
	CONSOLE_SCREEN_BUFFER_INFO csbi;
	DWORD dwConSize;

	if ( INVALID_HANDLE_VALUE == hConsole) {
		return 0;
	}

	// get the number of character cells in the current buffer
	if ( !GetConsoleScreenBufferInfo(hConsole, &csbi) ) {
		return 0;
	}

	dwConSize = csbi.dwSize.X * csbi.dwSize.Y;

	// fill the entire screen with blanks
	if ( !FillConsoleOutputCharacter(
		hConsole,		/* Handle to console screen buffer */
		(TCHAR) ' ',		/* Character to write to the buffer */
		dwConSize,		/* Number of cells to write */
		coordScreen,		/* Coordinates of first cell */
		&cCharsWritten )	/* Receive number of characters written */
	){
		return 0;
	}

	// get the current text attribute
	if ( !GetConsoleScreenBufferInfo(hConsole, &csbi) ) {
		return 0;
	}

	// set the buffer's attributes accordingly
	if ( !FillConsoleOutputAttribute(
		hConsole,		/* Handle to console screen buffer */
		csbi.wAttributes,	/* Character attributes to use */
		dwConSize,		/* Number of cells to set attribute */
		coordScreen,		/* Coordinates of first cell */
		&cCharsWritten )	/* Receive number of characters written */
	){
		return 0;
	}

	// put the cursor at its home coordinates
	if ( !SetConsoleCursorPosition(hConsole, coordScreen) ) {
		return 0;
	}

#elif defined( MY_OS_UNIX ) || defined( MY_OS_LINUX )
	printf( "%s%s", "\033[2J", "\033[H" );
	fflush( stdout );

#else	/* On Unsupported Platforms */
	for (int i=0; i < 24; i++)
		putchar( '\n' );
#endif

	return 1;
}

 

Βασικά δεν ξέρω αν δουλεύει σωστά ως λογική το game, τέτοια ώρα που είναι δεν ασχολήθηκα με αλγόριθμους. Αυτό που είχες εσύ κράτησα, κι απλώς προσέθεσα μερικά παραπάνω chekcs για την τιμή επιστροφής της do_key_up().

 

Τέλος, για να κάνεις και το τελευταίο κομμάτι που έχει μείνει (δηλαδή τα χρώματα) cross-platform, μπορείς αν θέλεις να χρησιμοποιήσεις ένα απλό στη χρήση σχετικό user-interface, που είχα φτιάξει αποκλειστικά στον προεπεξεργαστή της C.

 

Μπορείς να βρεις εδώ την έκδοση 1.03, αλλά είχα κάνει και έκδοση 1.04(h2)-alpha που δεν την κυκλοφόρησα (το λινκ σε πάει στην online τεκμηρίωσή της, αλλά αν τη θέλεις πες μου να σου την στείλω με p.m.)

 

Καλή συνέχεια.

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

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

Ευχαριστώ για τις απαντήσεις.

1. Τα μαγικά νούμερα είναι από τα λίγα πράγματα που είναι σίγουρα σωστά. Είναι απλοί κωδικοί για χρώματα.

 

2. Όντως το κύριο πρόβλημα ήταν ότι ξέχασα να αρχικοποιήσω τον temp με μηδενικά και η συναρτηση insert επεφτε σε infinite loop. διόρθωσα και λίγα πράγματα στην λογική ακόμη και τα ξαναανέβασα στο αρχικό λινκ του github. Βεβαια το παιχνίδι ακόμη δεν δουλεύει σωστά (βάζει πάνω από έναν νέους αριθμούς σε κάποιους γύρους, δέχεται άκυρες κινήσεις κλπ) αλλά δείχνει κάποιες σωστές αντιδράσεις. όταν βρω χρόνο θα διαβάσω τον κώδικά σου migf1.Τα χρώματα είχα διαβάσει ότι ισχύουν μόνο για windows, θα διαβάσω αυτά που μου έστειλες αν και δεν με πολυενδιαφέρει πολύ το cross-platform του θέματος. Το πολύ πολύ αν ένας φίλος μου έχει όρεξη μπορεί να του το δώσω να το δουλέψει σε android.

 

edit: νομίζω ότι έχω διορθώσει πλέον όλα τα bugs. ορίστε και μια έτοιμη έκδοση για άμεσο κάψιμο!

2048.zip

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

Ωραίο, δειχνει να δουλευει σωστα. Μια απορία εχω - πως γινεται το .exe που δινεις να ειναι 400ΚΒ, ενώ αυτο που εκανα εγω compile με το gcc να ειναι 90ΚΒ;

Δεν έχω ιδέα :)

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

Ωραίο, δειχνει να δουλευει σωστα. Μια απορία εχω - πως γινεται το .exe που δινεις να ειναι 400ΚΒ, ενώ αυτο που εκανα εγω compile με το gcc να ειναι 90ΚΒ;

 

Διαφορετικα compile parameters? Πιθανη εκδοχη..Πχ σε ιδιο προγραμμα gcc μπλα μπλα με gcc -std=c99 αλλαζει τα πραγματα

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

Διαφορετικα compile parameters? Πιθανη εκδοχη..Πχ σε ιδιο προγραμμα gcc μπλα μπλα με gcc -std=c99 αλλαζει τα πραγματα

Επίσης οι πολλές βελτιστοποιήσεις compilers αυξάνουν το μέγεθος κατά πολύ.

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

Διαφορετικα compile parameters? Πιθανη εκδοχη..Πχ σε ιδιο προγραμμα gcc μπλα μπλα με gcc -std=c99 αλλαζει τα πραγματα

Τόσο μεγάλη διαφορά όμως; Με c99 δεν κανει compile, και με -O1 ή -Ο2 το μεγεθος αλλάζει ελάχιστα.

 

Μπορει να έχει σχέση η έκδοση του gcc; Εγω έχω την 4.8.1.

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

@tifosi: Ωραίος. Αν ευκαιρήσω αργότερα, θα δω μήπως το ντύσω με x-platform χρώματα και του βάλω να κρατάει και best-score.

 

@bnvdarklord: Δοκίμασε να βάλεις -s flag στον gcc (κάνει strip τα symbols από το εκτελέσιμο). Επιπρόσθετα, μπορείς να δοκιμάσεις και -Os flag (optimize for size).

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

Λοιπόν, κάτι έκανα. Μου βγήκε λίγο μεγάλο βέβαια, αλλά δεν βαριέσαι...

 

post-38307-0-77910000-1403493165_thumb.png

 

Download: 2048.zip (κώδικας και 32μπιτο εκτελέσιμο Windows).

 

Για όσους ασχοληθούν, ο κώδικας αποτελείται από τα εξής αρχεία:

main.c      (the main program)
tui.c/tui.h (text-user-interface of the game)
con_color.h (my preprocessor interface for console colored output)
my.c/my.h   (primitive x-platform console/terminal utility funcs)
common.h    (defs & types common to the prog and its text ui)
Το main.c περιέχει το κυρίως πρόγραμμα, το tui.c περιέχει ότι σχετίζεται με το text-user-interface, και το common.h περιέχει κοινούς τους τύπους & σταθερές.

 

Το my.c είναι μια λίγο πιο εμπλουτισμένη έκδοση από αυτήν που είχα δώσει σε προηγούμενο πόστ, για τη διαχείριση του κέρσορα, κλπ στην κονσόλα, και είναι πλήρως αυτόνομο. Θεωρητικά είναι cross-platform, αλλά το δοκίμασα μονάχα σε Windows (αν έχετε πρόβλημα σε *nix, πείτε μου και θα δω τι μπορώ να κάνω).

 

Το con_color.h (και το συνοδευτικό con_color_private.h) είναι επίσης αυτόνομο, και ασχολείται με τα χρώματα της κονσόλας/τερματικού. Αυτό είναι δοκιμασμένα cross-platform (btw είναι καινούρια έκδοση, που δεν την έχω στο site μου).

 

Πάνω σε αυτά τα δυο "πατάει" το tui.c, με σκοπό να τα κρύψει από το main.c.

 

Για να κάνετε compile τον κώδικα, θέλετε C99. Βάλτε όλα αρχεία σε έναν φάκελο και με gcc δώστε:

gcc -std=c99 -O2 -s my.c tui.c main.c
Για άλλους compilers, φτιάξτε ένα project, προσθέστε του τα παραπάνω αρχεία και ενεργοποιήστε την C99 υποστήριξη.

 

Ο κώδικας έχει παρά πολλά σχόλια, αλλά δεν είμαι 100% σίγουρος πως δεν περιέχει bugs. Τον έγραψα εν μέσω αγώνων μουντιάλ, οπότε δείξτε επιείκεια :lol: Αλγοριθμικά δεν ασχολήθηκα, πέρα από το να δομήσω τον αλγόριθμο του φίλου tifosi σε μικρότερες συναρτήσεις και να τις προσαρμόσω στον δικό μου κώδικα (τώρα, αν έχω κάνει καμιά πατάτα, θα δείξει).

 

Btw, ο κώδικας είναι τελείως free... κάντε τον ότι νομίζετε (εκτός από το να τον παρουσιάσετε σαν δικό σας :P). Αν βρείτε τίποτα bugs, σφυρίξτε τα εδώ στο νήμα να τα δούμε.

 

Have fun & keep in touch :P

 

 

Καλά, τι ματσάρες είναι αυτές που βλέπουμε στο μουντιάλ! Μακράν το καλύτερο που θυμάμαι, κι υποτίθεται πως είμαστε ακόμα στο 1ο στάδιο, που παίζει όλος ο κατιμάς.

 

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

Ο καλά εισαι.... Αλγερια χθές και μετα Πορτογαλία... αν και Πορτογαλια με πηρε ο ύπνος ειδα μονο 1 ημιχρονο. Στο στοιχημα πιάνω το Χ της Ελλάδας το οβερ της Κολομβιας και χάνω την Αγγλία :o 

 

Χθες δεν έπαιξα καν πολυ επικινδυνα παιχνιδια.

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

@bnvdarklord: Δοκίμασε να βάλεις -s flag στον gcc (κάνει strip τα symbols από το εκτελέσιμο). Επιπρόσθετα, μπορείς να δοκιμάσεις και -Os flag (optimize for size).

Κάτι αλλο θα "φταίει", γιατι με το -s μειώνεται ακόμα περισσότερο στα 20KB. Χρήσιμο flag, αν και φαντάζομαι θα έχει καποια drawbacks.

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

Κάτι αλλο θα "φταίει", γιατι με το -s μειώνεται ακόμα περισσότερο στα 20KB. Χρήσιμο flag, αν και φαντάζομαι θα έχει καποια drawbacks.

Αυτό δεν ήταν το ζητούμενο; Να μειωθεί δηλαδή το μέγεθος του εκτελέσιμου, ή κατάλαβα λάθος;

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

Αυτό δεν ήταν το ζητούμενο; Να μειωθεί δηλαδή το μέγεθος του εκτελέσιμου, ή κατάλαβα λάθος;

Αυτο που αναρωτήθηκα ειναι πως γινεται το εκτελέσιμο του OP να ειναι 400KB, ενω το δικο μου, με οτι flag δοκιμασα να ειναι παντα λιγοτερο απο 100ΚΒ. Μπορεί άλλος compiler να παράγει τοσο μεγαλύτερο exe;

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

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

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

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

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

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

Σύνδεση

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

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

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