diff options
Diffstat (limited to '2048_clean.c')
| -rw-r--r-- | 2048_clean.c | 111 |
1 files changed, 70 insertions, 41 deletions
diff --git a/2048_clean.c b/2048_clean.c index ac58325..79a474b 100644 --- a/2048_clean.c +++ b/2048_clean.c @@ -1,24 +1,69 @@ -#include <ncurses.h> #include <stdio.h> #include <stdlib.h> +#include <termios.h> #include <time.h> #include <unistd.h> -#define waddstr_(text) waddstr(main_window, text) -#define waddch_(ch) waddch(main_window, ch) -#define wprintw_(format, data) wprintw(main_window, format, data) -#define newline waddch_('\n') +#define waddstr_(text) printf("%s", text) +#define waddch_(ch) putchar(ch) +#define wprintw_(format, data) printf(format, data) +#define newline printf("\r\n") #define repeat(i, n) for (int i = 0; i < n; ++i) #define get_tile_at(k) (grid + y * ((x + size) % (size + 1) + k * x) + (size + 1 - y) * i) -WINDOW *main_window; -char *message = "\0"; -int size, num_rows, num_columns, new_tile_pos, num_empty_slots, changed, last_empty_tile_index, *last_non_empty_tile, - *this_tile, grid_buf[128], *grid = grid_buf; +#define CLEAR_SCREEN "\033[2J\033[H" +#define HIDE_CURSOR "\033[?25l" +#define SHOW_CURSOR "\033[?25h" -void draw_frame_1() { +int size, new_tile_pos, num_empty_slots, changed, last_empty_tile_index, *last_non_empty_tile, *this_tile, + grid_buf[128], *grid = grid_buf, did_restore_from_alt_buffer, did_disable_raw_mode; + +void restore_from_alt_buffer(void) { + if (did_restore_from_alt_buffer++) + return; + printf("\033[?1049l"); +} + +void switch_to_alt_buffer(void) { + atexit(restore_from_alt_buffer); + printf("\033[?1049h"); +} + +struct termios original_termios; + +void disable_raw_mode(void) { + if (did_disable_raw_mode++) + return; + tcsetattr(STDIN_FILENO, TCSAFLUSH, &original_termios); + printf(SHOW_CURSOR); +} + +void enable_raw_mode(void) { + tcgetattr(STDIN_FILENO, &original_termios); + atexit(disable_raw_mode); + + struct termios raw = original_termios; + raw.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON); + raw.c_oflag &= ~(OPOST); + raw.c_cflag |= (CS8); + raw.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG); + raw.c_cc[VMIN] = 0; + raw.c_cc[VTIME] = 1; + + tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw); + printf(HIDE_CURSOR); +} + +char get_key(void) { + char c; + while (read(STDIN_FILENO, &c, 1) != 1) + ; + return c; +} + +void draw_frame_1(void) { waddch_('+'); repeat(i, 8 * size - 1) { waddch_('-'); @@ -27,19 +72,18 @@ void draw_frame_1() { newline; } -void draw_frame_2() { +void draw_frame_2(void) { waddch_('|'); repeat(i, size) { - repeat(j, 8) { + repeat(j, 7) { waddch_(32); } - waddch_('\b'); waddch_('|'); } newline; } -void show_grid() { +void show_grid(void) { draw_frame_1(); repeat(i, size) { draw_frame_2(); @@ -62,10 +106,9 @@ void show_grid() { if (i < size - 1) { waddch_('|'); repeat(j, size) { - repeat(j, 8) { + repeat(j, 7) { waddch_('-'); } - waddch_('\b'); if (j < size - 1) { waddch_('+'); } @@ -113,7 +156,7 @@ int move_grid(int x, int y, int do_change) { return !changed; } -void put_new_tile() { +void put_new_tile(void) { num_empty_slots = 0; repeat(i, size * size) { if (!grid[i]) { @@ -134,34 +177,25 @@ void put_new_tile() { int main(int argc, char **argv) { srand(time(0)); - initscr(); - cbreak(); - noecho(); - curs_set(0); - getmaxyx(stdscr, num_rows, num_columns); + switch_to_alt_buffer(); + enable_raw_mode(); size = argc > 1 ? (*argv[1] - '0') : 4; if (size <= 1 || size > 8) { - message = "\1Invalid size given.\n"; - goto quit; - } - - main_window = newwin(0, 0, (num_rows - 4 * size) / 2, (num_columns - 8 * size) / 2); - if (!main_window) { - message = "\1Terminal too small.\n"; - goto quit; + fputs("invalid board size\n", stderr); + return 1; } put_new_tile(); put_new_tile(); while (1) { - wclear(main_window); + printf(CLEAR_SCREEN); show_grid(); waddstr_(" h,j,k,l: move q: quit"); - wrefresh(main_window); + fflush(stdout); - switch (wgetch(main_window)) { + switch (get_key()) { case 'q': goto quit; @@ -183,7 +217,6 @@ int main(int argc, char **argv) { put_new_tile(); } if (move_grid(1, 1, 0) & move_grid(-1, 1, 0) & move_grid(1, size, 0) & move_grid(-1, size, 0)) { - message = "\0Game over.\n"; goto quit; } usleep(2048 * 8); @@ -192,11 +225,7 @@ int main(int argc, char **argv) { } quit: - if (main_window) { - delwin(main_window); - } - endwin(); - - fputs(message + 1, stderr); - return *message; + disable_raw_mode(); + restore_from_alt_buffer(); + printf(CLEAR_SCREEN); } |
