游戏中的有限状态机 (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