From f25b57e018b6dab4e8eca274d668e036329fa6f8 Mon Sep 17 00:00:00 2001 From: Aaron Bulmahn Date: Thu, 17 Apr 2014 21:46:34 +0200 Subject: [PATCH 1/4] fix logic: combine tiles on the right side --- 2048_curses.c | 30 ++++++++++++++++++++++++++++-- 2048_no_curses.c | 30 ++++++++++++++++++++++++++++-- 2 files changed, 56 insertions(+), 4 deletions(-) diff --git a/2048_curses.c b/2048_curses.c index 9098e7c..34803fa 100644 --- a/2048_curses.c +++ b/2048_curses.c @@ -61,7 +61,7 @@ char *file; /* Merges adjacent squares of the same value together in a certain direction */ void merge(int d) { - if (d == DL || d == DR) { + if (d == DL) { int i, j; for (i = 0; i < SZ; i++) { for (j = 0; j < SZ; j++) { @@ -74,7 +74,7 @@ void merge(int d) } } } - else { + else if (d == DU) { int i, j; for (i = 0; i < SZ; i++) { for (j = 0; j < SZ; j++) { @@ -87,6 +87,32 @@ void merge(int d) } } } + 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; + } + } + } + } + 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; + } + } + } + } } diff --git a/2048_no_curses.c b/2048_no_curses.c index f936494..73ed6d8 100644 --- a/2048_no_curses.c +++ b/2048_no_curses.c @@ -61,7 +61,7 @@ char *file; /* Merges adjacent squares of the same value together in a certain direction */ void merge(int d) { - if (d == DL || d == DR) { + if (d == DL) { int i, j; for (i = 0; i < SZ; i++) { for (j = 0; j < SZ; j++) { @@ -74,7 +74,7 @@ void merge(int d) } } } - else { + else if (d == DU) { int i, j; for (i = 0; i < SZ; i++) { for (j = 0; j < SZ; j++) { @@ -87,6 +87,32 @@ void merge(int d) } } } + 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; + } + } + } + } + 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; + } + } + } + } } From 267678ed0240be1bdda110d74f462f754dc891c2 Mon Sep 17 00:00:00 2001 From: Aaron Bulmahn Date: Thu, 17 Apr 2014 22:07:32 +0200 Subject: [PATCH 2/4] fix logic: don't add tiles if nothing moved --- 2048_curses.c | 43 ++++++++++++++++++++++++++++--------------- 2048_no_curses.c | 44 ++++++++++++++++++++++++++++---------------- 2 files changed, 56 insertions(+), 31 deletions(-) diff --git a/2048_curses.c b/2048_curses.c index 34803fa..9c9bf21 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,8 +57,9 @@ int hs; char *file; /* Merges adjacent squares of the same value together in a certain direction */ -void merge(int d) +int merge(int d) { + int moved = 0; if (d == DL) { int i, j; for (i = 0; i < SZ; i++) { @@ -70,6 +69,7 @@ void merge(int d) sl += g[i][j]; s += g[i][j]; g[i][j++ + 1] = 0; + moved = 1; } } } @@ -83,6 +83,7 @@ void merge(int d) sl += g[j][i]; s += g[j][i]; g[j++ + 1][i] = 0; + moved = 1; } } } @@ -96,6 +97,7 @@ void merge(int d) sl += g[i][j]; s += g[i][j]; g[i][j-- - 1] = 0; + moved = 1; } } } @@ -109,18 +111,21 @@ void merge(int d) 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++) { @@ -131,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; } } } @@ -145,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; } } } @@ -159,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; } } } @@ -173,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 */ @@ -355,10 +365,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; @@ -367,22 +378,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); @@ -395,7 +406,9 @@ int main(int argc, char **argv) goto retry; } - 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 73ed6d8..500ec29 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,8 +57,9 @@ int hs; char *file; /* Merges adjacent squares of the same value together in a certain direction */ -void merge(int d) +int merge(int d) { + int moved = 0; if (d == DL) { int i, j; for (i = 0; i < SZ; i++) { @@ -70,6 +69,7 @@ void merge(int d) sl += g[i][j]; s += g[i][j]; g[i][j++ + 1] = 0; + moved = 1; } } } @@ -83,6 +83,7 @@ void merge(int d) sl += g[j][i]; s += g[j][i]; g[j++ + 1][i] = 0; + moved = 1; } } } @@ -96,6 +97,7 @@ void merge(int d) sl += g[i][j]; s += g[i][j]; g[i][j-- - 1] = 0; + moved = 1; } } } @@ -109,17 +111,20 @@ void merge(int d) 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++) { @@ -130,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; } } } @@ -144,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; } } } @@ -158,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; } } } @@ -172,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 */ @@ -328,11 +338,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; @@ -340,19 +350,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(); @@ -361,7 +371,9 @@ int main(int argc, char **argv) goto retry; } - ITER(n_blocks, rand_block()); - draw_grid(); + if (moved) { + ITER(n_blocks, rand_block()); + draw_grid(); + } } } From 99c159c98258c5f49e6a9256d06c238e363fe275 Mon Sep 17 00:00:00 2001 From: Aaron Bulmahn Date: Thu, 17 Apr 2014 22:13:35 +0200 Subject: [PATCH 3/4] fixed "game over" message not appearing --- 2048_curses.c | 29 ++++++++++++++--------------- 2048_no_curses.c | 28 +++++++++++++--------------- 2 files changed, 27 insertions(+), 30 deletions(-) diff --git a/2048_curses.c b/2048_curses.c index 9c9bf21..9836c08 100644 --- a/2048_curses.c +++ b/2048_curses.c @@ -207,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; } @@ -222,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) */ @@ -405,6 +396,14 @@ 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); + } if (moved) { ITER(n_blocks, rand_block()); diff --git a/2048_no_curses.c b/2048_no_curses.c index 500ec29..66dfd4e 100644 --- a/2048_no_curses.c +++ b/2048_no_curses.c @@ -206,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; } @@ -221,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 */ @@ -370,6 +361,13 @@ 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); + } if (moved) { ITER(n_blocks, rand_block()); From cceb83134b528d2fa69686bb87a12ed033beaf4f Mon Sep 17 00:00:00 2001 From: Aaron Bulmahn Date: Thu, 17 Apr 2014 22:20:40 +0200 Subject: [PATCH 4/4] added Makefile --- Makefile | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 Makefile 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