游戏智能
P&D 过河游戏智能帮助实现,程序具体要求:
- 实现状态图的自动生成
- 讲解图数据在程序中的表示方法
- 利用算法实现下一步的计算
- 参考:P&D 过河游戏智能帮助实现
代码原理
本次游戏基于之前的Priests&Devils过河小游戏。在原先的基础上增加了”AI Move”,能够提示用户进行正确的操作。
基本原理是:根据当前左岸上的牧师和恶魔数量以及船停靠的位置来判断下一步动作。
状态转换
状态转换图如下图所示:
相应代码如下:
采用P_D[]来记录要移动的角色。P_D[0]是要向对岸移动的牧师的数量。P_D[1]是要向对岸移动的恶魔的数量。
1 | using UnityEngine; |
AI Move原理
AI Move 运行原理为:
点击按钮后,首先判断当前游戏状态。若游戏没有结束,则读取当前岸上的各个角色和船的位置,根据状态图找到下一动作进行执行。
判断当前游戏状态
1
2
3int flag = judge.check();
if (flag == 1 || flag ==2)
return;获取from岸上的牧师数量和恶魔数量
int numDevilLeft = judge.from_devil, numPriestLeft = judge.from_priest;
获取船的位置
int boatPos = boat.get_is_from();
输入状态,获取下一步动作
1
2
3
4Debug.Log("State:"+numDevilLeft+" "+numPriestLeft+" "+boat.get_is_from());
int[] P_D = agent.getAIaction(numDevilLeft, numPriestLeft, boat.get_is_from());
Debug.Log("P_D[0] " + P_D[0]);
Debug.Log("P_D[1] " + P_D[1]);人从船上上岸的过程
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44int numPriestToBoat = 0, numDevilToBoat = 0;
int[] personOnBoat = boat.getPersonOnBoat();
Debug.Log("Boat0 "+personOnBoat[0]+" boat1"+personOnBoat[1]);
if (personOnBoat[0] >= 3 && personOnBoat[0] <= 6)
{
if (P_D[0] > 0)
numPriestToBoat++;
else if (P_D[0] == 0)
{
Debug.Log("getoff P"+personOnBoat[0]);
moveCharacter(characters[personOnBoat[0]]);
}
}
else if (personOnBoat[0] >= 0 && personOnBoat[0] <= 2)
{
if (P_D[1] > 0)
numDevilToBoat++;
else if (P_D[1] == 0)
{
Debug.Log("getoff D"+personOnBoat[0]);
moveCharacter(characters[personOnBoat[0]]);
}
}
if (personOnBoat[1] >= 3 && personOnBoat[1] <= 6)
{
if (P_D[0] == 2 || (P_D[0] == 1 && numPriestToBoat == 0))
numPriestToBoat++;
else if (P_D[0] == 0 || (P_D[0] == 1 && numPriestToBoat == 1))
{
Debug.Log("getoff P"+personOnBoat[1]);
moveCharacter(characters[personOnBoat[1]]);
}
}
else if (personOnBoat[1] >= 0 && personOnBoat[1] <= 2)
{
if (P_D[1] == 2 || (P_D[1] == 1 && numDevilToBoat == 0))
numDevilToBoat++;
else if (P_D[1] == 0 || (P_D[1] == 1 && numDevilToBoat == 1))
{
Debug.Log("getoff D"+personOnBoat[1]);
moveCharacter(characters[personOnBoat[1]]);
}
}人从岸边上船的过程
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21for (int i = 0; i < P_D[0] - numPriestToBoat; i++)
{
int index = -1;
if (boatPos == 1)
index = fromCoast.getAPriestIndex();
else if (boatPos == -1)
index = toCoast.getAPriestIndex();
Debug.Log("geton P"+index);
moveCharacter(characters[index]);
}
for (int i = 0; i < P_D[1] - numDevilToBoat; i++)
{
int index = -1;
if (boatPos == 1)
index = fromCoast.getADevilIndex();
else if (boatPos == -1)
index = toCoast.getADevilIndex();
Debug.Log("geton D"+index);
moveCharacter(characters[index]);
}
接口处理
在智能动作函数中传递的参数都是角色的下标。所以对角色控制器添加index属性。
修改构造函数如下
1
2
3
4
5
6
7
8
9
10
11
12
13public CharacterController(string name,int t){
if(name == "priest"){
character = Object.Instantiate(Resources.Load("Prefab/priest",typeof(GameObject)),Vector3.zero,Quaternion.identity,null) as GameObject;
is_devil = false;
}else if(name == "devil"){
character = Object.Instantiate(Resources.Load("Prefab/devil",typeof(GameObject)),Vector3.zero,Quaternion.identity,null) as GameObject;
is_devil = true;
}
index = t;
move = character.AddComponent(typeof(Move))as Move;
click = character.AddComponent(typeof(UserClick))as UserClick;
click.setController(this);
}添加返回index函数
1
2
3
4public int getCharacterIndex()
{
return index;
}
传递在岸上的角色的下标
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27public int getAPriestIndex()
{
for (int i = 0; i < characters.Length; i++)
{
if (characters [i] == null)
continue;
if (!characters[i].Is_Devil())
return characters[i].getCharacterIndex();
else
continue;
}
return -1;
}
public int getADevilIndex()
{
for (int i = 0; i < characters.Length; i++)
{
if (characters [i] == null)
continue;
if (characters[i].Is_Devil())
return characters[i].getCharacterIndex();
else
continue;
}
return -1;
}
传递在船上角色的下标
1
2
3
4
5
6
7
8
9
10
11
12public int[] getPersonOnBoat()
{
int[] result = new int[2];
for (int i = 0; i < 2; i++)
{
if (characters [i] == null)
result[i] = -1;
else
result[i] = characters[i].getCharacterIndex();
}
return result;
}
效果展示
游戏界面:
游戏视频:
项目地址: