简易的robocode

一、大体思路

扫描敌人的逻辑不变,对扫描到敌人后的应对方法进行重写

下面是整体的代码实现

package jjysss;

import java.awt.Color;

import robocode.AdvancedRobot;
import robocode.HitWallEvent;
import robocode.ScannedRobotEvent;
import robocode.HitByBulletEvent;

public class Jjyssss extends AdvancedRobot {
	private static final int MAX = 20;
	public static final double P=3.14159265359d;

	private static final double min_dis = 220.0d;

		
	// 坦克移动方向
	int way = 1;

	// 宽度,高度
	double width;
	double height;
	double MIN_RANGE = 30.0d;

	// 回合计数器
	int ifcontinue = MAX;

	public void run() {
		setGunColor(new Color(0, 0, 0));
		setBulletColor(new Color(0, 0, 0));
		setRadarColor(new Color(0, 0, 0));
		setScanColor(new Color(0, 0, 0));
		setBodyColor(new Color(0, 0, 0));

        //分开旋转
		setAdjustRadarForRobotTurn(true);
		setAdjustGunForRobotTurn(true);
		

		// 雷达持续旋转
		turnRadarLeftRadians(2147483647); 

		
		// 活动范围
		width = this.getBattleFieldWidth() - MIN_RANGE;
		height = this.getBattleFieldHeight() - MIN_RANGE;
	}
	
	//扫描到了
	public void onScannedRobot(ScannedRobotEvent e) {
		//自己与敌的连线,与Y轴形成的夹角
		double bearing = getHeadingRadians() + e.getBearingRadians();
		bearing=robocode.util.Utils.normalRelativeAngle(bearing); //根据robocode教程
		
		// 速度
		double enemySpeed = Math.sin(e.getHeadingRadians()-bearing) * e.getVelocity();  // em的相对与我的相对位置
		setTurnRadarRightRadians(-getRadarTurnRemainingRadians()); //转回去,回调函数
		
		//旋转gun		
		//   10 11 平滑处理,降低旋转速度。 gun是相对坐标的
		double gunturn = norma(bearing - getGunHeadingRadians() + enemySpeed/11);
		setTurnGunRightRadians(gunturn);

		// 默认向前
		boolean ahead = true;
		
		if (e.getDistance() > min_dis){
			// 接近 //得到e.getbearingradians,这是机器人需要调整的角度+一个补偿值(敌坦的速度/自己的速度)
			setTurnRightRadians(norma(bearing - getHeadingRadians() + enemySpeed / 11));
		} else {
			// away  右转加45度 45跑路
			setTurnRightRadians(45 + e.getBearing());
			ahead = false;
		}
		
		move(ahead, way * (e.getDistance() - min_dis));  
		
		if(e.getDistance()<=230) setFire(3);

		else setFire(1);
	}

	private static double norma(double x)
	 {
		return (x %= (2 * P)) >= 0 ? (x < P) ? x : x - (2 * P)
				: (x >= -P) ? x : x + (2 * P);
	}

	private void move(boolean ahead, double distance) {
		// 自己的位置
		double x = this.getX() + distance;
		double y = this.getY() + distance;

	if (ifcontinue <= 0)
	{
		if (x <= MIN_RANGE || y <= MIN_RANGE || x >= width || y >= height)
		{
			ahead = false;
			//重启计数器
			ifcontinue = MAX;
		}

		if (ahead)
			setAhead(distance);
		else 
			setBack(distance);
	}
   else
   {
		ifcontinue--;
	}

	
}

 public void onHitByBullet(HitByBulletEvent event)
 {
           setTurnRightRadians(90);
			setBack(50);
			execute();
	   
   }

	public void onHitWall(HitWallEvent e) {
		way = -way;
		ifcontinue = MAX;
	}
}

二、细节分述

1.导入各个包

package jjysss;

import java.awt.Color;

import robocode.AdvancedRobot;
import robocode.HitWallEvent;
import robocode.ScannedRobotEvent;
import robocode.HitByBulletEvent;

2.类中属性

