From feae9f442000cf218c249e6e163e8b5137771857 Mon Sep 17 00:00:00 2001 From: Charles Date: Sun, 28 Jun 2020 08:34:16 +0200 Subject: Added player controls --- src/main.c | 82 +++++++++++++++++++++++++++++++++++++++---------------------- src/tower.c | 47 +++++++++++++++++++++++------------ 2 files changed, 84 insertions(+), 45 deletions(-) (limited to 'src') diff --git a/src/main.c b/src/main.c index 57b8179..a7ed674 100644 --- a/src/main.c +++ b/src/main.c @@ -1,10 +1,22 @@ #include "hanoi.h" -int main() +int main(int argc, char **argv) { + t_tower towers[3]; + size_t disk_num = 3; + if (argc == 2) + if (sscanf(argv[1], "%lu", &disk_num) != 1) + { + fprintf(stderr, "%s: error: `%s` is not a valid number of disk", argv[0], argv[1]); + return (1); + } + towers_init(towers, disk_num); + initscr(); noecho(); cbreak(); + keypad(stdscr, TRUE); + curs_set(0); int width, height; getmaxyx(stdscr, height, width); @@ -13,64 +25,76 @@ int main() int win_width = width / 3; WINDOW *wins[3]; + refresh(); for (int i = 0; i < 3; i++) { - refresh(); if ((wins[i] = newwin(0, win_width, 0, i * win_width)) == NULL) abort(); - box(wins[i], 0, 0); - /* wrefresh(wins[i]); */ } - t_tower towers[3]; - towers_init(towers, 3); - + enum e_mode mode = MODE_SELECT_FROM; int from_selection = 0; - int to_selection = 1; - bool mode_from = true; + int current = 0; bool running = true; while (running) { for (int i = 0; i < 3; i++) { - int highlight_level = 0; - if (i == from_selection) - highlight_level = 1; - tower_put(&towers[i], wins[i], highlight_level); + enum e_highlight highlight = HIGHLIGHT_NONE; + if (mode == MODE_SELECT_TO && i == from_selection) + highlight |= HIGHLIGHT_FROM; + if (i == current) + highlight |= HIGHLIGHT_CURRENT; + tower_put(&towers[i], wins[i], highlight); } - char c; + int c; c = getch(); - int selection = mode_from ? from_selection : to_selection; switch (c) { case 'q': running = false; break; case 'j': - selection--; + case KEY_LEFT: + current--; break; case 'k': - selection++; + case KEY_RIGHT: + current++; break; case '\n': - if (mode_from) - from_selection = selection; - else - to_selection = selection; - if (!mode_from) - towers_move(towers, from_selection, to_selection); - mode_from = !mode_from; + if (mode == MODE_SELECT_FROM) + { + if (towers[current].len == 0) + mvprintw(0, 0, "Tower %d is empty"); + else + { + from_selection = current; + mode = MODE_SELECT_TO; + } + } + else if (mode == MODE_SELECT_TO) + { + if (!towers[current].len == 0 && + tower_peek(&towers[current]) < tower_peek(&towers[from_selection])) + { + mvprintw(0, 0, "Top disk of %d is smaller than top disk of %d", + current, from_selection); + } + else + towers_move(towers, from_selection, current); + mode = MODE_SELECT_FROM; + } break; } - selection %= 3; - mvprintw(0, 0, "%d", selection); - refresh(); + if (current < 0) + current = 2; + else if (current > 2) + current = 0; } - /* refresh(); */ - for (int i = 0; i < 3; i++) delwin(wins[3]); endwin(); diff --git a/src/tower.c b/src/tower.c index a92a201..b31eaf7 100644 --- a/src/tower.c +++ b/src/tower.c @@ -1,23 +1,28 @@ #include "tower.h" -static uint8_t st_tower_pop(t_tower tower) +static uint8_t st_tower_pop(t_tower *tower) { - if (tower.len == 0) + if (tower->len == 0) abort(); - uint8_t top = tower.data[tower.len - 1]; - tower.len--; + uint8_t top = tower->data[tower->len - 1]; + tower->len--; return top; } -static void st_tower_push(t_tower tower, uint8_t top) +static void st_tower_push(t_tower *tower, uint8_t top) { - if (tower.len == MAX_HEIGHT) + if (tower->len == MAX_HEIGHT) abort(); - tower.data[tower.len] = top; - tower.len++; + tower->data[tower->len] = top; + tower->len++; } -void towers_init(t_tower towers[3], size_t disk_num) +uint8_t tower_peek(t_tower *tower) +{ + return (tower->data[tower->len - 1]); +} + +void towers_init(t_tower towers[3], size_t disk_num) { memset(towers[0].data, 0, sizeof(t_tower)); memset(towers[1].data, 0, sizeof(t_tower)); @@ -29,28 +34,38 @@ void towers_init(t_tower towers[3], size_t disk_num) towers[2].len = 0; } -void towers_move(t_tower towers[3], size_t from, size_t to) +void towers_move(t_tower towers[3], size_t from, size_t to) { if (from > 2 || to > 2) abort(); - st_tower_push(towers[to], st_tower_pop(towers[from])); + st_tower_push(&towers[to], st_tower_pop(&towers[from])); } -void tower_put(t_tower *tower, WINDOW *win, int highlight_level) +void tower_put(t_tower *tower, WINDOW *win, enum e_highlight highlight_level) { int height, width; getmaxyx(win, height, width); - if (highlight_level == 1) - wattron(win, A_BOLD); + wclear(win); + if (highlight_level & HIGHLIGHT_FROM) + mvwaddstr(win, 1, 1, "SELECTED"); + if (highlight_level & HIGHLIGHT_CURRENT) + wattron(win, A_REVERSE); mvwvline(win, 1, width / 2, '|', height - 2); for (size_t i = 0; i < tower->len; i++) { int disk_width = tower->data[i] * 2 + 1; + if (disk_width > width - 2) + { + disk_width = width - 5; + wattron(win, A_BOLD); + mvwprintw(win, height - i - 2, 0, "%2d", tower->data[i]); + wattroff(win, A_BOLD); + } mvwhline(win, height - i - 2, width / 2 - disk_width / 2, '#', disk_width); } - if (highlight_level == 1) - wattroff(win, A_BOLD); + if (highlight_level & HIGHLIGHT_CURRENT) + wattroff(win, A_REVERSE); wrefresh(win); } -- cgit