用python编写猴子吃桃问题_人工智能猴子摘香蕉

用python编写猴子吃桃问题_人工智能猴子摘香蕉Java实现人工智能实验一,猴子摘香蕉,图形化展示

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用

人工智能课程实验一的任务,写出猴子摘香蕉问题的知识表示,并用代码实现推理过程

问题描述

一个房间里,天花板上挂有一串香蕉,有一只猴子可在房间里任意活动(到处走动,推移箱子,攀登箱子等)。设房间里还有一只可被猴子移动的箱子,且猴子登上箱子时才能摘到香蕉,问猴子在某一状态下(设猴子位置为A,香蕉位置在B,箱子位置为C),如何行动可摘取到香蕉。

知识表示

知识表示的方法是有很多,如一阶谓词、产生式、语义网、框架等等。这里选择的是产生式表示的方法

知识的产生式表示

在这里插入图片描述

综合数据库

(ON, HOLD, Monkey, Banana, Box)
ON=0:猴子在地板上
ON=1:猴子在箱子上
HOLD=0:猴子没有抓到香蕉
HOLD=1:猴子抓到了香蕉
Monkey:猴子的位置
Banaba:香蕉的位置
Box: 箱子的位置

规则库

  1. IF 猴子位置= =箱子位置= =香蕉位置
    AND 猴子ON箱子
    THEN 猴子HOLD香蕉
  2. IF 猴子位置= =箱子位置= =香蕉位置
    AND 非(猴子ON 箱子)
    THEN 猴子ON箱子
  3. IF 猴子位置= =箱子位置!=香蕉位置
    AND 猴子ON 箱子
    THEN 非(猴子ON箱子)
  4. IF 猴子位置= =箱子位置!=香蕉位置
    AND 非(猴子ON 箱子)
    THEN猴子位置= =箱子位置= =香蕉位置
  5. IF 猴子位置!=箱子位置= =香蕉位置
    AND非(猴子ON箱子)
    THEN 猴子位置= =箱子位置
  6. IF 猴子位置!=箱子位置!=香蕉位置
    AND非(猴子ON箱子)
    THEN 猴子位置==箱子位置
    结束状态(1,1,B,B,B)

算法实现

其实用python实现最便捷,但我没有安装python环境(没写过python我是菜鸡)所以就用了Java实现,但思路不够清晰,写的很啰嗦呜呜呜
顺便做出了图形化界面,用的是学CS61b时候白嫖的StdDraw标准绘图库,把因为jdk版本问题,没有用StdDraw.java文件 ,直接把StdDraw.class文件放在lib问价夹里并在IDE里添加依赖路径就可以用了,而且IntelliJ IDEA会直接把.class文件decompile成.java文件显示,哦吼~

class设计

根据PEAS设计class
在这里插入图片描述
在这里插入图片描述
猴子是Agent,所以将Monkey作为主类。
显然:猴子可以移动,箱子可以被猴子推走,香蕉可以被摘下来,他们都可以移动,都需要有横纵坐标 以显示在图形界面不同的位置上。设计一个抽象类movable,包含他们共同的属性(横纵坐标,图片文件路径等)以及方法(显示图片)
因为只需要考虑三个位置ABC,就把问题化简了。
ps:StdDraw设定的画布原点在正中间

public abstract class movable { 
   
    public int X;
    public int Y;
    public String imgFileName;
    public static int A = -40;
    public static int B = 2;
    public static int C = 40;
    public static final int ceiling = 50;
    public static final int floor = -30;
    public static final int onBox = 10;
    public static final int inHand = 20;

    public void draw(){ 
   
        StdDraw.picture(X,Y,imgFileName);
    }
}

箱子和香蕉直接extent即可

public class Banana extends movable{ 
   
    public Banana(int B){ 
   
        this.X = B;
        if(HOLD.isHOLD())
            this.Y = inHand;
        this.Y = ceiling;
        imgFileName = "data/banana.png";
    }
}
///
public class Box extends movable{ 
   

    public Box(int C){ 
   
        this.X = C;
        this.Y = floor;
        imgFileName = "data/box.png";
    }
}

