diff options
| author | Charles <sircharlesaze@gmail.com> | 2020-06-28 09:40:47 +0200 |
|---|---|---|
| committer | Charles <sircharlesaze@gmail.com> | 2020-06-28 09:40:47 +0200 |
| commit | 15e690e0dc9f539ca0e8e9c98c3fdc9105ec9d74 (patch) | |
| tree | d60e39bdac9d2447b89e56dac88b8877b5005378 | |
| parent | feae9f442000cf218c249e6e163e8b5137771857 (diff) | |
| download | hanoi-15e690e0dc9f539ca0e8e9c98c3fdc9105ec9d74.tar.gz hanoi-15e690e0dc9f539ca0e8e9c98c3fdc9105ec9d74.tar.bz2 hanoi-15e690e0dc9f539ca0e8e9c98c3fdc9105ec9d74.zip | |
| -rw-r--r-- | README.md | 4 | ||||
| -rw-r--r-- | inc/hanoi.h | 30 | ||||
| -rw-r--r-- | inc/tower.h | 43 | ||||
| -rw-r--r-- | src/main.c | 123 | ||||
| -rw-r--r-- | src/solve.c | 16 | ||||
| -rw-r--r-- | src/tower.c | 2 |
6 files changed, 118 insertions, 100 deletions
@@ -6,9 +6,11 @@ Tower of hanoi puzzle with ncurses. ``` make -./hanoi [number of disks] +./hanoi [number of disks] [-s] ``` +Use `-s` to solve the puzzle. + ### Controls Cycle through the 3 pegs with `j`/`k` or left/right arrow. diff --git a/inc/hanoi.h b/inc/hanoi.h index 1953499..3091658 100644 --- a/inc/hanoi.h +++ b/inc/hanoi.h @@ -1,9 +1,15 @@ #ifndef HANOI_H # define HANOI_H +# include <unistd.h> +# include <stdlib.h> +# include <stdint.h> +# include <stddef.h> +# include <string.h> + # include <ncurses.h> -# include "tower.h" +# define MAX_HEIGHT 128 enum e_mode { @@ -11,4 +17,26 @@ enum e_mode MODE_SELECT_TO, }; + +typedef struct +{ + uint8_t data[MAX_HEIGHT]; + size_t len; +} t_tower; + +enum e_highlight +{ + HIGHLIGHT_NONE = 0, + HIGHLIGHT_FROM = 1 << 0, + HIGHLIGHT_CURRENT = 1 << 1, +}; + +void towers_init(t_tower towers[3], size_t disk_num); +void towers_move(t_tower towers[3], size_t from, size_t to); +void tower_put(t_tower *tower, WINDOW *win, enum e_highlight highlight_level); +uint8_t tower_peek(t_tower *tower); + +void solve(t_tower towers[3], WINDOW *wins[3], + int n, int from, int via, int to); + #endif diff --git a/inc/tower.h b/inc/tower.h deleted file mode 100644 index da3fb1e..0000000 --- a/inc/tower.h +++ /dev/null @@ -1,43 +0,0 @@ -/* ************************************************************************** */ -/* */ -/* . */ -/* tower.h / \ */ -/* / \ */ -/* By: charles <charles.cabergs@gmail.com> /o o \ */ -/* / v \ */ -/* Created: 2020/06/27 14:06:50 by charles / _ \ */ -/* Updated: 2020/06/28 08:12:37 by charles '-----------' */ -/* */ -/* ************************************************************************** */ - -#ifndef TOWER_H -# define TOWER_H - -# include <stdlib.h> -# include <stdint.h> -# include <stddef.h> -# include <string.h> - -# include <ncurses.h> - -# define MAX_HEIGHT 128 - -typedef struct -{ - uint8_t data[MAX_HEIGHT]; - size_t len; -} t_tower; - -enum e_highlight -{ - HIGHLIGHT_NONE = 0, - HIGHLIGHT_FROM = 1 << 0, - HIGHLIGHT_CURRENT = 1 << 1, -}; - -void towers_init(t_tower towers[3], size_t disk_num); -void towers_move(t_tower towers[3], size_t from, size_t to); -void tower_put(t_tower *tower, WINDOW *win, enum e_highlight highlight_level); -uint8_t tower_peek(t_tower *tower); - -#endif @@ -2,15 +2,18 @@ int main(int argc, char **argv) { + bool solve_arg = false; t_tower towers[3]; size_t disk_num = 3; - if (argc == 2) - if (sscanf(argv[1], "%lu", &disk_num) != 1) + if (argc >= 2) + if (sscanf(argv[1], "%lu", &disk_num) != 1 || disk_num > MAX_HEIGHT - 1) { fprintf(stderr, "%s: error: `%s` is not a valid number of disk", argv[0], argv[1]); return (1); } towers_init(towers, disk_num); + if (argc == 3 && strcmp(argv[2], "-s") == 0) + solve_arg = true; initscr(); noecho(); @@ -32,69 +35,81 @@ int main(int argc, char **argv) abort(); } - enum e_mode mode = MODE_SELECT_FROM; - int from_selection = 0; - int current = 0; - bool running = true; - while (running) + + if (!solve_arg) { - for (int i = 0; i < 3; i++) + enum e_mode mode = MODE_SELECT_FROM; + int from_selection = 0; + int current = 0; + bool running = true; + while (running) { - 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); - } - - int c; - c = getch(); + for (int i = 0; i < 3; i++) + { + 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); + } - switch (c) - { - case 'q': - running = false; - break; - case 'j': - case KEY_LEFT: - current--; + if (towers[0].len == 0 && + towers[1].len == 0) break; - case 'k': - case KEY_RIGHT: - current++; - break; - case '\n': - if (mode == MODE_SELECT_FROM) - { - if (towers[current].len == 0) - mvprintw(0, 0, "Tower %d is empty"); - else + + int c; + c = getch(); + + switch (c) + { + case 'q': + running = false; + break; + case 'j': + case KEY_LEFT: + current--; + break; + case 'k': + case KEY_RIGHT: + current++; + break; + case '\n': + if (mode == MODE_SELECT_FROM) { - from_selection = current; - mode = MODE_SELECT_TO; + 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])) + else if (mode == MODE_SELECT_TO) { - mvprintw(0, 0, "Top disk of %d is smaller than top disk of %d", - current, from_selection); + 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; } - else - towers_move(towers, from_selection, current); - mode = MODE_SELECT_FROM; - } - break; + break; + } + if (current < 0) + current = 2; + else if (current > 2) + current = 0; } - if (current < 0) - current = 2; - else if (current > 2) - current = 0; } + else + solve(towers, wins, disk_num, 0, 1, 2); + mvaddstr(0, 0, "FINISHED: press any key to quit"); + getch(); for (int i = 0; i < 3; i++) delwin(wins[3]); endwin(); diff --git a/src/solve.c b/src/solve.c new file mode 100644 index 0000000..d020dfd --- /dev/null +++ b/src/solve.c @@ -0,0 +1,16 @@ +#include "hanoi.h" + +void solve(t_tower towers[3], WINDOW *wins[3], + int n, int from, int via, int to) +{ + if (n == 0) + return; + solve(towers, wins, n - 1, from, to, via); + towers_move(towers, from, to); + + for (int i = 0; i < 3; i++) + tower_put(&towers[i], wins[i], HIGHLIGHT_NONE); + usleep(1000); + + solve(towers, wins, n - 1, via, from, to); +} diff --git a/src/tower.c b/src/tower.c index b31eaf7..914c0fb 100644 --- a/src/tower.c +++ b/src/tower.c @@ -1,4 +1,4 @@ -#include "tower.h" +#include "hanoi.h" static uint8_t st_tower_pop(t_tower *tower) { |
