# 一、问题描述

利用一阶谓词逻辑求解猴子摘香蕉问题：房内有一个猴子，一个箱子，天花板上挂了一串香蕉，其位置如图1所示，猴子为了拿到香蕉，它必须把箱子搬到香蕉下面，然后再爬到箱子上。请定义必要的谓词，列出问题的初始化状态（即下图所示状态），目标状态（猴子拿到了香蕉，站在箱子上，箱子位于位置b）。

# 二、迟来的的代码

``````#include <stdio.h>

#define Yes 1           // monkey on the box
#define No 0            // monkey doesn't on the box
#define maxStep 150     // monkey can do the max steps

// define the problem states struct
struct States
{
char box;       // box location
char monkey;    // monkey location
char banana;    // banana location
short Onbox;    // monkey on the box
}states[maxStep];

static int n = 0;   // count step

// initialize problem states
void init()
{
printf("please input the banana location: ");
scanf("%c", &states[0].banana);

printf("please input the monkey location: ");
scanf("n%c", &states[0].monkey);

printf("please input the box location: ");
scanf("n%c", &states[0].box);

// if the monkey and box aren't in the same place,
// then predicts monkey doesn't on the box
if(states[0].monkey != states[0].box)
{
states[0].Onbox = No;
}
else
{
printf("Is the monkey on the box now? (1/0)");
scanf("n%hd", &states[0].Onbox);
}
}

// monkey reach the banana
void reach(int i)
{
printf("monkey reach the bananan");
n++;
}

// monkey go to location
void monkeyGoto(int i, char location)
{
printf("monkey go to %cn", location);
states[i+1] = states[i];
states[i+1].monkey = location;  // change monkey location
n++;
}

// monkey climb on the box
void climbOnbox(int i)
{
printf("monkey climb on the boxn");
states[i+1] = states[i];
states[i+1].Onbox = Yes;
n++;
}

// monkey climb down the box
void climbDownbox(int i)
{
printf("monkey climb down the boxn");
states[i+1] = states[i];
states[i+1].Onbox = No;
n++;
}

// monkey move the box to dest
void moveBox(int i, char dest)
{
printf("monkey move the box to %cn", dest);
states[i+1] = states[i];
states[i+1].monkey = dest;  // change monkey location
states[i+1].box = dest;     // change box location
n++;
}

// monkey do next Step
int nextStep(int i)
{
if (i >= maxStep)
{
printf("Steps are too more, monkey can't go again!/n");
return No;
}

// if the banana and box are in the same place
if(states[i].banana == states[i].box)
{
// if the monkey is on the box, then reach it
if(states[i].Onbox)
{
reach(i);
return Yes;
}
else
{
// monkey doesn't on the box but in the same place
if(states[i].monkey == states[i].box)
{
climbOnbox(i);
return nextStep(i+1);
}
// monkey doesn't on the box and not in the same place
else
{

monkeyGoto(i, states[i].box);
return nextStep(i+1);
}
}
}
// banana and box aren't in the same place
else
{
// monkey on the box
if(states[i].Onbox)
{
climbDownbox(i);
return nextStep(i+1);
}
else
{
// monkey and box are in the same place
if(states[i].monkey == states[i].box)
{
moveBox(i, states[i].banana);
return nextStep(i+1);
}
// monkey and box aren't int the same place
else
{
monkeyGoto(i, states[i].box);
return nextStep(i+1);
}
}
}
}

int nextStep1(int i)
{
while(i< maxStep)
{
// if the banana and box are in the same place
if(states[i].banana == states[i].box)
{
// if the monkey is on the box, then reach it
if(states[i].Onbox)
{
reach(i);
return Yes;
}
else
{
// monkey doesn't on the box but in the same place
if(states[i].monkey == states[i].box)
{
climbOnbox(i);
i++;
continue;
}
// monkey doesn't on the box and not in the same place
else
{
monkeyGoto(i, states[i].box);
i++;
continue;
}
}
}
// banana and box aren't in the same place
else
{
// monkey on the box
if(states[i].Onbox)
{
climbDownbox(i);
i++;
continue;
}
else
{
// monkey and box are in the same place
if(states[i].monkey == states[i].box)
{
moveBox(i, states[i].banana);
i++;
continue;
}
// monkey and box aren't int the same place
else
{
monkeyGoto(i, states[i].box);
i++;
continue;
}
}
}
}

if (i >= maxStep)
{
printf("Steps are too more, monkey can't go again!/n");
return No;
}
}

int main(void)
{
init();
printf("nmonkey go to grasp the banana nownn");
nextStep1(0);
printf("nTo reach the banana, monkey need to do %i stepsn", n);

return 0;
}

``````

# 三、简单分析

猴子摘香蕉问题是一个经典的人工智能算法题，主要考察对知识的表示和推理，可以设置多个初始状态，对猴子进行测试，具体的推理过程代码里已经详细讲解了，这里不做具体叙述。此外，注意初始状态的描述，当猴子与箱子不在同一位置时，猴子一定不在箱子上面。这里还写了递归和迭代的两种方法。

为了改变一下，本次注释采用英文形式，不便之处，多多见谅^_^

如果是广大的同学记得关注我哦，最近准备写实验的博客，包括大一，大二，大三的，如果大家有什么想让我写的博客，可以留言，我会在必要的时候把实验的内容发布在博客，供大家参考指教（^_^）

# 四、附上广大计科专业的人工智能本题的代码（非常不建议使用，bug特别多^_^，且难读懂）

