汉诺塔问题可以用递归和堆栈,也可以纯循环实现(坑人的程设作业)
参考资料:https://wenku.baidu.com/view/7c4c2b6d0029bd64793e2c68 (必看)
感谢资料作者。
#include<stdio.h>
#define NUM_OF_PILLAR 3 //三根柱子
int* find(int (*a)[NUM_OF_PILLAR],int *loc,int which,int num);//找到目标圆盘位置
void move(int* loc,int (*a)[NUM_OF_PILLAR],int num,int judge);//移动圆盘
int main()
{
int num,row,col;//声明盘子数目,二维数组的行、列数
scanf("%d",&num);
int a[num][NUM_OF_PILLAR];
int loc[2]={0};//声明存放盘子坐标的数组
int i;//给for用
int judge;
if(num%2==0){//判断圆盘数目为奇数还是偶数
judge = 1;//奇数往左移
}
else{
judge = -1;//偶数往右移
}
for(row=0;row<num;row++){
a[row][0]=row+1;
}
for(row=0;row<num;row++){
a[row][1]=0;
}
for(row=0;row<num;row++){
a[row][2]=0;
}//三个for初始化柱子上圆盘的位置
while(a[0][2]!=1)//主循环,判别条件:最后一根柱子上的顶端位置放着最小盘
{ //注意这里的柱子只能放num个圆盘 所以判断最后一根柱最高点的就可以了
for(i=1;i<=num;i++)
{
find(a,loc,i,num);
move(loc,a,num,judge);
}
}
return 0;
}
//遍历二维数组,找到目标值which的坐标
int* find(int (*a)[NUM_OF_PILLAR],int *loc,int which,int num)
{
int col,row;
for(col=0;col<NUM_OF_PILLAR;col++){
for(row=0;row<num;row++){
loc[0]=row;
loc[1]=col;
if(a[row][col]==which)
return loc;
}
}
}
//移动盘子
void move(int* loc,int (*a)[NUM_OF_PILLAR],int num,int judge)
{
int nowRow,nowCol,nextRow,nextCol,i,temp;
nowRow=loc[0];
nowCol=loc[1];
nextCol=loc[1]+judge;//利用judge决定列该加还是减 加表示右移 减表示左移
temp=a[nowRow][nowCol];
if(nextCol<0)//防止数组下标越界
{
nextCol=NUM_OF_PILLAR-1;
}
if(nextCol>2)//防止数组下标越界
{
nextCol=0;
}
for(i=0;i<2;i++)//当无法去后面两根柱子时 放弃本次移动
{
for(nextRow=num-1;nextRow>=0;nextRow--)
{
if(a[nowRow-1][nowCol]>0)//如果待移动圆盘上方有别的圆盘 放弃本次移动
{
return;
}
if(a[nextRow][nextCol]>a[nowRow][nowCol])//可移动
{
if(a[nextRow-1][nextCol]==0){//判断目标位置上有没有别的圆盘
a[nowRow][nowCol]=0;
nowRow=nextRow-1;
nowCol=nextCol;
a[nowRow][nowCol]=temp;
char from,to;
switch(loc[1]) {
case 0:from='A';break;
case 1:from='B';break;
case 2:from='C';break;
}
switch(nowCol) {
case 0:to='A';break;
case 1:to='B';break;
case 2:to='C';break;
}
printf("%c %c\n",from,to);
return ;
}
}
if(a[num-1][nextCol]==0)//如果目标柱是空的直接移动
{
a[nowRow][nowCol]=0;
nowRow=nextRow;
nowCol=nextCol;
a[nowRow][nowCol]=temp;
char from,to;
switch(loc[1]) {
case 0:from='A';break;
case 1:from='B';break;
case 2:from='C';break;
}
switch(nowCol) {
case 0:to='A';break;
case 1:to='B';break;
case 2:to='C';break;
}
printf("%c %c\n",from,to);
return ;
}
}
nextCol+=judge;//无法移到第一根目标柱 目光投向第二根
if(nextCol<0)
{
nextCol=2;
}
if(nextCol>2)
{
nextCol=0;
}
}
}