对于ON HOLD两种状态,定义成了两个静态类,方便判断

public class ON { 
   
    private static final int yes = 1;
    private static final int no = 0;
    private static int status;
    public static boolean isON(){ 
   
        return status == yes;
    }
    public static void setYes(){ 
   
        status = yes;
    }
    public static void setNo(){ 
   
        status = no;
    }
    public static void setStatus(int arg){ 
   
        status = arg;
    }
    public static int getStatus(){ 
   
        return status;
    }
}

public class HOLD { 
   
    private static final int yes = 1;
    private static final int no = 0;
    private static int status;
    public static boolean isHOLD(){ 
   
        return status == yes;
    }
    public static void setYes(){ 
   
        status = yes;
    }
    public static void setNo(){ 
   
        status = no;
    }
    public static void setStatus(int arg){ 
   
        status = arg;
    }
    public static int getStatus(){ 
   
        return status;
    }
}

最后就是主类monkey

因为猴子的动作(推箱子,走向箱子)等等都需要知道或改变箱子、香蕉的位置,从逻辑性和复用性的角度考虑,肯定是将实例化后的箱子,香蕉作为参数传入给猴子拥有的方法比较合理。但我只是为了完成这个实验所以干脆把Box、Banana 作为猴子的成员变量

StdDraw显示动画的原理:t时刻在(x,y)处显示图片1,清空画布,t+dt 时刻在(x+dx,y+dy)处显示图片1,达到视觉上的移动效果。所以为了在空白处显示每一步对应的产生式变化,我用allsteps存储每一步状态,每次更新的时候清空画布并且显示目前为止经历的状态,有些凌乱,都不是重点

import java.util.ArrayList;
import java.util.List;
public class Monkey extends movable{ 

Box box;
Banana banana;
List<List<Character>> allSteps = new ArrayList<>();
public Monkey(int A){ 

this.X = A;
if(ON.isON())
this.Y = onBox;
else this.Y = floor;
imgFileName = "data/monkey.png";
}
public void firstStep(){ 

List<Character> init = new ArrayList<>();
init.add(run.status.get(ON.getStatus()));
init.add(run.status.get(HOLD.getStatus()));
init.add(run.status.get(this.X));
init.add(run.status.get(this.banana.X));
init.add(run.status.get(this.box.X));
allSteps.add(init);
showStep();
}
public void moveToBox(){ 

this.X = box.X;
List<Character> sb = new ArrayList<>();
sb.add(run.status.get(ON.getStatus()));
sb.add(run.status.get(HOLD.getStatus()));
sb.add(run.status.get(this.X));
sb.add(run.status.get(this.banana.X));
sb.add(run.status.get(this.box.X));
allSteps.add(sb);
showStep();
}
public void pushToBanana(){ 

this.X = banana.X;
box.X = banana.X;
List<Character> sb = new ArrayList<>();
sb.add(run.status.get(ON.getStatus()));
sb.add(run.status.get(HOLD.getStatus()));
sb.add(run.status.get(this.X));
sb.add(run.status.get(this.banana.X));
sb.add(run.status.get(this.box.X));
allSteps.add(sb);
showStep();
}
public void climbOn(){ 

ON.setYes();
this.Y = onBox;
List<Character> sb = new ArrayList<>();
sb.add(run.status.get(ON.getStatus()));
sb.add(run.status.get(HOLD.getStatus()));
sb.add(run.status.get(this.X));
sb.add(run.status.get(this.banana.X));
sb.add(run.status.get(this.box.X));
allSteps.add(sb);
showStep();
}
public void climbDown(){ 

ON.setNo();
this.Y = floor;
StdDraw.clear();
List<Character> sb = new ArrayList<>();
sb.add(run.status.get(ON.getStatus()));
sb.add(run.status.get(HOLD.getStatus()));
sb.add(run.status.get(this.X));
sb.add(run.status.get(this.banana.X));
sb.add(run.status.get(this.box.X));
allSteps.add(sb);
showStep();
}
public void grasp(){ 

HOLD.setYes();
this.banana.Y = inHand;
List<Character> sb = new ArrayList<>();
sb.add(run.status.get(ON.getStatus()));
sb.add(run.status.get(HOLD.getStatus()));
sb.add(run.status.get(this.X));
sb.add(run.status.get(this.banana.X));
sb.add(run.status.get(this.box.X));
allSteps.add(sb);
showStep();
}
private void showStep(){ 

int Line = 70;
int addLine = -5;
StdDraw.clear();
this.box.draw();
this.draw();
this.banana.draw();
for(List<Character> list:allSteps){ 

StdDraw.text(-60,Line, list.toString());
Line += addLine;
}
StdDraw.text(movable.A,-65,"A");
StdDraw.text(movable.B,-65,"B");
StdDraw.text(movable.C,-65,"C");
StdDraw.show();
StdDraw.pause(1000);
}
}

