游戏编程中的人工智能技术-神经网络入门(三)

    前两节提到了神经网络部分和遗传算法部分,那么代码就到此结束了吗?当然没有,无论什么算法,总要针对一个特定的对象进行使用不是?因此,本节介绍另一个部分,CMinesweeper,即扫雷机代码。
class CMinesweeper
{

private:

  //the minesweeper's neural net
  CNeuralNet		m_ItsBrain;//扫雷机的大脑,在这里就是一个神经网络

	//its position in the world
	SVector2D		m_vPosition;//扫雷机的位置,用一个二维坐标表示

	//direction sweeper is facing
	SVector2D		m_vLookAt;//扫雷机的朝向,用一个二维向量表示,注意这个向量是物理中的向量

	//its rotation (surprise surprise)
	double			m_dRotation;//扫雷机的旋转速度??

	double			m_dSpeed;//扫雷机的速度

	//to store output from the ANN
	double			m_lTrack, m_rTrack;//扫雷机左、右轮速度,这里即是神经网络的输出

	//the sweeper's fitness score 
	double			m_dFitness;//扫雷机的适应度函数,算法好坏的关键在于适应度函数的设计!

	//the scale of the sweeper when drawn
	double			m_dScale;// 变比

  //index position of closest mine
  int         m_iClosestMine;//距离扫雷机最近的地雷
  

public:


	CMinesweeper();//构造函数
	
	//updates the ANN with information from the sweepers enviroment
	bool			Update(vector<SVector2D> &mines);//具体见update函数

	//used to transform the sweepers vertices prior to rendering
  void			WorldTransform(vector<SPoint> &sweeper);

	//returns a vector to the closest mine
  SVector2D	GetClosestMine(vector<SVector2D> &objects);

  //checks to see if the minesweeper has 'collected' a mine
  int       CheckForMine(vector<SVector2D> &mines, double size);

	void			Reset();
  

	//-------------------accessor functions
	SVector2D	Position()const{return m_vPosition;}

	void			IncrementFitness(){++m_dFitness;}

	void			DecrementFitness(){--m_dFitness;}//这个是我自己加的,现在没什么用

	double		Fitness()const{return m_dFitness;}
  
  void      PutWeights(vector<double> &w){m_ItsBrain.PutWeights(w);}

  int       GetNumberOfWeights()const{return m_ItsBrain.GetNumberOfWeights();}
};

其中的子函数较多。现一一介绍。

(1)扫雷机的更新函数update(),主要根据扫雷机的输入经过神经网络的输出,来更新扫雷机的速度和位置信息。

bool CMinesweeper::Update(vector<SVector2D> &mines)
{
	
	//this will store all the inputs for the NN
	vector<double> inputs;	//用来储存输入

	//get vector to closest mine
	SVector2D vClosestMine = GetClosestMine(mines);//找到与扫雷机最近的地雷
  
	//normalise it
  Vec2DNormalize(vClosestMine);//距离归一化
  
  //add in vector to closest mine
	inputs.push_back(vClosestMine.x);//四个输入之一:地雷的x坐标
	inputs.push_back(vClosestMine.y);//四个输入之二:地雷的y坐标

	//add in sweepers look at vector
	inputs.push_back(m_vLookAt.x);//四个输入之三:扫雷机朝向的x坐标
	inputs.push_back(m_vLookAt.y);//四个输入之四:扫雷机朝向的y坐标

  
	//update the brain and get feedback
	vector<double> output = m_ItsBrain.Update(inputs);//注意, m_ItsBrain是神经网络的实例
													//因此,这个update是神经网络的update
													//inputs就是上面的那四个输入

	//make sure there were no errors in calculating the 
	//output
	if (output.size() < CParams::iNumOutputs) 
  {
    return false;
  }

	//assign the outputs to the sweepers left & right tracks
	m_lTrack = output[0];//输出之一,左轮速度
	m_rTrack = output[1];//输出之二,右轮速度

	//calculate steering forces
	double RotForce = m_lTrack - m_rTrack;//转向力

	//clamp rotation
	Clamp(RotForce, -CParams::dMaxTurnRate, CParams::dMaxTurnRate);

  m_dRotation += RotForce;//转向力的积分,那就是转向速度了
	
	m_dSpeed = (m_lTrack + m_rTrack);//扫雷机的实际速度为左右轮速之和	

	//update Look At 
	m_vLookAt.x = -sin(m_dRotation);//更新朝向
	m_vLookAt.y = cos(m_dRotation);

	//update position
  m_vPosition += (m_vLookAt * m_dSpeed);//更新位置

	//wrap around window limits
	if (m_vPosition.x > CParams::WindowWidth) m_vPosition.x = 0;//设定超出边界该怎么办
	if (m_vPosition.x < 0) m_vPosition.x = CParams::WindowWidth;
	if (m_vPosition.y > CParams::WindowHeight) m_vPosition.y = 0;
	if (m_vPosition.y < 0) m_vPosition.y = CParams::WindowHeight;

	return true;
}
(2)矩阵变换函数

void CMinesweeper::WorldTransform(vector<SPoint> &sweeper)
{
	//create the world transformation matrix
	C2DMatrix matTransform;
	
	//scale
	matTransform.Scale(m_dScale, m_dScale);
	
	//rotate
	matTransform.Rotate(m_dRotation);
	
	//and translate
	matTransform.Translate(m_vPosition.x, m_vPosition.y);
	
	//now transform the ships vertices
	matTransform.TransformSPoints(sweeper);
}
关于这方面的介绍,详见本书第六章:登月也不难。其实就是一些矩阵的变换

(3)找到最近的地雷:GetClosestMine(vector<SVector2D> &mines)

SVector2D CMinesweeper::GetClosestMine(vector<SVector2D> &mines)
{
	double			closest_so_far = 99999;

	SVector2D		vClosestObject(0, 0);

	//cycle through mines to find closest
	for (int i=0; i<mines.size(); i++)
	{
		double len_to_object = Vec2DLength(mines[i] - m_vPosition);

		if (len_to_object < closest_so_far)
		{
			closest_so_far	= len_to_object;
			
			vClosestObject	= m_vPosition - mines[i];

      m_iClosestMine = i;
		}
	}

	return vClosestObject;
}
这个函数也不难,就是通过遍历和排序找到距离最近的地雷。

(4)检测是否碰到了地雷

int CMinesweeper::CheckForMine(vector<SVector2D> &mines, double size)
{
  SVector2D DistToObject = m_vPosition - mines[m_iClosestMine];
		
	if (Vec2DLength(DistToObject) < (size + 5))
	{
			return m_iClosestMine;
  }

  return -1;
}
这些都不难,随便看看都能懂,就不一一注释了。



你可能感兴趣的:(人工智能,神经网络)