Consolidate printing styles, make more generic. Add goal option to create a custom target

This commit is contained in:
Tiehuis 2014-12-06 13:43:00 +13:00
parent 3ca10eb8d5
commit 32a4b483ee
3 changed files with 32 additions and 21 deletions

View File

@ -131,20 +131,26 @@ void merge(struct gamestate *g, direction d, void (*callback)(struct gamestate *
#undef merge_if_equal #undef merge_if_equal
} }
int moves_available(struct gamestate *g) /* Return -1 on lose condition, 1 on win condition, 0 on
* haven't ended */
int end_condition(struct gamestate *g)
{ {
int ret = -1;
int x, y; int x, y;
for (x = 0; x < g->opts->grid_width; ++x) { for (x = 0; x < g->opts->grid_width; ++x) {
for (y = 0; y < g->opts->grid_height; ++y) { for (y = 0; y < g->opts->grid_height; ++y) {
if (g->grid[x][y] >= g->opts->goal)
return 1;
if (!g->grid[x][y] || ((x + 1 < g->opts->grid_width) && if (!g->grid[x][y] || ((x + 1 < g->opts->grid_width) &&
(g->grid[x][y] == g->grid[x+1][y])) (g->grid[x][y] == g->grid[x+1][y]))
|| ((y + 1 < g->opts->grid_height) && || ((y + 1 < g->opts->grid_height) &&
(g->grid[x][y] == g->grid[x][y+1]))) (g->grid[x][y] == g->grid[x][y+1])))
return 1; ret = 0;
} }
} }
return 0; return ret;
} }
void random_block(struct gamestate *g) void random_block(struct gamestate *g)
@ -262,7 +268,7 @@ void reset_highscore(void)
void print_usage(void) void print_usage(void)
{ {
printf( printf(
"usage: 2048 [-cCrh] [-b <rate>] [-s <size>]\n" "usage: 2048 [-cCaArh] [-g <goal>] [-b <rate>] [-s <size>]\n"
"\n" "\n"
"controls\n" "controls\n"
" hjkl movement keys\n" " hjkl movement keys\n"
@ -271,6 +277,7 @@ void print_usage(void)
"options\n" "options\n"
" -s <size> set the grid side lengths\n" " -s <size> set the grid side lengths\n"
" -b <rate> set the block spawn rate\n" " -b <rate> set the block spawn rate\n"
" -g <goal> set a new goal (default 2048)\n"
" -a enable animations (default)\n" " -a enable animations (default)\n"
" -A disable animations\n" " -A disable animations\n"
" -c enable color support\n" " -c enable color support\n"
@ -283,7 +290,7 @@ void print_usage(void)
struct gameoptions* parse_options(struct gameoptions *opt, int argc, char **argv) struct gameoptions* parse_options(struct gameoptions *opt, int argc, char **argv)
{ {
int c; int c;
while ((c = getopt(argc, argv, "aArcChs:b:")) != -1) { while ((c = getopt(argc, argv, "aArcChg:s:b:")) != -1) {
switch (c) { switch (c) {
case 'a': case 'a':
opt->animate = 1; opt->animate = 1;
@ -297,6 +304,9 @@ struct gameoptions* parse_options(struct gameoptions *opt, int argc, char **argv
case 'C': case 'C':
opt->enable_color = 0; opt->enable_color = 0;
break; break;
case 'g':
opt->goal = strtol(optarg, NULL, 10);
break;
case 's':; case 's':;
/* Stick with square for now */ /* Stick with square for now */
int optint = strtol(optarg, NULL, 10); int optint = strtol(optarg, NULL, 10);

View File

@ -37,7 +37,7 @@ struct gamestate {
struct gameoptions* parse_options(struct gameoptions*, int, char**); struct gameoptions* parse_options(struct gameoptions*, int, char**);
void gravitate(struct gamestate*, direction, void (*callback)(struct gamestate*)); void gravitate(struct gamestate*, direction, void (*callback)(struct gamestate*));
void merge(struct gamestate*, direction, void (*callback)(struct gamestate*)); void merge(struct gamestate*, direction, void (*callback)(struct gamestate*));
int moves_available(struct gamestate *); int end_condition(struct gamestate *);
void random_block(struct gamestate *); void random_block(struct gamestate *);
int gamestate_tick(struct gamestate*, direction, void (*callback)(struct gamestate*)); int gamestate_tick(struct gamestate*, direction, void (*callback)(struct gamestate*));
void gamestate_clear(struct gamestate*);; void gamestate_clear(struct gamestate*);;

View File

@ -99,15 +99,13 @@ void draw_screen(struct gamestate *g)
#ifdef VT100_COMPATIBLE #ifdef VT100_COMPATIBLE
printf("\033[2J\033[H"); printf("\033[2J\033[H");
#endif #endif
char *scr = g->score_last ? "SCORE: %d (+%d)\n" : "SCORE: %d\n";
printf("HISCORE: %ld |", g->score_high); printf(scr, g->score, g->score_last);
printf("| SCORE: %ld ", g->score); printf("HISCR: %ld\n", g->score_high);
if (g->score_last) printf("(+%ld)", g->score_last);
printf("\n");
// alter this grid_size + 1 to match abitrary grid size // alter this grid_size + 1 to match abitrary grid size
iterate(g->opts->grid_width, printf("------")); iterate((g->print_width + 2) * g->opts->grid_width + 1, printf("-"));
printf("-\n"); printf("\n");
int x, y; int x, y;
for (y = 0; y < g->opts->grid_height; y++) { for (y = 0; y < g->opts->grid_height; y++) {
printf("|"); printf("|");
@ -115,12 +113,13 @@ void draw_screen(struct gamestate *g)
if (g->grid[x][y]) if (g->grid[x][y])
printf("%*ld |", g->print_width, g->grid[x][y]); printf("%*ld |", g->print_width, g->grid[x][y]);
else else
printf(" |"); printf("%*s |", g->print_width, "");
} }
printf("\n"); printf("\n");
} }
iterate(g->opts->grid_width, printf("------"));
printf("-\n\n"); iterate((g->print_width + 2) * g->opts->grid_width + 1, printf("-"));
printf("\n\n");
} }
#endif /* CURSES */ #endif /* CURSES */
@ -141,6 +140,13 @@ int main(int argc, char **argv)
while (1) { while (1) {
draw_screen(g); draw_screen(g);
int e;
if ((e = end_condition(g))) {
drawstate_clear();
printf(e > 0 ? "You win\n" : "You lose\n");
goto endloop;
}
/* abstract getting keypress */ /* abstract getting keypress */
int ch; int ch;
do { do {
@ -148,11 +154,6 @@ int main(int argc, char **argv)
if (ch == 'q') { goto endloop; } if (ch == 'q') { goto endloop; }
} while (strchr("hjkl", ch) == NULL); } while (strchr("hjkl", ch) == NULL);
if (!moves_available(g)) {
printf("You lose\n");
break;
}
gamestate_tick(g, ch, g->opts->animate ? ddraw : NULL); gamestate_tick(g, ch, g->opts->animate ? ddraw : NULL);
} }
endloop: endloop: