Unity3D课程——游戏智能之牧师与魔鬼智能提示版

状态分析

  • 首先列出可能的情况,即船上和其所靠岸上的Role,以PXDX形式表示,P代表牧师,其后面的X代表牧师的数量,D为恶魔,其后X同理
  • 先排除不可能的情况,例如P0D0,因为船必须有Role在上面才能开动,而P0D0显然不合理;再比如P1D2,牧师少于恶魔则游戏结束,所以也不可能
  • 综上,可以得到可能的情况有八种:
    • P0D1
    • P0D2
    • P0D3
    • P1D1
    • P2D2
    • P3D1
    • P3D2
    • P3D3
  • 其中每种情况又分为在初始岸边和目的岸边,在不同的岸边下一步的选择也不同,根据上面八种情况,可以得到以下状态图
    在这里插入图片描述

其中状态为船只停靠岸的Role情况,船的移动就是状态的转换,该图涵盖了所有可能情况,根据该图实现代码即可

代码实现

  • 枚举五种输入(导致状态改变),其中End代表结束,INVALID表示当前输入非法
enum MoveStrategy { P1D0, P2D0, P1D1, P0D1, P0D2, END, INVALID}
  • 根据当前状态得到下一步正确的输入,函数返回值为输入,即船上应该载的Role;当船在移动时该函数返回INVALID
MoveStrategy getNextMoveStratrgy() {
		int[] boat_roles = boat.getRolesNum();
		int[] total = new int[2];       //船和其停靠岸边一共有的角色

		//在初始岸边
		if (boat.getPos() == 0) {
			int[] src_roles = src.getRolesNum();
			for (int i = 0; i < 2; i++)
				total[i] = boat_roles[i] + src_roles[i];

			if (total[0] == 0 && total[1] == 1)
				return MoveStrategy.P0D1;
			else if (total[0] == 0 && total[1] == 2)
				return MoveStrategy.P0D2;
			else if (total[0] == 0 && total[1] == 3)
				return MoveStrategy.P0D2;
			else if (total[0] == 1 && total[1] == 1)
				return MoveStrategy.P1D1;
			else if (total[0] == 2 && total[1] == 2)
				return MoveStrategy.P2D0;
			else if (total[0] == 3 && total[1] == 1)
				return MoveStrategy.P2D0;
			else if (total[0] == 3 && total[1] == 2)
				return MoveStrategy.P0D2;
			else if (total[0] == 3 && total[1] == 3)
				return MoveStrategy.P0D2;
			else
				return MoveStrategy.INVALID;
		}
		else if (boat.getPos() == 2) {
			int[] dst_roles = dst.getRolesNum();
			for (int i = 0; i < 2; i++)
				total[i] = boat_roles[i] + dst_roles[i];

			if (total[0] == 0 && total[1] == 1)
				return MoveStrategy.P0D1;
			else if (total[0] == 0 && total[1] == 2)
				return MoveStrategy.P0D1;
			else if (total[0] == 0 && total[1] == 3)
				return MoveStrategy.P0D1;
			else if (total[0] == 1 && total[1] == 1)
				return MoveStrategy.P1D0;
			else if (total[0] == 2 && total[1] == 2)
				return MoveStrategy.P1D1;
			else if (total[0] == 3 && total[1] == 1)
				return MoveStrategy.P0D1;
			else if (total[0] == 3 && total[1] == 2)
				return MoveStrategy.P0D1;
			else if (total[0] == 3 && total[1] == 3)
				return MoveStrategy.END;
			else
				return MoveStrategy.INVALID;
		}
		else
			return MoveStrategy.INVALID;
	}
  • 对得到的MoveStrategy数据类型进行处理,根据船上已有的Role对船上和岸上的Role进行移动
public void nextStep() {
		MoveStrategy strategy = getNextMoveStratrgy();
		int[] boat_roles = boat.getRolesNum();
		int[] right_boat = new int[2];
		if (strategy == MoveStrategy.P0D1) {
			right_boat[0] = 0;
			right_boat[1] = 1;
		}
		else if (strategy == MoveStrategy.P0D2) {
			right_boat[0] = 0;
			right_boat[1] = 2;
		}
		else if (strategy == MoveStrategy.P1D1) {
			right_boat[0] = 1;
			right_boat[1] = 1;
		}
		else if (strategy == MoveStrategy.P1D0) {
			right_boat[0] = 1;
			right_boat[1] = 0;
		}
		else if (strategy == MoveStrategy.P2D0) {
			right_boat[0] = 2;
			right_boat[1] = 0;
		}
		else if(strategy == MoveStrategy.END) {
			right_boat[0] = 0;
			right_boat[1] = 0;
		}
		else
			return;

		int need_p = right_boat[0] - boat_roles[0];		//船上还需要的牧师数量
		int need_d = right_boat[1] - boat_roles[1];     //船上还需要的魔鬼数量
		
		while(need_p < 0) {
			MoveRole(boat.getRole(1));
			need_p++;
		}
		while (need_d < 0) {
			MoveRole(boat.getRole(2));
			need_d++;
		}
		if (boat.getPos() == 0) {
			while (need_p > 0) {
				MoveRole(src.getRole(1));
				need_p--;
			}
			while (need_d > 0) {
				MoveRole(src.getRole(2));
				need_d--;
			}
		}
		else if (boat.getPos() == 2) {
			while (need_p > 0) {
				MoveRole(dst.getRole(1));
				need_p--;
			}
			while (need_d > 0) {
				MoveRole(dst.getRole(2));
				need_d--;
			}
		}
	}
  • nextStep中的getRole函数是此次实验新添加的,其在BoatModel和CoastModel中定义,用于寻找所需类型的Role,其实现如下:
public RoleModel getRole(int flag) {
		for (int i = 0; i < passenger.Length; i++) {
				if (passenger[i] != null && passenger[i].getFlag() == flag) 
						return passenger[i];
		}
		return null;
}

public RoleModel getRole(int flag) {
		for (int i = 0; i < empty.Length; i++) {
				if (empty[i] != null && empty[i].getFlag() == flag)
					  return empty[i];
		}
		return null;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值