⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 statistfire.cpp

📁 AI-CODE坦克机器人 《C++语言学习利器 —AI-CODE坦克机器人》-杜飞雪-源代码
💻 CPP
字号:
#include <airobot/cpp/SimpleRobot.hpp>

/**
 * 概率
 * @author xiemin
 */
class Statist
{
	private:
		//角度的间隔
		static const double GAP;
		//概率分布数组的大小
		enum { FACTOR_SIZE = 30 };  
		//概率分布数组
		double factors[FACTOR_SIZE];
	
	public:		
		/*
		 * 提高指定角度下的概率值
		 */
		void rate(double bearing)
		{
			factors[getIndex(bearing)]+=0.01;
			for(int i=0; i<FACTOR_SIZE; i++) 
				factors[i] *= 0.99;
		}
		
		/**
		 * 得到最好的开火夹角
		 * @return
		 */
		double getBestFireBearing(void)
		{
			return (getHeightestIndex()-FACTOR_SIZE/2)*GAP;
		}
		
	private:
		/*
		 * 得到指定的夹角在概率数组中的索引
		 */
		int getIndex(double bearing)
		{
			return FACTOR_SIZE/2+(int)(bearing/GAP);
		}
		
		/*
		 * 得到概率最高的索引
		 */
		int getHeightestIndex(void)
		{
			int heightestIndex = 0;
			for(int i=0; i<FACTOR_SIZE; i++)
				if( factors[i]>factors[heightestIndex])
					heightestIndex = i;
			return heightestIndex;
		}
	
};

const double Statist::GAP = Math::toRadians(3);

///////////////////////////////////////////////////////////////////

/**
 * 这个类代表一个波,用于统计敌人移动的概率
 * @author xiemin
 */
class Wave
{
	private:
		//当前分区下的概率分布
		Statist* statist;
		//波的中心方向
		double center;
		//波的开始位置
		Point2D startLocation;
		//波的速度
		double velocity;
		//波出发的时间
		long startTime;
		//波是否是可用的
		bool valid;
		
	public:
		Wave(Statist* s)
		{
			statist = s;
			valid = true;
		}
		
		/**
		 * 更新波的状态
		 * @param time
		 * @param enemyLocation
		 */
		void update(long time, const Point2D& enemyLocation)
		{
			if(!valid) return;
			
			//检查是否撞到了对手
			double distance = startLocation.distance(enemyLocation);
			double moveDistance = velocity*(time-startTime);
			//hited!!
			if(moveDistance>=distance) 
			{
				valid = false;
				double heading = Math::heading(startLocation, enemyLocation);
				//计算开火的夹角
				double bearing = Math::bearing(heading, center);
				//更新这个夹角的命中率
				statist->rate(bearing);
			}
		}
	
		/**
		 * @param startTime The startTime to set.
		 */
		void setStartTime(long t)
		{
			startTime = t;
		}
		
		/**
		 * @param center The center to set.
		 */
		void setCenter(double c)
		{
			center = c;
		}
		/**
		 * @param startLocation The startLocation to set.
		 */
		void setStartLocation(Point2D l)
		{
			startLocation = l;
		}
		/**
		 * @param velocity The velocity to set.
		 */
		void setVelocity(double v)
		{
			velocity = v;
		}
		/**
		 * @return Returns the isAvailable.
		 */
		bool isValid()
		{
			return valid;
		}
};

///////////////////////////////////////////////////////////////////////////
/**
 * 用统计学瞄准的机器人
 * @author xiemin
 */
class StatistFire : public SimpleRobot
{
	private:
		//发弹的火力
		static const double POWER;
		//按距离分区的间隔
		static const double GAP;
		//机器人之间的最大距离
		static const int MAX_DIS;
		//不同分区下的概率
		Statist* statists;
		//发射的波
		vector<Wave*> waves;
	
	public:
		StatistFire(void)
		{
			int size = (int)(MAX_DIS/GAP);
			statists = new Statist[size];
		}
		
		void onTick(TickAction* action)
		{
			Bot* bot = getFirstOpponent();
			if(bot==NULL) return;
			
			addWave(bot);
			updateWaves(bot);
			doFire(bot);
			doMove();
		}
		
		void onRoundBegin(RoundBeginAction* action)
		{
			//清除上一轮发射的波
			for(int i=0; i<waves.size(); i++)
				delete waves[i];
			waves.clear();
		}
		
	private:
		//执行移动
		void doMove()
		{
			//移动到场地的中央
			Point2D center(getCourtWidth()/2, getCourtHeight()/2);
			moveTo(center);
		}
		
		/*
		 * 执行开火操作
		 */
		void doFire(Bot* bot)
		{
			if(getFirePrepareTime()<=0)
			{
				Statist* statist = getStatist(bot);
				double bearing = statist->getBestFireBearing();
				double heading = Math::heading(getLocation(), bot->getLocation());
				double fireHeading = heading+bearing;
				fire(fireHeading, POWER);
			}
		}
		
		/*
		 * 增加一个波
		 */
		void addWave(Bot* bot)
		{
			Statist* statist = getStatist(bot);
			Wave* wave = new Wave(statist);
			double center = Math::heading(getLocation(), bot->getLocation());
			wave->setCenter(center);
			wave->setStartLocation(getLocation());
			wave->setStartTime(getTime());
			wave->setVelocity(getBulletVelocity(POWER));
			waves.push_back(wave);
		}
		
		/*
		 * 更新所有的波
		 */
		void updateWaves(Bot* bot)
		{
			for(int i=0; i<waves.size(); i++)
			{
				Wave* wave = waves[i];
				if(wave->isValid())
					wave->update(getTime(), bot->getLocation());
			}
		}
		
		//得到当前分区的概率
		Statist* getStatist(Bot* bot)
		{
			double distance = Math::distance(getLocation(), bot->getLocation());
			int index = (int)(distance/GAP);
			return &statists[index];
		}
};

//发弹的火力
const double StatistFire::POWER = 0.1;
//按距离分区的间隔
const double StatistFire::GAP = 100;
//机器人之间的最大距离
const int StatistFire::MAX_DIS = 1000;


//启动机器人程序
int main(int argC, char* argV[])
{
	Robot* robot = new StatistFire();
	return startup(argC, argV, robot);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -