当前位置:首页 » 编程语言 » 农夫过河c语言算法位运算
扩展阅读
webinf下怎么引入js 2023-08-31 21:54:13
堡垒机怎么打开web 2023-08-31 21:54:11

农夫过河c语言算法位运算

发布时间: 2023-02-21 09:30:07

c语言,农夫过河问题

程序就是求解农夫过河问题:
农夫带着一狼,一羊和一些菜过河。河边只有一船,一次农夫只能带一样东西。无人时,狼要吃羊,羊要吃菜,程序将找出所有农夫过河的方案。

首先要表示狼,羊,菜和农夫所在的位置,4者的位置有本岸和对岸两种情况,分别用0和1表示,4者,所以用一个有4元素的数组。为了要记录每一步,程序中使用了一个二维数组a[MAX_STEP][4],记录每一步4者所在位置。第一步就是a[0],第二布是a[1]...而,a[0][0]就表示第一步狼在本岸(0)还是对岸(1),a[0][1]表示第一步羊在本岸还是对岸......
为了记录每一次农夫过河时的状态,使用了一个数组b[MAX_STEP],数组中的元素的值可能为-1, 0, 1, 2,分别表示农夫在过河时,是空手,带狼,带羊,带菜。

第一步的状态是狼,羊,菜和农夫都在本案,所以a[0][0]到a[0][3]都是0,本来应该初始化一下,但a是全局变量,所以自动初始化为0,所以程序中省下了这一步。
search是一个递归函数,通过不断的查找可能的下一步,找出一个方案,是一种深度优先搜索。
a[iStep][0] + a[iStep][1] + a[iStep][2] + a[iStep][3] == 4意味着第 iStep时,a[iStep][0]到a[iStep][3]都为1,表示4者都到了对岸。所以输出结果。
for (i = 0; i < iStep; i++)
{
if (a[i][3] == 0)
{
printf("%s到对岸\n", name[b[i] + 1]);
}
else
{
printf("%s回本岸\n", name[b[i] + 1]);
}
}
输出每一步
a[i][3]是农夫在本岸还是对岸,如果为0,在本岸,下一步肯定是到对岸,所以打印"...到对岸",而name[b[i]+1]找出对应带的东西的描述。
for (i = 0; i < iStep; i++)
{
if (memcmp(a[i], a[iStep], sizeof(a[i])) == 0)
{
return;
}
}
判定是否会死循环,如果当前状态在以前出现过,那么就会出现死循环。用当前这步的状态a[iStep]和以前的所有步a[i] (i=0; i <iStep; i++)比较。memcmp是内存比较函数,可以用于比较数组,返回值为0,表示数组中所有值相同。
如果相同,就直接返回,不再查找。

if (a[iStep][1] != a[iStep][3] && (a[iStep][2] == a[iStep][1] || a[iStep][0] == a[iStep][1]))
{
return;
}

判定羊会吃菜,或狼会吃羊的情况。
当农夫和羊在一起的时候,狼不会吃羊,羊也不会吃菜,所以只有当农夫和羊不在一起(a[iStep][1] != a[iStep][3])时,才可能发生“吃”的状态。
而且“吃”的情况必须是在菜和羊在一起(a[iStep][2] == a[iStep][1])或者羊和狼在一起(a[iStep][0] == a[iStep][1])
发生吃的情况是,返回,不再查找。

for (i = -1; i <= 2; i++)
{
b[iStep] = i;
memcpy(a[iStep + 1], a[iStep], sizeof(a[iStep + 1]));
a[iStep + 1][3] = 1 - a[iStep + 1][3];
if (i == -1)
{
search(iStep + 1);
}
else if (a[iStep][i] == a[iStep][3])
{
a[iStep + 1][i] = a[iStep + 1][3];
search(iStep + 1);
}
}
但现在,已经确保了上一步是“安全”的,可以继续查找。
-1, 0, 1, 2分别表示渡河时4种情况,空手,带狼,带羊,带菜。
memcpy(a[iStep + 1], a[iStep], sizeof(a[iStep + 1])); 复制当前步的数组到下一步。
农夫的状态肯定会发生改变,所以a[iStep + 1][3] = 1 - a[iStep + 1][3]; 因为当a为0或1时,a = 1 - a会使a在0和1之间切换。
如果i== -1,表示空手,狼,羊,菜的状态都不会发生改变,所以直接搜索下一步(search(iStep + 1); )
否则要被带过去的东西(0, 1, 2分别表示0, 1, 2)的状态需要改变。
要带的东西必须和农夫同在本案或对岸(a[iStep][i] == a[iStep][3]),才可能带得了。只有在这种情况下,使要带的东西的状态和农夫相同(a[iStep + 1][i] = a[iStep + 1][3];),并开始下一步的搜索(search(iStep + 1))。

❷ 仅用c语言能编出哪些小游戏

可以编写狼追兔子游戏,掷骰子游戏,24点游戏,井字棋游戏,农夫过河游戏,扫雷小游戏,人机猜数游戏,三色球游戏, 推箱子游戏,坦克大战游戏,贪吃蛇游戏等。

❸ 哪位会c语言的老哥帮我看看 位运算农夫过河问题

