diff --git a/2048_curses.c b/2048_curses.c index 9098e7c..9836c08 100644 --- a/2048_curses.c +++ b/2048_curses.c @@ -28,13 +28,11 @@ free(ptr);\ } while (0) -/* Define a sequence that should be executed each turn */ +/* should be executed each turn */ #define TURN(x)\ - do {\ - gravitate(x);\ - merge(x);\ - gravitate(x);\ - } while (0) + gravitate(x) +\ + merge(x) +\ + gravitate(x) /* maximum length of any value in grid, for printing */ int MAXVAL; @@ -59,9 +57,10 @@ int hs; char *file; /* Merges adjacent squares of the same value together in a certain direction */ -void merge(int d) +int merge(int d) { - if (d == DL || d == DR) { + int moved = 0; + if (d == DL) { int i, j; for (i = 0; i < SZ; i++) { for (j = 0; j < SZ; j++) { @@ -70,11 +69,12 @@ void merge(int d) sl += g[i][j]; s += g[i][j]; g[i][j++ + 1] = 0; + moved = 1; } } } } - else { + else if (d == DU) { int i, j; for (i = 0; i < SZ; i++) { for (j = 0; j < SZ; j++) { @@ -83,18 +83,49 @@ void merge(int d) sl += g[j][i]; s += g[j][i]; g[j++ + 1][i] = 0; + moved = 1; } } } } + else if (d == DR) { + int i, j; + for (i = SZ - 1; i >= 0; i--) { + for (j = SZ - 1; j >= 0; j--) { + if (j > 0 && g[i][j] && g[i][j] == g[i][j - 1]) { + g[i][j] <<= 1; + sl += g[i][j]; + s += g[i][j]; + g[i][j-- - 1] = 0; + moved = 1; + } + } + } + } + else if (d == DD) { + int i, j; + for (i = SZ - 1; i >= 0; i--) { + for (j = SZ - 1; j >= 0; j--) { + if (j > 0 && g[j][i] && g[j][i] == g[j - 1][i]) { + g[j][i] <<= 1; + sl += g[j][i]; + s += g[j][i]; + g[j-- - 1][i] = 0; + moved = 1; + } + } + } + } + return moved; } /* move all values in the grid to the edge given by the direction pressed */ /* would be nice to generalize this code a little so didn't need four loops */ /* if animations are wanted, then need to alter this so it moves each square one at a time */ -void gravitate(int d) +int gravitate(int d) { + int moved = 0; if (d == DL) { int i, j; for (i = 0; i < SZ; i++) { @@ -105,6 +136,7 @@ void gravitate(int d) if (j + st < SZ) { g[i][j] = g[i][j + st]; g[i][j + st] = 0; + moved = 1; } } } @@ -119,6 +151,7 @@ void gravitate(int d) if (j + st < SZ) { g[j][i] = g[j + st][i]; g[j + st][i] = 0; + moved = 1; } } } @@ -133,6 +166,7 @@ void gravitate(int d) if (j - st >= 0) { g[i][j] = g[i][j - st]; g[i][j - st] = 0; + moved = 1; } } } @@ -147,10 +181,12 @@ void gravitate(int d) if (j - st >= 0) { g[j][i] = g[j - st][i]; g[j - st][i] = 0; + moved = 1; } } } } + return moved; } /* load hiscore */ @@ -171,13 +207,13 @@ void save_score() { } } -/* returns if there are any available spaces left on the grid */ -int space_left() +/* returns if there are any possible moves */ +int moves_available() { int i, j; for (i = 0; i < SZ; i++) for (j = 0; j < SZ; j++) - if (!g[i][j]) + if (!g[i][j] || ((i + 1 < SZ) && (g[i][j] == g[i + 1][j])) || ((j + 1 < SZ) && (g[i][j] == g[i][j + 1]))) return 1; return 0; } @@ -186,18 +222,9 @@ int space_left() /* could do this in a much smarter fashion by finding which spaces are free */ void rand_block() { - if (space_left()) { - int x_p, y_p; - while (g[x_p = rand() % SZ][y_p = rand() % SZ]); - g[x_p][y_p] = (rand() & 3) ? 2 : 4; - } - else { - endwin(); - printf("\n" - "YOU LOSE! - Your score was %d\n", s); - save_score(); - exit(EXIT_SUCCESS); - } + int x_p, y_p; + while (g[x_p = rand() % SZ][y_p = rand() % SZ]); + g[x_p][y_p] = (rand() & 3) ? 2 : 4; } /* quick floor log2(n) */ @@ -329,10 +356,11 @@ int main(int argc, char **argv) ITER(2, rand_block()); draw_grid(gamewin); - int key; + int key, moved; while (1) { /* will goto this if we didn't get a valid keypress */ retry:; + moved = 0; key = wgetch(gamewin); sl = 0; @@ -341,22 +369,22 @@ int main(int argc, char **argv) case 'h': case 'a': case KEY_LEFT: - TURN(DL); + moved = TURN(DL); break; case 'l': case 'd': case KEY_RIGHT: - TURN(DR); + moved = TURN(DR); break; case 'j': case 's': case KEY_DOWN: - TURN(DD); + moved = TURN(DD); break; case 'k': case 'w': case KEY_UP: - TURN(DU); + moved = TURN(DU); break; case 'q': FREE2D(g, SZ); @@ -368,8 +396,18 @@ int main(int argc, char **argv) default: goto retry; } + + if (!moves_available()) { + endwin(); + printf("\n" + "YOU LOSE! - Your score was %d\n", s); + save_score(); + exit(EXIT_SUCCESS); + } - ITER(n_blocks, rand_block()); - draw_grid(gamewin); + if (moved) { + ITER(n_blocks, rand_block()); + draw_grid(gamewin); + } } } diff --git a/2048_no_curses.c b/2048_no_curses.c index f936494..66dfd4e 100644 --- a/2048_no_curses.c +++ b/2048_no_curses.c @@ -33,11 +33,9 @@ /* Define a sequence that should be executed each turn */ #define TURN(x)\ - do {\ - gravitate(x);\ - merge(x);\ - gravitate(x);\ - } while (0) + gravitate(x) +\ + merge(x) +\ + gravitate(x) /* direction enumeration */ enum {DR, DU, DL, DD}; @@ -59,9 +57,10 @@ int hs; char *file; /* Merges adjacent squares of the same value together in a certain direction */ -void merge(int d) +int merge(int d) { - if (d == DL || d == DR) { + int moved = 0; + if (d == DL) { int i, j; for (i = 0; i < SZ; i++) { for (j = 0; j < SZ; j++) { @@ -70,11 +69,12 @@ void merge(int d) sl += g[i][j]; s += g[i][j]; g[i][j++ + 1] = 0; + moved = 1; } } } } - else { + else if (d == DU) { int i, j; for (i = 0; i < SZ; i++) { for (j = 0; j < SZ; j++) { @@ -83,17 +83,48 @@ void merge(int d) sl += g[j][i]; s += g[j][i]; g[j++ + 1][i] = 0; + moved = 1; } } } } + else if (d == DR) { + int i, j; + for (i = SZ - 1; i >= 0; i--) { + for (j = SZ - 1; j >= 0; j--) { + if (j > 0 && g[i][j] && g[i][j] == g[i][j - 1]) { + g[i][j] <<= 1; + sl += g[i][j]; + s += g[i][j]; + g[i][j-- - 1] = 0; + moved = 1; + } + } + } + } + else if (d == DD) { + int i, j; + for (i = SZ - 1; i >= 0; i--) { + for (j = SZ - 1; j >= 0; j--) { + if (j > 0 && g[j][i] && g[j][i] == g[j - 1][i]) { + g[j][i] <<= 1; + sl += g[j][i]; + s += g[j][i]; + g[j-- - 1][i] = 0; + moved = 1; + } + } + } + } + return moved; } /* move all values in the grid to the edge given by the direction pressed */ /* would be nice to generalize this code a little so didn't need four loops */ -void gravitate(int d) +int gravitate(int d) { + int moved = 0; if (d == DL) { int i, j; for (i = 0; i < SZ; i++) { @@ -104,6 +135,7 @@ void gravitate(int d) if (j + st < SZ) { g[i][j] = g[i][j + st]; g[i][j + st] = 0; + moved = 1; } } } @@ -118,6 +150,7 @@ void gravitate(int d) if (j + st < SZ) { g[j][i] = g[j + st][i]; g[j + st][i] = 0; + moved = 1; } } } @@ -132,6 +165,7 @@ void gravitate(int d) if (j - st >= 0) { g[i][j] = g[i][j - st]; g[i][j - st] = 0; + moved = 1; } } } @@ -146,10 +180,12 @@ void gravitate(int d) if (j - st >= 0) { g[j][i] = g[j - st][i]; g[j - st][i] = 0; + moved = 1; } } } } + return moved; } /* loads hiscore */ @@ -170,13 +206,13 @@ void save_score() { } } -/* returns if there are any available spaces left on the grid */ -int space_left() +/* returns if there are any possible moves */ +int moves_available() { int i, j; for (i = 0; i < SZ; i++) for (j = 0; j < SZ; j++) - if (!g[i][j]) + if (!g[i][j] || ((i + 1 < SZ) && (g[i][j] == g[i + 1][j])) || ((j + 1 < SZ) && (g[i][j] == g[i][j + 1]))) return 1; return 0; } @@ -185,18 +221,9 @@ int space_left() /* do this in a smarter fashion */ void rand_block() { - if (space_left()) { - int x_p, y_p; - while (g[x_p = rand() % SZ][y_p = rand() % SZ]); - g[x_p][y_p] = (rand() & 3) ? 2 : 4; - } - else { - printf("\n" - "YOU LOSE\n" - "Your score was %d\n", s); - save_score(); - exit(EXIT_SUCCESS); - } + int x_p, y_p; + while (g[x_p = rand() % SZ][y_p = rand() % SZ]); + g[x_p][y_p] = (rand() & 3) ? 2 : 4; } /* draws the grid and fills it with the current values */ @@ -302,11 +329,11 @@ int main(int argc, char **argv) tattr.c_lflag &= ~(ICANON | ECHO); tcsetattr(STDOUT_FILENO, TCSANOW, &tattr); - int key; - + int key, moved; while (1) { /* will goto this if we didn't get a valid keypress */ - retry:; + retry:; + moved = 0; key = getchar(); sl = 0; @@ -314,19 +341,19 @@ int main(int argc, char **argv) switch (key) { case 'h': case 'a': - TURN(DL); + moved = TURN(DL); break; case 'l': case 'd': - TURN(DR); + moved = TURN(DR); break; case 'j': case 's': - TURN(DD); + moved = TURN(DD); break; case 'k': case 'w': - TURN(DU); + moved = TURN(DU); break; case 'q': save_score(); @@ -334,8 +361,17 @@ int main(int argc, char **argv) default: goto retry; } + + if (!moves_available()) { + printf("\n" + "YOU LOSE! - Your score was %d\n", s); + save_score(); + exit(EXIT_SUCCESS); + } - ITER(n_blocks, rand_block()); - draw_grid(); + if (moved) { + ITER(n_blocks, rand_block()); + draw_grid(); + } } } diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..58abe0f --- /dev/null +++ b/Makefile @@ -0,0 +1,10 @@ +CC=gcc +CCARGS= + +all: 2048 2048_no_curses + +2048: 2048_curses.c + $(CC) $(CCARGS) 2048_curses.c -lcurses -o 2048 + +2048_no_curses: 2048_no_curses.c + gcc 2048_no_curses.c -o 2048_no_curses