Merge pull request #2 from arbu/master

Some changes to the logic, so the game is closer to the original
This commit is contained in:
Tiehuis 2014-04-19 18:38:52 +12:00
commit 73d328c3a0
3 changed files with 149 additions and 65 deletions

View File

@ -28,13 +28,11 @@
free(ptr);\ free(ptr);\
} while (0) } while (0)
/* Define a sequence that should be executed each turn */ /* should be executed each turn */
#define TURN(x)\ #define TURN(x)\
do {\ gravitate(x) +\
gravitate(x);\ merge(x) +\
merge(x);\ gravitate(x)
gravitate(x);\
} while (0)
/* maximum length of any value in grid, for printing */ /* maximum length of any value in grid, for printing */
int MAXVAL; int MAXVAL;
@ -59,9 +57,10 @@ int hs;
char *file; char *file;
/* Merges adjacent squares of the same value together in a certain direction */ /* 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; int i, j;
for (i = 0; i < SZ; i++) { for (i = 0; i < SZ; i++) {
for (j = 0; j < SZ; j++) { for (j = 0; j < SZ; j++) {
@ -70,11 +69,12 @@ void merge(int d)
sl += g[i][j]; sl += g[i][j];
s += g[i][j]; s += g[i][j];
g[i][j++ + 1] = 0; g[i][j++ + 1] = 0;
moved = 1;
} }
} }
} }
} }
else { else if (d == DU) {
int i, j; int i, j;
for (i = 0; i < SZ; i++) { for (i = 0; i < SZ; i++) {
for (j = 0; j < SZ; j++) { for (j = 0; j < SZ; j++) {
@ -83,18 +83,49 @@ void merge(int d)
sl += g[j][i]; sl += g[j][i];
s += g[j][i]; s += g[j][i];
g[j++ + 1][i] = 0; 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 */ /* 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 */ /* 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 */ /* 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) { if (d == DL) {
int i, j; int i, j;
for (i = 0; i < SZ; i++) { for (i = 0; i < SZ; i++) {
@ -105,6 +136,7 @@ void gravitate(int d)
if (j + st < SZ) { if (j + st < SZ) {
g[i][j] = g[i][j + st]; g[i][j] = g[i][j + st];
g[i][j + st] = 0; g[i][j + st] = 0;
moved = 1;
} }
} }
} }
@ -119,6 +151,7 @@ void gravitate(int d)
if (j + st < SZ) { if (j + st < SZ) {
g[j][i] = g[j + st][i]; g[j][i] = g[j + st][i];
g[j + st][i] = 0; g[j + st][i] = 0;
moved = 1;
} }
} }
} }
@ -133,6 +166,7 @@ void gravitate(int d)
if (j - st >= 0) { if (j - st >= 0) {
g[i][j] = g[i][j - st]; g[i][j] = g[i][j - st];
g[i][j - st] = 0; g[i][j - st] = 0;
moved = 1;
} }
} }
} }
@ -147,10 +181,12 @@ void gravitate(int d)
if (j - st >= 0) { if (j - st >= 0) {
g[j][i] = g[j - st][i]; g[j][i] = g[j - st][i];
g[j - st][i] = 0; g[j - st][i] = 0;
moved = 1;
} }
} }
} }
} }
return moved;
} }
/* load hiscore */ /* load hiscore */
@ -171,13 +207,13 @@ void save_score() {
} }
} }
/* returns if there are any available spaces left on the grid */ /* returns if there are any possible moves */
int space_left() int moves_available()
{ {
int i, j; int i, j;
for (i = 0; i < SZ; i++) for (i = 0; i < SZ; i++)
for (j = 0; j < SZ; j++) 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 1;
return 0; return 0;
} }
@ -186,19 +222,10 @@ int space_left()
/* could do this in a much smarter fashion by finding which spaces are free */ /* could do this in a much smarter fashion by finding which spaces are free */
void rand_block() void rand_block()
{ {
if (space_left()) {
int x_p, y_p; int x_p, y_p;
while (g[x_p = rand() % SZ][y_p = rand() % SZ]); while (g[x_p = rand() % SZ][y_p = rand() % SZ]);
g[x_p][y_p] = (rand() & 3) ? 2 : 4; 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);
}
}
/* quick floor log2(n) */ /* quick floor log2(n) */
int flog2(int n) int flog2(int n)
@ -329,10 +356,11 @@ int main(int argc, char **argv)
ITER(2, rand_block()); ITER(2, rand_block());
draw_grid(gamewin); draw_grid(gamewin);
int key; int key, moved;
while (1) { while (1) {
/* will goto this if we didn't get a valid keypress */ /* will goto this if we didn't get a valid keypress */
retry:; retry:;
moved = 0;
key = wgetch(gamewin); key = wgetch(gamewin);
sl = 0; sl = 0;
@ -341,22 +369,22 @@ int main(int argc, char **argv)
case 'h': case 'h':
case 'a': case 'a':
case KEY_LEFT: case KEY_LEFT:
TURN(DL); moved = TURN(DL);
break; break;
case 'l': case 'l':
case 'd': case 'd':
case KEY_RIGHT: case KEY_RIGHT:
TURN(DR); moved = TURN(DR);
break; break;
case 'j': case 'j':
case 's': case 's':
case KEY_DOWN: case KEY_DOWN:
TURN(DD); moved = TURN(DD);
break; break;
case 'k': case 'k':
case 'w': case 'w':
case KEY_UP: case KEY_UP:
TURN(DU); moved = TURN(DU);
break; break;
case 'q': case 'q':
FREE2D(g, SZ); FREE2D(g, SZ);
@ -369,7 +397,17 @@ int main(int argc, char **argv)
goto retry; 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()); ITER(n_blocks, rand_block());
draw_grid(gamewin); draw_grid(gamewin);
} }
} }
}