scanf("%c",&p[i]); fflush(stdin); //加一句清输入缓冲区即可。
另外,int *move(int *M,int i){}
改为 int move(int *M,int i){} 否则 a=move(&a,3); 这种句子变量类型不匹配。

❹ 农夫过河问题的求解

#include<iostream.h>
#include<stdio.h>
#defineMAXNUM 20
typedefstruct //顺序队列类型定义
{
int f, r; //f表示头,r 表示尾
int q[MAXNUM];//顺序队
}SeqQueue,*PSeqQueue;

PSeqQueuecreateEmptyQueue_seq( ) //创建队列
{
PSeqQueue paqu = new SeqQueue;
if(paqu == NULL)
cout<<"Out of space!"<<endl;
else
paqu->f=paqu->r=0;
return (paqu);
}
intisEmptyQueue_seq( PSeqQueue paqu ) //判断paqu 所指是否是空队列
{
return paqu->f==paqu->r;
}
voidenQueue_seq(PSeqQueue paqu,int x) //在队列中插入一元素 x
{
if ((paqu->r+1)%MAXNUM==paqu->f)
cout<<"队列已满."<<endl;
else
{
paqu->q[paqu->r]=x;
paqu->r=(paqu->r+1)%MAXNUM;
}
}
void deQueue_seq(PSeqQueue paqu) //删除队列头部元素
{
if( paqu->f==paqu->r)
cout<<"队列为空"<<endl;
else
paqu->f=(paqu->f+1)%MAXNUM;
}
intfrontQueue_seq( PSeqQueue paqu ) //对非空队列,求队列头部元素
{
return (paqu->q[paqu->f]);
}
intfarmer(int location) //判断农夫位置对0做与运算,还是原来的数字,用来判断位置
{
return 0 != (location & 0x08);
}
intwolf(int location) //判断狼位置
{
return 0 != (location & 0x04);
}
intcabbage(int location) //判断白菜位置
{
return 0 != (location & 0x02);
}
intgoat(int location) //判断羊的位置
{
return 0 !=(location & 0x01);
}
intsafe(int location) // 若状态安全则返回 true
{
if ((goat(location) == cabbage(location))&& (goat(location) != farmer(location)) )
return 0;
if ((goat(location) == wolf(location))&& (goat(location) != farmer(location)))
return 0;
return 1; //其他状态是安全的

}
void farmerProblem( )
{
int movers, i, location, newlocation;
int route[16]; //记录已考虑的状态路径
int print[MAXNUM];
PSeqQueue moveTo;
moveTo = createEmptyQueue_seq( );//新的队列判断路径
enQueue_seq(moveTo, 0x00); //初始状态为0
for (i = 0; i < 16; i++)
route[i] = -1; //-1表示没有记录过路径
route[0]=0;
while(!isEmptyQueue_seq(moveTo)&&(route[15] == -1))//队列不为空,路径未满时循环
{
location = frontQueue_seq(moveTo); //从队头出队
deQueue_seq(moveTo);
for (movers = 1; movers <= 8;movers<<= 1)
{
if ((0 != (location & 0x08)) == (0 !=(location & movers)))
{
newlocation = location^(0x08|movers);//或运算
if (safe(newlocation) &&(route[newlocation] == -1))//判断是否安全,以及路径是否可用

{
route[newlocation] = location;
enQueue_seq(moveTo, newlocation);

}

}

}

}
/*打印出路径 */
if(route[15] != -1)
{
cout<<"过河步骤是 : "<<endl;
i=0;
for(location = 15; location >= 0; location= route[location])
{
print[i]=location;
i++;
if (location == 0)
break;
}
int num=i-1;
int temp[20][4];
int j;
for(i=num;i>=0;i--)
{
for(j=3;j>=0;j--)
{
temp[num-i][j]=print[i]%2;
print[i]/=2;
temp[0][j]=0;
temp[num+1][j]=1;
}
}
for(i=1;i<=num;i++)
{
cout<<"\t\t\tNO ."<<i<<"\t";
if(i%2==1)
{
if(temp[i][3]!=temp[i-1][3])
cout<<"农夫带羊过南岸";
if(temp[i][2]!=temp[i-1][2])
cout<<"农夫带白菜过南岸";
if(temp[i][1]!=temp[i-1][1])
cout<<"农夫带狼过南岸";
if(temp[i][3]==temp[i-1][3]&&temp[i][2]==temp[i-1][2]&&temp[i][1]==temp[i-1][1])
cout<<"农夫自己过南岸";
}
else if(i%2==0)
{
if(temp[i][3]!=temp[i-1][3])
cout<<"农夫带羊回北岸";
if(temp[i][2]!=temp[i-1][2])
cout<<"农夫带白菜回北岸";
if(temp[i][1]!=temp[i-1][1])
cout<<"农夫带狼回北岸";
if(temp[i][3]==temp[i-1][3]&&temp[i][2]==temp[i-1][2]&&temp[i][1]==temp[i-1][1])
cout<<"农夫自己回北岸";
}
cout<<endl;
}
}

else
cout<<"Nosolution."<<endl;
}
int main() /*主函数*/
{
farmerProblem();

return 0;
}