aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md4
-rw-r--r--inc/hanoi.h30
-rw-r--r--inc/tower.h43
-rw-r--r--src/main.c123
-rw-r--r--src/solve.c16
-rw-r--r--src/tower.c2
6 files changed, 118 insertions, 100 deletions
diff --git a/README.md b/README.md
index a9ba8f2..a26236a 100644
--- a/README.md
+++ b/README.md
@@ -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
diff --git a/src/main.c b/src/main.c
index a7ed674..60f2fa8 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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)
{