``````#include <stdio.h>
struct State
{
int monkey; /*-1:Monkey at A;0: Monkey at B;1:Monkey at C;*/
int box; /*-1:box at A;0:box at B;1:box at C;*/
int banana; /*Banana at B,Banana=0*/
int monbox; /*-1: monkey on the box;1: monkey  the box;*/
};
struct State States [150];
char* routesave[150];
/*function monkeygoto,it makes the monkey goto the other place*/
void monkeygoto(int b,int i)
{
int a;
a=b;
if (a==-1)
{
routesave[i]="Monkey go to A";
States[i+1]=States[i];
States[i+1].monkey=-1;
}
else if(a==0)
{
routesave[i]="Monkey go to B";
States[i+1]=States[i];
States[i+1].monkey=0;
}
else if(a==1)
{
routesave[i]="Monkey go to C";
States[i+1]=States[i];
States[i+1].monkey=1;
}
else
{
printf("parameter is wrong");
}
}
/*end function monkeyygoto*/
/*function movebox,the monkey move the box to the other place*/
void movebox(int a,int i)
{
int B;
B=a;
if(B==-1)
{
routesave[i]="monkey move box to A";
States[i+1]=States[i];
States[i+1].monkey=-1;
States[i+1].box=-1;
}
else if(B==0)
{
routesave[i] = "monkey move box to B";
States[i+1]=States[i];
States[i+1].monkey=0;
States[i+1].box=0;
}
else if(B==1)
{
routesave[i] = "monkey move box to C";
States[i+1]=States[i];
States[i+1].monkey=1;
States[i+1].box=1;
}
else
{
printf("parameter is wrong");
}
}
/*end function movebox*/
/*function climbonto,the monkey climb onto the box*/
void climbonto(int i)
{
routesave[i]="Monkey climb onto the box";
States[i+1]=States[i];
States[i+1].monbox=1;
}
/*function climbdown,monkey climb down from the box*/
void climbdown(int i)
{
routesave[i]="Monkey climb down from the box";
States[i+1]=States[i];
States[i+1].monbox=-1;
}
/*function reach,if the monkey,box,and banana are at the same place,the monkey reach banana*/
void reach(int i)
{
routesave[i]="Monkey reach the banana";
}
/*output the solution to the problem*/
void showSolution(int i)
{
int c;
printf ("%s n", "Result to problem:");
for(c=0; c<i+1; c++)
{
printf ("Step %d : %s n",c+1,routesave[c]);
}
printf("n");
}
/*perform next step*/
void nextStep(int i)
{
int c;
int j;
if(i>=150)
{
printf("%s  n", "steplength reached 150,have problem ");
return;
}
for (c=0; c<i; c++) /*if the current state is same to previous,retrospect*/
{
if(States[c].monkey==States[i].monkey&&States[c].box==States[i].box&&States[c].banana==States[i].banana&&States[c].monbox==States[i].monbox)
{
return;
}
}
if(States[i].monbox==1&&States[i].monkey==0&&States[i].banana==0&&States[i].box==0)
{
showSolution(i);
printf("Press any key to continue n");
getchar();/*to save screen for user,press any key to continue*/
return;
}
j=i+1;
if(States[i].monkey==0)
{
if(States[i].box==0)
{
if(States[i].monbox==-1)
{
climbonto(i);
reach(i+1);
nextStep(j);
/*monkeygoto(-1,i);
nextStep(j);
monkeygoto(0,i);
nextStep(j);
movebox(-1,i);
nextStep(j);
movebox(0,i);
nextStep(j);*/
}
else
{
reach(i+1);
nextStep(j);
/*climbdown(i);
nextStep(j);*/
}
}
else if(States[i].box==1)
{
/*monkeygoto(-1,i);
nextStep(j);*/
monkeygoto(1,i);
nextStep(j);
movebox(0,i);
nextStep(j);
climbonto(i);
reach(i+1);
nextStep(j);
}
else /*box==-1*/
{
monkeygoto(-1,i);
nextStep(j);
movebox(0,i);
nextStep(j);
climbonto(i);
reach(i+1);
nextStep(j);
}
}
/*end if*/
if(States[i].monkey==-1)
{
if(States[i].box==-1)
{
if(States[i].monbox==-1)
{
movebox(0,i);
nextStep(j);
climbonto(i);
reach(i+1);
nextStep(j);
}
else
{
climbdown(i);
nextStep(j);
movebox(0,i);
nextStep(j);
climbonto(i);
reach(i+1);
nextStep(j);
}
}
else if(States[i].box==0)
{
monkeygoto(0,i);
nextStep(j);
climbonto(i);
reach(i+1);
nextStep(j);
}
else
{
monkeygoto(1,i);
nextStep(j);
movebox(0,i);
nextStep(j);
climbonto(i);
reach(i+1);
nextStep(j);
}
}
/*end if*/
if(States[i].monkey==1)
{
if (States[i].box==1)
{
if(States[i].monbox==-1)
{
movebox(0,i);
nextStep(j);
climbonto(i);
reach(i+1);
nextStep(j);
}
else
{
climbdown(i);
nextStep(j);
movebox(0,i);
nextStep(j);
climbonto(i);
reach(i+1);
nextStep(j);
}
}
else if(States[i].box==-1)
{
monkeygoto(-1,i);
nextStep(j);
movebox(0,i);
nextStep(j);
movebox(0,i);
nextStep(j);
climbonto(i);
reach(i+1);
nextStep(j);
}
else
{
monkeygoto(0,i);
nextStep(j);
movebox(0,i);
nextStep(j);
climbonto(i);
reach(i+1);
nextStep(j);
}
}
/*end if*/
}/*end nextStep*/
int main()
{
States[0].monkey=-1;
States[0].box=1;
States[0].banana=0;
States[0].monbox=-1;
nextStep(0);
}``````

THE END