• 游戏中的有限状态机 (StateMachine)


    /**
     * 状态机的组成主要是:状态机框架对象(我程序代码中的StateMachine)状态机中的三种状态eat,work,sleep
     * 状态机负责指挥这三种状态(甚至更多种状态)的变换,让他们是按照一定的先后顺序来走,符合我们的预期目的。
     * 然后就是到底谁需要使用状态机呢,我程序里面有2个对象用到了状态机,分别是vokie和NBA.
     * 他们是通过"sm = new StateMachine(this);"这样一句代码来实现对状态机的绑定,
     * 他们各自拥有一个状态机,不过我这里偷懒了,用了很蹩脚的instanceof方法来做的,其实可以写成2个状态机
     * 绑定以后,我们就可以在eat,work,sleep中处理Person跟Team对象了。
     * @author Administrator
     *
     */


    首先是可能存在的状态的接口定义:(基本的流程)

    public interface IState {
    	public void enter(Object o);
    	public void excute(Object o);
    	public void exit(Object o);
    }
    

    状态机中包含的三种状态定义:

    /**
     * 吃饭状态机,任何绑定使用该状态机的对象(Person Team)都可以在StateMachine的指导下、完成吃饭状态
     *
     */
    
    public class EatState implements IState{
    	public EatState() {
    	}
    
    	@Override
    	public void enter(Object obj) {
    		if(obj instanceof Person)
    		{
    			Person p = (Person)obj;
    			System.out.println("Eat-1:煮饭~   执行者:"+p.getName());
    		}else{
    			Team t = (Team)obj;
    			System.out.println("Eat-1:煮饭~   执行者:"+t.getName());
    		}
    	}
    
    	@Override
    	public void excute(Object obj) {
    		if(obj instanceof Person)
    		{
    			Person p = (Person)obj;
    			System.out.println("Eat-2:吃饭~   执行者:"+p.getName());
    		}else{
    			Team t = (Team)obj;
    			System.out.println("Eat-2:吃饭~   执行者:"+t.getName());
    		}
    	}
    
    	@Override
    	public void exit(Object obj) {
    		if(obj instanceof Person)
    		{
    			Person p = (Person)obj;
    			System.out.println("Eat-3:洗碗~   执行者:"+p.getName());
    		}else{
    			Team t = (Team)obj;
    			System.out.println("Eat-3:洗碗~   执行者:"+t.getName());
    		}
    	}
    }
    
    public class WorkState implements IState{
    	public WorkState() {
    	}
    
    	@Override
    	public void enter(Object obj) {
    		if(obj instanceof Person)
    		{
    			Person p = (Person)obj;
    			System.out.println("work-1:上班~   执行者:"+p.getName());
    		}else{
    			Team t = (Team)obj;
    			System.out.println("work-1:上班~   执行者:"+t.getName());
    		}
    	}
    
    	@Override
    	public void excute(Object obj) {
    		if(obj instanceof Person)
    		{
    			Person p = (Person)obj;
    			System.out.println("work-2:工作~   执行者:"+p.getName());
    		}else{
    			Team t = (Team)obj;
    			System.out.println("work-2:工作~   执行者:"+t.getName());
    		}
    	}
    
    	@Override
    	public void exit(Object obj) {
    		if(obj instanceof Person)
    		{
    			Person p = (Person)obj;
    			System.out.println("work-3:下班~   执行者:"+p.getName());
    		}else{
    			Team t = (Team)obj;
    			System.out.println("work-3:下班~   执行者:"+t.getName());
    		}
    	}
    }
    
    public class SleepState implements IState{
    	public SleepState() {
    	}
    
    	@Override
    	public void enter(Object obj) {
    		if(obj instanceof Person)
    		{
    			Person p = (Person)obj;
    			System.out.println("Sleep-1:关灯~   执行者:"+p.getName());
    		}else{
    			Team t = (Team)obj;
    			System.out.println("Sleep-1:关灯~   执行者:"+t.getName());
    		}
    	}
    
    	@Override
    	public void excute(Object obj) {
    		if(obj instanceof Person)
    		{
    			Person p = (Person)obj;
    			System.out.println("Sleep-2:睡觉~   执行者:"+p.getName());
    		}else{
    			Team t = (Team)obj;
    			System.out.println("Sleep-2:睡觉~   执行者:"+t.getName());
    		}
    	}
    
    	@Override
    	public void exit(Object obj) {
    		if(obj instanceof Person)
    		{
    			Person p = (Person)obj;
    			System.out.println("Sleep-3:起床~   执行者:"+p.getName());
    		}else{
    			Team t = (Team)obj;
    			System.out.println("Sleep-3:起床~   执行者:"+t.getName());
    		}
    	}
    }
    


    需要使用到状态机的对象:Person & Team

    public class Person {
    	private String name;
    	
    	private StateMachine sm;
    	
    	public Person(String name) {
    		this.name = name;
    		sm = new StateMachine(this);
    		sm.setState(new WorkState());
    		sm.getState().enter(this);
    	}
    
    	public StateMachine getStateMachine()
    	{
    		return sm;
    	}
    
    	public String getName() {
    		// TODO Auto-generated method stub
    		return name;
    	}
    }
    
    import java.util.ArrayList;
    
    public class Team {
    	private ArrayList<String> nameList = new ArrayList<String>();
    	
    	private StateMachine sm;
    	
    	public Team(ArrayList<String> nameList) {
    		this.nameList = nameList;
    		sm = new StateMachine(this);
    		sm.setState(new WorkState());
    		sm.getState().enter(this);
    	}
    
    	public StateMachine getStateMachine()
    	{
    		return sm;
    	}
    
    	public String getName() {
    		StringBuilder sb = new StringBuilder();
    		for(String str:nameList)
    			sb.append("  |  ").append(str);
    		return sb.toString();
    	}
    }
    

    然后是状态机这个大框架:

    /**
     * 从一种状态向另一种状态的转移,最常见的就是操作系统里面的状态图,游戏中也经常用到关于状态图
     * 比如游戏中篮球运动员投篮的一套动作流程:运球->急停->起跳->投篮.
     * 我这里用例是人一天的作息状态转换:工作->吃饭->休息
     */
    class StateMachine
    {
    	public IState currentState;  //当前正在执行的状态
    	public IState previousState;  //前一个状态
    	public Object owner;  //状态机的拥有者,也就是说明该对象需要使用状态机的机制
    	public StateMachine(Object t_obj)
        {
        	owner = t_obj;
        	currentState = null;
        	previousState = null;
        }
    
        public boolean excute()
        {
        	if(currentState != null)
         	{
            	currentState.excute(owner);
            	return true;
        	}
        	return false;
        }
    
        //状态机改变状态
        public boolean changeState(IState newState)
        {
        	if(newState == null)
        	{
            	return false;
        	}
        	previousState = currentState;   //保存当前的状态
        	currentState.exit(owner);   //退出当前状态
        	currentState = newState;
        	currentState.enter(owner);  //进入新的状态
         	return true;
        }
    
        public boolean reverseToPreviousState()
        {
        	return changeState(previousState);
        }
        
        public void setState(IState state)
        {
        	currentState = state;
        }
        
        public IState getState()
        {
        	return currentState;
        }
    }

    最后是测试代码:

    import java.util.ArrayList;
    
    public class Demo {
    	public static void main(String[] args) {
    		Person vokie = new Person("vokie");
    		
    		//执行工作状态机的excute方法
    		vokie.getStateMachine().excute();
    		//传入SleeState,让SleepState来处理person类中的变量等等
    		vokie.getStateMachine().changeState(new SleepState());
    		vokie.getStateMachine().excute();
    		vokie.getStateMachine().changeState(new EatState());
    		vokie.getStateMachine().excute();
    		vokie.getStateMachine().changeState(new WorkState());
    		vokie.getStateMachine().excute();
    		vokie.getStateMachine().changeState(new SleepState());
    		
    		//下面测试代码的作用是想表达的是:状态机可以处理其拥有者owner的逻辑,变量
    		ArrayList<String> nameList = new ArrayList<String>();
    		nameList.add("Smith");
    		nameList.add("Kobe");
    		nameList.add("James");
    		Team NBA = new Team(nameList);
    		NBA.getStateMachine().excute();
    		//传入SleepState,让SleepState来处理Team类中的所有成员
    		NBA.getStateMachine().changeState(new SleepState());
    		NBA.getStateMachine().excute();
    		NBA.getStateMachine().changeState(new EatState());
    		NBA.getStateMachine().excute();
    		NBA.getStateMachine().changeState(new WorkState());
    		NBA.getStateMachine().excute();
    		NBA.getStateMachine().changeState(new SleepState());
    	}
    }
    


    运行结果:

    work-1:上班~   执行者:vokie
    work-2:工作~   执行者:vokie
    work-3:下班~   执行者:vokie
    Sleep-1:关灯~   执行者:vokie
    Sleep-2:睡觉~   执行者:vokie
    Sleep-3:起床~   执行者:vokie
    Eat-1:煮饭~   执行者:vokie
    Eat-2:吃饭~   执行者:vokie
    Eat-3:洗碗~   执行者:vokie
    work-1:上班~   执行者:vokie
    work-2:工作~   执行者:vokie
    work-3:下班~   执行者:vokie
    Sleep-1:关灯~   执行者:vokie
    work-1:上班~   执行者:  |  Smith  |  Kobe  |  James
    work-2:工作~   执行者:  |  Smith  |  Kobe  |  James
    work-3:下班~   执行者:  |  Smith  |  Kobe  |  James
    Sleep-1:关灯~   执行者:  |  Smith  |  Kobe  |  James
    Sleep-2:睡觉~   执行者:  |  Smith  |  Kobe  |  James
    Sleep-3:起床~   执行者:  |  Smith  |  Kobe  |  James
    Eat-1:煮饭~   执行者:  |  Smith  |  Kobe  |  James
    Eat-2:吃饭~   执行者:  |  Smith  |  Kobe  |  James
    Eat-3:洗碗~   执行者:  |  Smith  |  Kobe  |  James
    work-1:上班~   执行者:  |  Smith  |  Kobe  |  James
    work-2:工作~   执行者:  |  Smith  |  Kobe  |  James
    work-3:下班~   执行者:  |  Smith  |  Kobe  |  James
    Sleep-1:关灯~   执行者:  |  Smith  |  Kobe  |  James
    


  • 相关阅读:
    itextpdf 和 pdfbox 测试用例
    Java base64 编码、解码
    常用字体
    DIY 单片机 入门
    太难了。
    Java 之 native:JNI 本地方法测试实现
    Java 之 String 引用传递
    Java class 文件 方法的指令含义
    Spring学习文章链接
    数据结构_树_图_总结
  • 原文地址:https://www.cnblogs.com/vokie/p/3602068.html
Copyright © 2020-2023  润新知