2 * Name: Towers of Hanoi.
5 * This is a playable copy of towers of hanoi.
6 * Its sole purpose is to demonstrate my Amiga Curses package.
7 * This program should compile on any system that has Curses.
8 * 'hanoi' will give a manual game with 7 playing pieces.
9 * 'hanoi n' will give a manual game with n playing pieces.
10 * 'hanoi n a' will give an auto solved game with n playing pieces.
12 * Author: Simon J Raybould (sie@fulcrum.bt.co.uk).
13 * (This version has been slightly modified by the ncurses maintainers.)
17 * $Id: hanoi.c,v 1.24 2002/06/29 23:32:18 tom Exp $
20 #include <test.priv.h>
22 #define NPEGS 3 /* This is not configurable !! */
25 #define DEFAULTTILES 7
28 #define STATUSLINE (LINES-3)
33 #define LENTOIND(x) (((x)-1)/2)
34 #define OTHER(a,b) (3-((a)+(b)))
37 size_t Length
[MAXTILES
];
41 static struct Peg Pegs
[NPEGS
];
43 {LEFTPEG
, MIDPEG
, RIGHTPEG
};
44 static int TileColour
[] =
46 COLOR_GREEN
, /* Length 3 */
47 COLOR_MAGENTA
, /* Length 5 */
48 COLOR_RED
, /* Length 7 */
49 COLOR_BLUE
, /* Length 9 */
50 COLOR_CYAN
, /* Length 11 */
51 COLOR_YELLOW
, /* Length 13 */
52 COLOR_GREEN
, /* Length 15 */
53 COLOR_MAGENTA
, /* Length 17 */
54 COLOR_RED
, /* Length 19 */
56 static int NMoves
= 0;
58 static void InitTiles(int NTiles
);
59 static void DisplayTiles(void);
60 static void MakeMove(int From
, int To
);
61 static void AutoMove(int From
, int To
, int Num
);
62 static void Usage(void);
63 static int Solved(int NumTiles
);
64 static int GetMove(int *From
, int *To
);
65 static int InvalidMove(int From
, int To
);
68 main(int argc
, char **argv
)
70 int NTiles
, FromCol
, ToCol
;
73 setlocale(LC_ALL
, "");
77 NTiles
= DEFAULTTILES
;
80 NTiles
= atoi(argv
[1]);
81 if (NTiles
> MAXTILES
|| NTiles
< MINTILES
) {
82 fprintf(stderr
, "Range %d to %d\n", MINTILES
, MAXTILES
);
83 ExitProgram(EXIT_FAILURE
);
87 if (strcmp(argv
[2], "a")) {
89 ExitProgram(EXIT_FAILURE
);
91 NTiles
= atoi(argv
[1]);
92 if (NTiles
> MAXTILES
|| NTiles
< MINTILES
) {
93 fprintf(stderr
, "Range %d to %d\n", MINTILES
, MAXTILES
);
94 ExitProgram(EXIT_FAILURE
);
100 ExitProgram(EXIT_FAILURE
);
103 trace(TRACE_MAXIMUM
);
108 int bg
= COLOR_BLACK
;
110 #if HAVE_USE_DEFAULT_COLORS
111 if (use_default_colors() == OK
)
114 for (i
= 0; i
< 9; i
++)
115 init_pair(i
+ 1, bg
, TileColour
[i
]);
120 fprintf(stderr
, "Min screen length 24 lines\n");
121 ExitProgram(EXIT_FAILURE
);
125 leaveok(stdscr
, TRUE
); /* Attempt to remove cursor */
132 AutoMove(0, 2, NTiles
);
133 } while (!Solved(NTiles
));
138 if (GetMove(&FromCol
, &ToCol
))
140 if (InvalidMove(FromCol
, ToCol
)) {
141 mvaddstr(STATUSLINE
, 0, "Invalid Move !!");
146 MakeMove(FromCol
, ToCol
);
147 if (Solved(NTiles
)) {
148 mvprintw(STATUSLINE
, 0,
149 "Well Done !! You did it in %d moves", NMoves
);
157 ExitProgram(EXIT_SUCCESS
);
161 InvalidMove(int From
, int To
)
173 if (!Pegs
[From
].Count
)
175 if (Pegs
[To
].Count
&&
176 Pegs
[From
].Length
[Pegs
[From
].Count
- 1] >
177 Pegs
[To
].Length
[Pegs
[To
].Count
- 1])
183 InitTiles(int NTiles
)
187 for (Size
= NTiles
* 2 + 1, SlotNo
= 0; Size
>= 3; Size
-= 2)
188 Pegs
[0].Length
[SlotNo
++] = Size
;
190 Pegs
[0].Count
= NTiles
;
198 int Line
, peg
, SlotNo
;
199 char TileBuf
[BUFSIZ
];
202 mvaddstr(1, 24, "T O W E R S O F H A N O I");
203 mvaddstr(3, 34, "SJR 1990");
204 mvprintw(19, 5, "Moves : %d", NMoves
);
206 mvaddstr(BASELINE
, 8,
209 for (Line
= TOPLINE
; Line
< BASELINE
; Line
++) {
210 mvaddch(Line
, LEFTPEG
, ' ');
211 mvaddch(Line
, MIDPEG
, ' ');
212 mvaddch(Line
, RIGHTPEG
, ' ');
214 mvaddch(BASELINE
, LEFTPEG
, '1');
215 mvaddch(BASELINE
, MIDPEG
, '2');
216 mvaddch(BASELINE
, RIGHTPEG
, '3');
220 for (peg
= 0; peg
< NPEGS
; peg
++) {
221 for (SlotNo
= 0; SlotNo
< Pegs
[peg
].Count
; SlotNo
++) {
222 memset(TileBuf
, ' ', Pegs
[peg
].Length
[SlotNo
]);
223 TileBuf
[Pegs
[peg
].Length
[SlotNo
]] = '\0';
225 attrset(COLOR_PAIR(LENTOIND(Pegs
[peg
].Length
[SlotNo
])));
228 mvaddstr(BASELINE
- (SlotNo
+ 1),
229 (int) (PegPos
[peg
] - Pegs
[peg
].Length
[SlotNo
] / 2),
238 GetMove(int *From
, int *To
)
240 mvaddstr(STATUSLINE
, 0, "Next move ('q' to quit) from ");
243 if ((*From
= getch()) == 'q')
250 if ((*To
= getch()) == 'q')
263 MakeMove(int From
, int To
)
266 Pegs
[To
].Length
[Pegs
[To
].Count
] = Pegs
[From
].Length
[Pegs
[From
].Count
];
273 AutoMove(int From
, int To
, int Num
)
280 AutoMove(From
, OTHER(From
, To
), Num
- 1);
283 AutoMove(OTHER(From
, To
), To
, Num
- 1);
291 for (i
= 1; i
< NPEGS
; i
++)
292 if (Pegs
[i
].Count
== NumTiles
)
300 fprintf(stderr
, "Usage: hanoi [<No Of Tiles>] [a]\n");
302 "The 'a' option causes the tower to be solved automatically\n");