C语言:汉诺塔的纯循环实现

汉诺塔问题可以用递归和堆栈,也可以纯循环实现(坑人的程设作业)

参考资料: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;
	}
}
}

 

  • 2
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值