最后就是run这个运行类,main函数在这里(包含规则库),从txt文件读取五元组的初始状态,需要从字符到坐标再到字符进行一些转化
规则库才是这个实验的重点,所以写了注释,虽然很简单

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class run { 

public static final Map<Integer,Character> status = new HashMap<>();
private static void defineStatus(){ 

status.put(-40,'A');
status.put(2,'B');
status.put(40,'C');
status.put(0,'0');
status.put(1,'1');
}
private static int charToPosition(char c){ 

switch (c){ 

case 'A':return movable.A;
case 'B':return movable.B;
case 'C':return movable.C;
default:return 0;
}
}
public static Monkey readArgs(String path){ 

//从文件中读取初始状态
//猴子,香蕉,箱子的位置以及是否猴子是否在箱子上,是否拿着香蕉
In in = new In(path);
ON.setStatus(in.readInt());
HOLD.setStatus(in.readInt());
in.readChar();
Monkey monkey = new Monkey(charToPosition(in.readChar()));
in.readChar();
monkey.banana = new Banana(charToPosition(in.readChar()));
in.readChar();
monkey.box = new Box(charToPosition(in.readChar()));
//对于一些不合理的输入报警
assert !ON.isON() || monkey.X == monkey.box.X
:"illegal position when on box";
assert !HOLD.isHOLD() ||
(monkey.X == monkey.box.X) && (monkey.X == monkey.banana.X)
:"illegal position when hold banana";
assert !HOLD.isHOLD() || ON.isON():"hold banana but not on box";
return monkey;
}
public static void main(String[] args) { 

defineStatus();
//读取txt文件
String fileName = args[0];
Monkey monkey = readArgs(fileName);
//画面双缓冲防抖
StdDraw.enableDoubleBuffering();
//画布大小
StdDraw.setScale(-80,80);
StdDraw.clear();
//展示猴子香蕉箱子初始状态
monkey.box.draw();
monkey.draw();
monkey.banana.draw();
monkey.firstStep();
StdDraw.show();
StdDraw.pause(1000);
if(HOLD.isHOLD()){ 

//如果猴子已经拿到香蕉直接展示
//对于猴子拿到香蕉却没有站在箱子上的不合法输入在读取文件时报警
StdDraw.show();
}
else if(ON.isON()){ 

//如果猴子没拿到香蕉但站在箱子上
//则观察箱子是否和香蕉在同一个位置
if(monkey.banana.X!= monkey.X){ 

//如果不在同一个位置,需要猴子先
//下箱子,推箱子到香蕉位置,爬箱子
monkey.climbDown();
monkey.pushToBanana();
monkey.climbOn();
}//然后拿到香蕉。如果在同一个位置直接拿香蕉
monkey.grasp();
}else{ 
//如果猴子没有站在箱子上
//要观察箱子是否和猴子在同一个位置,
//以及箱子是否和香蕉在同一个位置
if(monkey.box.X!= monkey.X){ 

if(monkey.box.X!=monkey.banana.X){ 

//如果猴子和箱子不在同一个位置,箱子和香蕉也不在同一个位置
monkey.moveToBox();//猴子需要走到箱子处
monkey.pushToBanana();//推箱子到香蕉处
monkey.climbOn();//爬上箱子
monkey.grasp();//拿香蕉
}else{ 
//如果猴子和箱子不在同一个位置,箱子和香蕉在同一个位置
monkey.moveToBox();//猴子只要走到箱子处,不用推箱子
monkey.climbOn();//直接爬箱子
monkey.grasp();//拿香蕉
}
}
else{ 
//如果猴子没有在箱子上但和箱子在同一个位置
if(monkey.box.X!=monkey.banana.X){ 

//猴子推箱子到香蕉处
monkey.pushToBanana();
}//爬上箱子
monkey.climbOn();
monkey.grasp();//拿香蕉
}
}
}
}