View File

@ -33,11 +33,9 @@
/* Define a sequence that should be executed each turn */ /* Define a sequence that should be executed each turn */
#define TURN(x)\ #define TURN(x)\
do {\ gravitate(x) +\
gravitate(x);\ merge(x) +\
merge(x);\ gravitate(x)
gravitate(x);\
} while (0)
/* direction enumeration */ /* direction enumeration */
enum {DR, DU, DL, DD}; enum {DR, DU, DL, DD};
@ -59,9 +57,10 @@ int hs;
char *file; char *file;
/* Merges adjacent squares of the same value together in a certain direction */ /* 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; int i, j;
for (i = 0; i < SZ; i++) { for (i = 0; i < SZ; i++) {
for (j = 0; j < SZ; j++) { for (j = 0; j < SZ; j++) {
@ -70,11 +69,12 @@ void merge(int d)
sl += g[i][j]; sl += g[i][j];
s += g[i][j]; s += g[i][j];
g[i][j++ + 1] = 0; g[i][j++ + 1] = 0;
moved = 1;
} }
} }
} }
} }
else { else if (d == DU) {
int i, j; int i, j;
for (i = 0; i < SZ; i++) { for (i = 0; i < SZ; i++) {
for (j = 0; j < SZ; j++) { for (j = 0; j < SZ; j++) {
@ -83,17 +83,48 @@ void merge(int d)
sl += g[j][i]; sl += g[j][i];
s += g[j][i]; s += g[j][i];
g[j++ + 1][i] = 0; 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 */ /* 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 */ /* 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) { if (d == DL) {
int i, j; int i, j;
for (i = 0; i < SZ; i++) { for (i = 0; i < SZ; i++) {
@ -104,6 +135,7 @@ void gravitate(int d)
if (j + st < SZ) { if (j + st < SZ) {
g[i][j] = g[i][j + st]; g[i][j] = g[i][j + st];
g[i][j + st] = 0; g[i][j + st] = 0;
moved = 1;
} }
} }
} }
@ -118,6 +150,7 @@ void gravitate(int d)
if (j + st < SZ) { if (j + st < SZ) {
g[j][i] = g[j + st][i]; g[j][i] = g[j + st][i];
g[j + st][i] = 0; g[j + st][i] = 0;
moved = 1;
} }
} }
} }
@ -132,6 +165,7 @@ void gravitate(int d)
if (j - st >= 0) { if (j - st >= 0) {
g[i][j] = g[i][j - st]; g[i][j] = g[i][j - st];
g[i][j - st] = 0; g[i][j - st] = 0;
moved = 1;
} }
} }
} }
@ -146,10 +180,12 @@ void gravitate(int d)
if (j - st >= 0) { if (j - st >= 0) {
g[j][i] = g[j - st][i]; g[j][i] = g[j - st][i];
g[j - st][i] = 0; g[j - st][i] = 0;
moved = 1;
} }
} }
} }
} }
return moved;
} }
/* loads hiscore */ /* loads hiscore */
@ -170,13 +206,13 @@ void save_score() {
} }
} }
/* returns if there are any available spaces left on the grid */ /* returns if there are any possible moves */
int space_left() int moves_available()
{ {
int i, j; int i, j;
for (i = 0; i < SZ; i++) for (i = 0; i < SZ; i++)
for (j = 0; j < SZ; j++) 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 1;
return 0; return 0;
} }
@ -185,19 +221,10 @@ int space_left()
/* do this in a smarter fashion */ /* do this in a smarter fashion */
void rand_block() void rand_block()
{ {
if (space_left()) {
int x_p, y_p; int x_p, y_p;
while (g[x_p = rand() % SZ][y_p = rand() % SZ]); while (g[x_p = rand() % SZ][y_p = rand() % SZ]);
g[x_p][y_p] = (rand() & 3) ? 2 : 4; 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);
}
}
/* draws the grid and fills it with the current values */ /* draws the grid and fills it with the current values */
void draw_grid() void draw_grid()
@ -302,11 +329,11 @@ int main(int argc, char **argv)
tattr.c_lflag &= ~(ICANON | ECHO); tattr.c_lflag &= ~(ICANON | ECHO);
tcsetattr(STDOUT_FILENO, TCSANOW, &tattr); tcsetattr(STDOUT_FILENO, TCSANOW, &tattr);
int key; int key, moved;
while (1) { while (1) {
/* will goto this if we didn't get a valid keypress */ /* will goto this if we didn't get a valid keypress */
retry:; retry:;
moved = 0;
key = getchar(); key = getchar();
sl = 0; sl = 0;
@ -314,19 +341,19 @@ int main(int argc, char **argv)
switch (key) { switch (key) {
case 'h': case 'h':
case 'a': case 'a':
TURN(DL); moved = TURN(DL);
break; break;
case 'l': case 'l':
case 'd': case 'd':
TURN(DR); moved = TURN(DR);
break; break;
case 'j': case 'j':
case 's': case 's':
TURN(DD); moved = TURN(DD);
break; break;
case 'k': case 'k':
case 'w': case 'w':
TURN(DU); moved = TURN(DU);
break; break;
case 'q': case 'q':
save_score(); save_score();
@ -335,7 +362,16 @@ int main(int argc, char **argv)
goto retry; 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()); ITER(n_blocks, rand_block());
draw_grid(); draw_grid();
} }
} }
}

10
Makefile Normal file
View File

@ -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