其中,MAX代表一个周期计数器的最大值,ifcontinue就是一个计数器,在后面的代码实现了当计数器小于0时,坦克会发生一次移动,大于0时坦克不变,这个设定会给坦克一个随机量,移动更灵活。width和height则表示坦克的活动范围为(width,height),而MIN_RANGE限定一个边界值,后面我们用地图的width,height减去MIN_RANGE,就是坦克的活动范围。这个和way的作用类似,就是避免坦克撞到墙。min_dis是和敌人最小距离即安全距离。p是π的近似值

	private static final int MAX = 20;
	public static final double P=3.14159265359d;

	private static final double min_dis = 220.0d;

		
	// 坦克移动方向
	int way = 1;

	// 宽度,高度
	double width;
	double height;
	double MIN_RANGE = 30.0d;

	// 回合计数器
	int ifcontinue = MAX;

3.run方法重写

1.设置颜色

2.雷达枪分开旋转,这样可以使扫敌和攻击效率变高

3.turnRadarLeftRadians(INT_MAX),给一个尽可能大的弧度制,让雷达一直旋转。

4.限定坦克活动范围

	public void run() {
		setGunColor(new Color(0, 0, 0));
		setBulletColor(new Color(0, 0, 0));
		setRadarColor(new Color(0, 0, 0));
		setScanColor(new Color(0, 0, 0));
		setBodyColor(new Color(0, 0, 0));

        //分开旋转
		setAdjustRadarForRobotTurn(true);
		setAdjustGunForRobotTurn(true);
		

		// 雷达持续旋转
		turnRadarLeftRadians(2147483647); 

		
		// 活动范围
		width = this.getBattleFieldWidth() - MIN_RANGE;
		height = this.getBattleFieldHeight() - MIN_RANGE;
	}

4.OnScannedRobot重写

1.计算出bearing值。

2.计算出enemyspeed,敌人的朝向-自己朝向=枪该转过去的角度。取sin()是因为能更好的表达两者的角度差,差为0时,结果为0,差为90度时,sin为1,差为180时,sin为0。前面这一坨也是一个权重值,乘以敌人的速度,得出敌人的一个相对速度。为后面的枪旋转射击做准备。

3.setTurnRadarRightRadians(-getRadarTurnRemainingRadians()); 这句代码的精妙之处在于,类似于C++的回调函数,当坦克扫描到敌人后,进入onScannedRobot方法,而getRadarTurnRemainingRadians()代码为获取雷达旋转剩余的弧度数,取负数往反方向旋转,setTurnRadarRight-Radians方法接收此参数后,会反方向扫描,但此时又恰好好会遇见刚才扫描过的敌人,又会进入onScannedRobot方法,形成了一个闭环,算是一个简陋的索敌雷达。

4.枪应该旋转的角度,根据课件原本为雷达应该旋转的角度,但是在本坦克中,雷达的锁定有另一种方法, 但是这个也可以界定为枪旋转的角度,虽然不是很精确,不过也实现了一定程度的追踪打击。但是枪旋转期间,敌人也在移动,所以还需要加上一个权重值来表示额外的旋转角度,经过实验发现,enemyspeed*一个数,旋转得太快了,所以改为/,测试后10和11是胜率比较高的数。

5.我们的坦克在正常情况下是向前走的。在下面的代码中,遇到MIN_RANGE和小于和敌人的安全距离会停下来。

6.当前距离大于安全距离时,坦克接近敌人,逻辑和枪寻敌一样。小于安全距离时,右转45度停止向前移动。

