漢諾塔(又稱河內塔)是一款源於印度一個古老傳說的益智類遊戲。傳說上帝創造世界的時候做了三根金剛石柱子,在一根柱子上從下往上按大小順序摞著7片黃金圓盤。上帝命令婆羅門把圓盤從下面開始按大小順序重新擺放在另一根柱子上。並且規定,在小圓盤上不能放大圓盤,在三根柱子之間一次只能移動一個圓盤。
遊戲裡有三根金剛石柱子,在一根柱子上從下往上按大小順序摞著7片黃金圓盤。玩家需要做的是把圓盤從下面開始按大小順序重新擺放在另一根柱子上。並且規定,在小圓盤上不能放大圓盤,在三根柱子之間一次只能移動一個圓盤。
#include <graphics.h>#include <conio.h>#include <stdio.h>#define MAX 64 #define NULL 0
struct STKNODE{ int a[4];};
struct STK{ STKNODE* stack[MAX]; int top;};
STK s[3]; int v = 5;
void Initstk(STK* s); void Hannoi(int n, char a, char b, char c); void start(); void Move(int n, char a, char b); int switchab(char a); void adjust();
int main(){ int n, ta[4] = { 115, 500, 285, 518 }; printf("儘量小於16\n"); printf("請輸入漢諾塔的層數(1~64):"); scanf_s("%d", &n); STKNODE** p; p = (STKNODE**)malloc(n * sizeof(STKNODE**)); for (int i2 = 0; i2 < n; i2++) { p[i2] = (STKNODE*)malloc(sizeof(STKNODE)); } Initstk(&s[0]); Initstk(&s[1]); Initstk(&s[2]); start(); setfillcolor(GREEN); for (int i = 0; i < n; i++) { ta[0] += 5; ta[1] -= 20; ta[2] -= 5; ta[3] -= 20; solidrectangle(ta[0], ta[1], ta[2], ta[3]); ++s[0].top; for (int i1 = 0; i1 < 4; i1++) { p[i]->a[i1] = ta[i1]; s[0].stack[s[0].top] = p[i]; } } Hannoi(n, 'a', 'b', 'c'); system("pause"); printf("\t\t\t\tGame Over!\n");}
void Hannoi(int n, char a, char b, char c){ if (n == 1) Move(1, a, c); else { Hannoi(n - 1, a, c, b); Move(n, a, c); Hannoi(n - 1, b, a, c); }}
void Initstk(STK* s){ int i; s->top = 0; for (i = 0; i <= MAX; i++) s->stack[++s->top] = NULL; s->top = 0;}
void Move(int n, char a, char b){ int i3, i4 = 0, i5 = 0; i3 = b - a; i4 = switchab(a); i5 = switchab(b); STKNODE* q1, * q0; q1 = (STKNODE*)malloc(sizeof(STKNODE)); q0 = (STKNODE*)malloc(sizeof(STKNODE));
q0 = s[i4].stack[s[i4].top]; ++s[i5].top; q1->a[0] = q0->a[0] + i3 * 200; q1->a[1] = 500 - s[i5].top * 20; q1->a[2] = q0->a[2] + i3 * 200; q1->a[3] = 500 - s[i5].top * 20 + 18; s[i5].stack[s[i5].top] = q1; --s[i4].top;
while (q0->a[1] >= 100) { setfillcolor(GREEN); solidrectangle(q0->a[0], q0->a[1], q0->a[2], q0->a[3]); adjust(); Sleep(10 * v); setfillcolor(WHITE); solidrectangle(q0->a[0], q0->a[1], q0->a[2], q0->a[3]); setlinecolor(RED); line((q0->a[0] + q0->a[2]) / 2, q0->a[1], (q0->a[0] + q0->a[2]) / 2, q0->a[3]); q0->a[1] -= 10; q0->a[3] -= 10; }
while (q0->a[2] != q1->a[2]) { setfillcolor(GREEN); solidrectangle(q0->a[0], q0->a[1], q0->a[2], q0->a[3]); adjust(); Sleep(10 * v); setfillcolor(WHITE); solidrectangle(q0->a[0], q0->a[1], q0->a[2], q0->a[3]); if (i3 < 0) { q0->a[0] -= 20; q0->a[2] -= 20; } else { q0->a[0] += 20; q0->a[2] += 20; } }
while (q0->a[3] <= q1->a[3]) { setfillcolor(GREEN); solidrectangle(q0->a[0], q0->a[1], q0->a[2], q0->a[3]); adjust(); Sleep(10 * v); setfillcolor(WHITE); solidrectangle(q0->a[0], q0->a[1], q0->a[2], q0->a[3]); setlinecolor(RED); if (q0->a[1] > 100) { line((q0->a[0] + q0->a[2]) / 2, q0->a[1], (q0->a[0] + q0->a[2]) / 2, q0->a[3]); } q0->a[1] += 10; q0->a[3] += 10; }
setfillcolor(GREEN); solidrectangle(q1->a[0], q1->a[1], q1->a[2], q1->a[3]);}
void start(){
initgraph(800, 650);
setbkcolor(WHITE);
cleardevice();
float H, S, L; H = 0; S = 1; L = 0.5f; setlinestyle(PS_SOLID, 2); for (int r = 600; r > 544; r--) { H += 5; setlinecolor(HSLtoRGB(H, S, L)); circle(750, 900, r); }
settextstyle(50, 0, "華文楷體"); settextcolor(RED); outtextxy(200, 150, "漢諾塔移動動畫"); settextstyle(20, 0, "黑體"); outtextxy(600, 200, "BY:enter"); outtextxy(500, 200, "版本V1.1"); settextstyle(50, 0, "黑體"); settextcolor(GREEN); outtextxy(200, 350, "隨便按一個鍵開始吧!");
_getch();
cleardevice();
setlinecolor(RED);
line(400, 110, 400, 500); line(600, 110, 600, 500); line(200, 110, 200, 500);
setfillcolor(LIGHTGRAY); fillrectangle(80, 501, 720, 510);
solidrectangle(360, 540, 440, 580); settextstyle(30, 0, "黑體"); settextcolor(GREEN); outtextxy(370, 550, "暫停"); settextstyle(20, 0, "宋體"); settextcolor(RED); outtextxy(300, 580, "滑鼠暫停後請按空格繼續");
solidrectangle(160, 540, 240, 580); settextstyle(30, 0, "黑體"); settextcolor(GREEN); outtextxy(170, 550, "加速"); settextstyle(20, 0, "宋體"); settextcolor(RED); outtextxy(170, 580, "請按 d");
solidrectangle(560, 540, 640, 580); settextstyle(30, 0, "黑體"); settextcolor(GREEN); outtextxy(570, 550, "減速"); settextstyle(20, 0, "宋體"); settextcolor(RED); outtextxy(570, 580, "請按 a");
settextstyle(50, 0, "宋體"); settextcolor(GREEN); outtextxy(10, 10, "正在進行中請欣賞:");}
int switchab(char a){ switch (a) { case 'a': return 0; case 'b': return 1; case 'c': return 2; default: return 0; }}
void adjust(){ char f;
if (_kbhit()) f = _getch();
if (MouseHit() == true) {
MOUSEMSG Mouse; Mouse = GetMouseMsg();
if (Mouse.x >= 360 && Mouse.x <= 440 && Mouse.y >= 540 && Mouse.y <= 580 && Mouse.mkLButton) { f = ' '; } if (Mouse.x >= 160 && Mouse.x <= 240 && Mouse.y >= 540 && Mouse.y <= 580 && Mouse.mkLButton) { f = 'd'; } if (Mouse.x >= 560 && Mouse.x <= 640 && Mouse.y >= 540 && Mouse.y <= 580 && Mouse.mkLButton) { f = 'a'; } }
switch (f) {
case ' ':
settextstyle(30, 0, "黑體"); settextcolor(GREEN); outtextxy(370, 550, "繼續"); _getch();
settextstyle(30, 0, "黑體"); settextcolor(GREEN); outtextxy(370, 550, "暫停"); break;
case 'a':
setfillcolor(LIGHTGRAY); solidrectangle(560, 540, 640, 580); settextstyle(30, 0, "黑體"); settextcolor(GREEN); outtextxy(575, 545, "減速"); Sleep(30);
v++;
setfillcolor(LIGHTGRAY); solidrectangle(560, 540, 640, 580); settextstyle(30, 0, "黑體"); settextcolor(GREEN); outtextxy(570, 550, "減速"); break;
case 'd': setfillcolor(LIGHTGRAY); solidrectangle(160, 540, 240, 580); settextstyle(30, 0, "黑體"); settextcolor(GREEN); outtextxy(165, 545, "加速"); Sleep(30); setfillcolor(LIGHTGRAY); solidrectangle(160, 540, 240, 580); settextstyle(30, 0, "黑體"); settextcolor(GREEN); outtextxy(170, 550, "加速");
v--;
if (v <= 0) { v = 1; } break;
default: break; }
f = 'r'; FlushMouseMsgBuffer(); }