最后,运行的效果如下

用到的lib,In和StdDraw

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/189454.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • 程序员在外包公司工作怎么样呢_从外包公司出来好找工作吗

    程序员在外包公司工作怎么样呢_从外包公司出来好找工作吗    今天刚刚好是周六,本来是可以好好休息的,计划好要去哪里玩的,但是天有不测风云,突然说银行领导要来检查,今天周末大家必须和平时一样照常上班,天呐!大哭!也无奈,只能照常上班咯,谁让别人是地主呢?我经常看到帖子上说或者论坛上大家在讨论程序员在外包公司工作怎么样?福利待遇好吗?工作累吗?上班时间怎么样?等等总之一堆一堆的,现在下班回家闲来无事,我就来说说在外包公司工作到底怎么样?是一种什么样的感觉?大家想不想听呢?那就让我慢慢道来…  &n

  • android缩放动画中心缩放_缩放动画

    android缩放动画中心缩放_缩放动画ScaleAnimation:缩放动画同样,创建ScaleAnimation也有两种方式XML文件+Java代码Java代码方式XML文件+Java代码效果图:文件目录:res/anim/scale.xml

    2022年10月15日
  • 智能窗帘研究制作_智能窗帘的制作方法[通俗易懂]

    智能窗帘研究制作_智能窗帘的制作方法[通俗易懂]步骤1:所需组件:IntelGalileox1IntelGalileox1的电源线LDRx1220ohm电阻x18.2Kohm电阻器x1蓝牙模块(HC-05)x19V电池x19V电池适配器x1电动机驱动器x1迷你-面包板x1连接线(公对公))x40连接线(公对母)x40步骤2:将LDR和220ohm电阻与IntelGalileo接口LDRLDR扩展为光敏电阻。根据投射到LDR表面的光强度,它会改变…

  • 计算机网络 | 一文搞懂什么是TCP/IP协议[通俗易懂]

    什么是TCP/IP协议?计算机与网络设备之间如果要相互通信,双方就必须基于相同的方法.比如如何探测到通信目标.由哪一边先发起通信,使用哪种语言进行通信,怎样结束通信等规则都需要事先确定.不同的硬件,操作系统之间的通信,所有这一切都需要一种规则.而我们就将这种规则称为协议(protocol).也就是说,TCP/IP是互联网相关各类协议族的总称。TCP/IP的分层管理TCP/IP协…

  • wmv转换mp4格式转换器_avi可以转化成什么格式

    wmv转换mp4格式转换器_avi可以转化成什么格式MP4的视频H264封装有2种格式:h264和avc1,对于这个细节,很容易被忽略。笔者也是在改编LIVE555流媒体时,增加mp4文件类型支持时遇到了该问题。(一)首先,从原理上了解一下这2种格式的区别:AVC1描述:H.264bitstreamwithoutstartcodes.一般通过ffmpeg转码生成的视频,是不带起始码0×00000001的。H264描述:H.26

    2022年10月16日
  • JS实现常见数据结构:哈希表[通俗易懂]

    哈希表特点:存储键值对的数据结构,哈希表内部是使用一个hash函数把传入的键转换成一串数字,而这串数字将作为键值对实际的key,通过这个key查询对应的value非常快。哈希表方法:1.add:添加一组键值对。2.remove:删除一组键值对。3.lookup:查找一个键对应的值。

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号