7.开火判定,距离小于等于230,发射威力为3的子弹,else威力为1。

	public void onScannedRobot(ScannedRobotEvent e) {
		//自己与敌的连线,与Y轴形成的夹角
		double bearing = getHeadingRadians() + e.getBearingRadians();
		bearing=robocode.util.Utils.normalRelativeAngle(bearing); //根据robocode教程
		
		// 速度
		double enemySpeed = Math.sin(e.getHeadingRadians()-bearing) * e.getVelocity();  // em的相对与我的相对位置
		setTurnRadarRightRadians(-getRadarTurnRemainingRadians()); //转回去,回调函数
		
		//旋转gun		
		//   10 11 平滑处理,降低旋转速度。 gun是相对坐标的
		double gunturn = norma(bearing - getGunHeadingRadians() + enemySpeed/11);
		setTurnGunRightRadians(gunturn);

		// 默认向前
		boolean ahead = true;
		
		if (e.getDistance() > min_dis){
			// 接近 //得到e.getbearingradians,这是机器人需要调整的角度+一个补偿值(敌坦的速度/自己的速度)
			setTurnRightRadians(norma(bearing - getHeadingRadians() + enemySpeed / 11));
		} else {
			// away  右转加45度 45跑路
			setTurnRightRadians(45 + e.getBearing());
			ahead = false;
		}
		
		move(ahead, way * (e.getDistance() - min_dis));  
		
		if(e.getDistance()<=230) setFire(3);

		else setFire(1);
	}

5.move方法

1.先确定自己的位置,distance为即将移动的距离,加上再判断是否走到了限定范围外。

如果走到了限定范围外,ahead变为false,计数器重启。

在下面的判断语句中,如果ahead为true,往前走,反之往后走。

ifcontinue不为0,ifcontinue--,计数器MAX为一个轮回。

	private void move(boolean ahead, double distance) {
		// 自己的位置
		double x = this.getX() + distance;
		double y = this.getY() + distance;

	if (ifcontinue <= 0)
	{
		if (x <= MIN_RANGE || y <= MIN_RANGE || x >= width || y >= height)
		{
			ahead = false;
			//重启计数器
			ifcontinue = MAX;
		}

		if (ahead)
			setAhead(distance);
		else 
			setBack(distance);
	}
   else
   {
		ifcontinue--;
	}

	
}

6.特殊情况判定

上面的坦克设定中,被射击到不会躲避,并且在矩形的边界中,如果遇见了猥琐在边界的敌人,此坦克会铁着头往敌人子弹上撞,所以重写onHitByBullet函数,虽然不能完全规避这种情况,但也减少了一部分情况的发生。

 public void onHitByBullet(HitByBulletEvent event)
 {
           setTurnRightRadians(90);
			setBack(50);
			execute();
	   
   }

7.撞到墙后

虽然有限定范围,但是坦克的受击反馈仍可能会撞到墙,这里做一个特殊处理,往相反方向走,计数器重启。

	public void onHitWall(HitWallEvent e) {
		way = -way;
		ifcontinue = MAX;
	}
}

8.norma

网上抄的,用于将角度转换为-π到π之间。

	private static double norma(double x)
	 {
		return (x %= (2 * P)) >= 0 ? (x < P) ? x : x - (2 * P)
				: (x >= -P) ? x : x + (2 * P);
	}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Robocode是一款简易的编程游戏,通过编写代码来控制机器人进行战斗。在游戏中,你可以创建自己的机器人,并且通过寻找对手、进行攻击和躲避攻击来实现胜利。 Robocode的规则非常简单,每个机器人都有一定数量的能量和生命值,可以通过攻击敌人来消耗能量和减少敌人的生命值。在游戏中,机器人可以通过不同的指令进行移动、转向、攻击等操作。 为了编写自己的机器人代码,你需要了解一些基本的编程知识,比如控制流程、函数、变量等。你可以使用Java或C#等编程语言来编写代码,并且可以使用Robocode提供的API来获取机器人的状态、执行操作等。 Robocode提供了一个交互式的开发环境,可以让你实时查看机器人的行为和效果。你可以在游戏中创建不同的对手,并且通过观察它们的行为和战斗结果来改进自己的机器人策略。 Robocode简易性使它成为一个很好的学习工具,无论是初学者还是有一定编程经验的人都可以通过它来提高他们的编程能力和理解。此外,Robocode还有一个活跃的社区,你可以与其他玩家分享你的机器人并与他们进行比赛。 总而言之,Robocode是一个开放、简易但富有挑战性的编程游戏,你可以通过编写机器人代码来进行战斗并提升自己的编程技能。无论是学习还是娱乐,它都是一个有趣和有价值的选择。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JJY_s

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值