3D游戏编程与设计10——游戏智能
程序员文章站
2022-07-13 09:58:57
...
3、P&D 过河游戏智能帮助实现,程序具体要求:
- 实现状态图的自动生成
- 讲解图数据在程序中的表示方法
- 利用算法实现下一步的计算
- 参考:P&D 过河游戏智能帮助实现
状态图:
其中,每个状态记录了位于右岸的牧师与恶魔数量,P 代表牧师,D 代表恶魔,B 代表船在右边。改变状态的动作有五个:PP(两个牧师过河)、PD(一个牧师和一个恶魔过河)、DD(两个恶魔过河)、P(一个牧师过河)、D(一个恶魔过河)。
在程序中用三个变量来表示游戏状态:
public bool boat_is_right = true; //记录船的位置
public int right_devil_count; //记录右岸恶魔数量
public int right_priest_count; //记录右岸牧师数量
实现 AI 的基本原理是:点击 next 之后,分析当前场景的状态,读取成功路径上的下一个状态,执行相应动作以达到下一个状态。具体实现如下:
void Next()
{
//重置船上角色
if (left_type == "devil")
{
Devilaction.devil_move(left_on_boat);
}
else if (left_type == "priest")
{
Priestaction.priest_move(left_on_boat);
}
if (right_type == "devil")
{
Devilaction.devil_move(right_on_boat);
}
else if (right_type == "priest")
{
Priestaction.priest_move(right_on_boat);
}
if (boat_is_right)
{
if (right_devil_count == 3 && right_priest_count == 3)//3P3DB
{
Devilaction.devil_move(devil1);
Priestaction.priest_move(priest1);
Boataction.boat_move(boat);
landing = true;
}
else if (right_devil_count == 2 && right_priest_count == 3)//3P2DB
{
if (devil1.transform.position.x >= 6)
{
Devilaction.devil_move(devil1);
}
if (devil2.transform.position.x >= 6)
{
Devilaction.devil_move(devil2);
}
if (devil3.transform.position.x >= 6)
{
Devilaction.devil_move(devil3);
}
Boataction.boat_move(boat);
landing = true;
}
else if (right_devil_count == 1 && right_priest_count == 3)//3P1DB
{
if (priest1.transform.position.x >= 6)
{
Priestaction.priest_move(priest1);
}
if (priest2.transform.position.x >= 6)
{
Priestaction.priest_move(priest2);
}
if (priest3.transform.position.x >= 6)
{
Priestaction.priest_move(priest3);
}
Boataction.boat_move(boat);
landing = true;
}
else if (right_devil_count == 2 && right_priest_count == 2)//2P2DB
{
if (priest1.transform.position.x >= 6)
{
Priestaction.priest_move(priest1);
}
if (priest2.transform.position.x >= 6)
{
Priestaction.priest_move(priest2);
}
if (priest3.transform.position.x >= 6)
{
Priestaction.priest_move(priest3);
}
Boataction.boat_move(boat);
landing = true;
}
else if (right_devil_count == 3 && right_priest_count == 0)//3DB
{
Devilaction.devil_move(devil1);
Devilaction.devil_move(devil2);
Boataction.boat_move(boat);
landing = true;
}
else if (right_devil_count == 1 && right_priest_count == 1)//1P1DB
{
if (priest1.transform.position.x >= 6)
{
Priestaction.priest_move(priest1);
}
else if (priest2.transform.position.x >= 6)
{
Priestaction.priest_move(priest2);
}
else if (priest3.transform.position.x >= 6)
{
Priestaction.priest_move(priest3);
}
if (devil1.transform.position.x >= 6)
{
Devilaction.devil_move(devil1);
}
else if (devil2.transform.position.x >= 6)
{
Devilaction.devil_move(devil2);
}
else if (devil3.transform.position.x >= 6)
{
Devilaction.devil_move(devil3);
}
Boataction.boat_move(boat);
landing = true;
}
else if (right_devil_count == 2 && right_priest_count == 0)//2DB
{
if (devil1.transform.position.x >= 6)
{
Devilaction.devil_move(devil1);
}
if (devil2.transform.position.x >= 6)
{
Devilaction.devil_move(devil2);
}
if (devil3.transform.position.x >= 6)
{
Devilaction.devil_move(devil3);
}
Boataction.boat_move(boat);
landing = true;
}
}
else
{
if (right_devil_count == 2 && right_priest_count == 2)//2P2D
{
if (priest1.transform.position.x <= -6)
{
Priestaction.priest_move(priest1);
}
else if (priest2.transform.position.x <= -6)
{
Priestaction.priest_move(priest2);
}
else if (priest3.transform.position.x <= -6)
{
Priestaction.priest_move(priest3);
}
Boataction.boat_move(boat);
landing = true;
}
else if (right_devil_count == 3 && right_priest_count == 1)//3P1D
{
if (devil1.transform.position.x <= -6)
{
Devilaction.devil_move(devil1);
}
else if (devil2.transform.position.x <= -6)
{
Devilaction.devil_move(devil2);
}
else if (devil3.transform.position.x <= -6)
{
Devilaction.devil_move(devil3);
}
Boataction.boat_move(boat);
landing = true;
}
else if (right_devil_count == 2 && right_priest_count == 3)//3P2D
{
if (devil1.transform.position.x <= -6)
{
Devilaction.devil_move(devil1);
}
else if (devil2.transform.position.x <= -6)
{
Devilaction.devil_move(devil2);
}
else if (devil3.transform.position.x <= -6)
{
Devilaction.devil_move(devil3);
}
Boataction.boat_move(boat);
landing = true;
}
else if (right_devil_count == 0 && right_priest_count == 3)//3P
{
Devilaction.devil_move(devil1);
Boataction.boat_move(boat);
landing = true;
}
else if (right_devil_count == 1 && right_priest_count == 1)//1P1D
{
if (devil1.transform.position.x <= -6)
{
Devilaction.devil_move(devil1);
}
else if (devil2.transform.position.x <= -6)
{
Devilaction.devil_move(devil2);
}
else if (devil3.transform.position.x <= -6)
{
Devilaction.devil_move(devil3);
}
if (priest1.transform.position.x <= -6)
{
Priestaction.priest_move(priest1);
}
else if (priest2.transform.position.x <= -6)
{
Priestaction.priest_move(priest2);
}
else if (priest3.transform.position.x <= -6)
{
Priestaction.priest_move(priest3);
}
Boataction.boat_move(boat);
landing = true;
}
else if (right_devil_count == 2 && right_priest_count == 0)//2D
{
if (devil1.transform.position.x <= -6)
{
Devilaction.devil_move(devil1);
}
else if (devil2.transform.position.x <= -6)
{
Devilaction.devil_move(devil2);
}
else if (devil3.transform.position.x <= -6)
{
Devilaction.devil_move(devil3);
}
Boataction.boat_move(boat);
landing = true;
}
else if (right_devil_count == 1 && right_priest_count == 0)//1D
{
Priestaction.priest_move(priest1);
Boataction.boat_move(boat);
landing = true;
}
}
}
在 OnGUI 函数中增加 Next 按钮,具体实现如下:
void OnGUI()
{
GUI.Box(new Rect(Screen.width / 2 - 75, 10, 150, 40), "Left Time: \n" + time.ToString());
if (GUI.Button(new Rect(Screen.width / 2 - 75, 350, 150, 40), "Next"))
{
Next();
}
if (game_over)
{
GUI.Window(0, new Rect(Screen.width / 2 - Screen.width / 12, Screen.height / 2 - Screen.height / 12, Screen.width / 6, Screen.height / 6), game_over_window, "Game Over!");
}
if (win)
{
GUI.Window(0, new Rect(Screen.width / 2 - Screen.width / 12, Screen.height / 2 - Screen.height / 12, Screen.width / 6, Screen.height / 6), win_window, "You Win!");
}
}