汉诺塔是这样一种小游戏:
有三根柱子。一开始,若干张圆盘按照上小下大的顺序串在第一根柱子上。而游戏的目标为将所有圆盘全部移动到第三根柱子上去,并且仍要保持上小下大的顺序。而且要求:
①每次只能移动一张圆盘。
②较大的圆盘不可以放在较小的圆盘上面。
比如说,在这一步我想把第一根柱子上的圆盘移动到第二根柱子上去,行不行呢?不行。
因为这样一移动,大圆盘就在小圆盘上面了。
所以,我们只能把它移动到第三根空的柱子上去。
源代码:
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#define MAX_PLATES 15
#define SPACE 32
#define EMPTY 51316
#define CUR 32118
int nTimesTwo(int n){int product = 1;for(int i = 0; i < n; i++) product*=2;return product;
}
void cls(){system("cls");
}
void pause(){system("pause");
}
void tab(int times){for(int i=0; i<times; i++) printf("\t");
}
void line(int times){for(int i=0; i<times; i++) printf("\n");
}
void space(int times){for(int i=0; i<times; i++) printf(" ");
}
void printPlate(int size){switch(size){case 0:space(MAX_PLATES);printf("|\t");break;case EMPTY:space(MAX_PLATES);printf(" \t");break;case CUR:space(MAX_PLATES);printf("v\t");break;default:for(int i = 0; i < MAX_PLATES-size; i++){printf(" ");}for(int i = 0; i < size * 2 + 1; i++){printf("█");}if(size<8)tab(1);break;}
}
int menu(){int num = 0;int cur = 6;int key;while(num==0){cls();printf("********************汉诺塔小游戏********************\n");printf("请选择盘子的数量:\n");for(int i = 1; i <= MAX_PLATES; i++){if(cur == i){printf("[%d] ",i);}else{printf(" %d ",i);}}line(1);key = getch();switch(key){case 'L': case 'l':return 0;break;case 'A': case 'a':if(cur == 1) cur=15;else cur--;break;case 'D': case 'd':if(cur == 15) cur=1;else cur++;break;case SPACE:num = cur;break;default:break;}}return num;
}int game(int plateNum){int pillar[3][MAX_PLATES+8] = {};int isPicked = 0;int cur = 0;int key;int steps=0;int notSuccess;for(int i = 0; i < plateNum; i++){pillar[0][i] = plateNum - i;}for(int i = 0; i < 3; i++){for(int j = MAX_PLATES+8-1;j>=MAX_PLATES+8-3; j--){pillar[i][j] = EMPTY;}} while(1){cls();notSuccess = 0;if(!isPicked){pillar[cur][MAX_PLATES+8-2]=CUR;}for(int i = MAX_PLATES+8-1; i >= 0; i--){for(int j = 0; j < 3; j++){tab(1);printPlate(pillar[j][i]);}line(1);}for(int i = 0; i < 2; i++){for(int j = 0; j < MAX_PLATES + 5; j++){if(pillar[i][j] != 0){notSuccess = 1;}}}if(isPicked){notSuccess = 1;}if(!notSuccess){return steps;}key = getch();switch(key){case 'A': case 'a':if(cur == 0){pillar[2][MAX_PLATES+8-2] = pillar[0][MAX_PLATES+8-2];pillar[0][MAX_PLATES+8-2] = EMPTY;cur=2;}else{pillar[cur-1][MAX_PLATES+8-2] = pillar[cur][MAX_PLATES+8-2];pillar[cur][MAX_PLATES+8-2] = EMPTY;cur--;}break;case 'D': case 'd':if(cur == 2){pillar[0][MAX_PLATES+8-2] = pillar[2][MAX_PLATES+8-2];pillar[2][MAX_PLATES+8-2] = EMPTY;cur=0;}else{pillar[cur+1][MAX_PLATES+8-2] = pillar[cur][MAX_PLATES+8-2];pillar[cur][MAX_PLATES+8-2] = EMPTY;cur++;}break;case SPACE:if(isPicked == 1){if(pillar[cur][0]==0){pillar[cur][0] = pillar[cur][MAX_PLATES+8-2];pillar[cur][MAX_PLATES+8-2] = CUR;steps++;isPicked = 0;}else{for(int i = MAX_PLATES+5-1; i>=0; i--){if(pillar[cur][i] != 0){if(pillar[cur][MAX_PLATES+8-2] < pillar[cur][i]){pillar[cur][i+1] = pillar[cur][MAX_PLATES+8-2];pillar[cur][MAX_PLATES+8-2] = CUR;steps++;isPicked = 0;}else{printf("不能放在比自己小的盘子上!\n");pause();}break;}}}}else{for(int i = MAX_PLATES+5-1; i>=0; i--){if(pillar[cur][i] != 0){pillar[cur][MAX_PLATES+8-2] = pillar[cur][i];pillar[cur][i] = 0;isPicked = 1;break;}}}break;case 'L': case 'l':return 0;default:break;}}
}int main(void){int plateNum=0;int key;int confirm=0;int step=0;while(confirm != 'y' && confirm != 'Y'){plateNum = menu();if(plateNum == 0){printf("结束游戏……\n");return 0;}cls();printf("确定开始游戏吗?\n盘数:%d\n最小移动步数:%d\n按“Y”键确认,按其他任意键返回重选。\n",plateNum,nTimesTwo(plateNum)-1);confirm = getch();}step = game(plateNum);if(step != 0){printf("成功!你所用的步数为:%d步。\n",step);}printf("游戏结束。\n");pause();return 0;
}