背景
韩顺平java中P647-P649,给出了防止敌人坦克碰撞的八种情况,代码太多了不想敲。并且,我也不想把问题简化,如:判断正方形、判断圆形...
解题思路
我的思路1:
能不能写一个方法,判断一个点是否在一个矩形中?
形参:(点的x坐标,点的y坐标,矩形左上角x坐标,矩形左上角y坐标,矩形的宽度wide,矩形的高度high)
形参:(点的x坐标,点的y坐标,矩形左上角x坐标,矩形左上角y坐标,矩形的宽度wide,矩形的高度high)
存在问题:
1. 每次传入参数都得写this.getX()、this.getY()、enemyTank.getX()...写麻了
2. 如果按照韩老师的逻辑,“判断一个点是否在一个矩形中?”的方法需要在一个case中调用4次,总共调用16次。(为什么是16次?见附录A)
我的思路2:
1. this坦克两个点的坐标使用:左上角坐标 + 偏移量 即 this.getX() + xOffset计算
2. 重写韩顺平老师的逻辑
3. “判断一个点是否在一个矩形中?”的代码嵌入到从Vector数组中遍历坦克的循环里。这样不用手写16次调用,而是循环调用enemyTanks.size()次
4. 自然的,我们发现,在3的条件下enemyTanks为中心可以简化思考。enemyTanks中取出enemyTank,它的方向就能确定矩阵的wide和high。
我的思路3:
现在就剩下最后一个问题:一个this坦克需要判断两个点,在一个enemyTanks的循环中,只判断了一个点,怎么办?
这时我们的视角从以enemyTanks为中心转为以this坦克的两个点为中心,也就是每个点其实都需要和所有enemyTanks比较。因此遍历enemyTanks的循环外面应该还有个两次的while循环,每次传入一个this坦克的点。
我的代码
//思考:我能否将八种情况抽象出来--判断一个点是否位于一个矩形内部
//写着写着“判断一个点是否位于一个矩形内部”变成了一个全是变量的if条件(通用)
// 我们只需要根据我方的方向,敌方的方向把条件填空即可
public boolean isTouchEnemyTank(){
this.getDirect();
//enemyTank.getDirect()=上下也就是0,2,就不用变了
int wide=40;
int high=60;
int xOffset = 0;
int yOffset = 0;
int count = 2; //while循环两次,因为this坦克处于一个方向,需要判断两个点。
//这时this坦克需要与所有地方坦克进行比较。也就是两个点需要与敌方坦克都进行比较
//初始的Xoffset是根据方向来设置的第一个点
switch (this.getDirect()){
case 0:
xOffset = 0;
yOffset = 0;
break;
case 1:
xOffset = 60;
yOffset = 0;
break;
case 2:
xOffset = 0;
yOffset = 60;
break;
case 3:
xOffset = 0;
yOffset = 0;
break;
}
while (count-- > 0) {
for (int i = 0; i < enemyTanks.size(); i++) {
EnemyTank enemyTank = enemyTanks.get(i);
if (this != enemyTank) {
if (enemyTank.getDirect() == 0 || enemyTank.getDirect() == 2) {
wide = 40;
high = 60;
}
if (enemyTank.getDirect() == 1 || enemyTank.getDirect() == 3) {
wide = 60;
high = 40;
}
//判断点(x+偏移,y+偏移) 是否位于宽度为wide,高度为high,以左上角(x,y)为参考点的矩阵中
if (this.getX() + xOffset >= enemyTank.getX() && this.getX() + xOffset <= enemyTank.getX() + wide
&& this.getY() + yOffset >= enemyTank.getY() && this.getY() + yOffset <= enemyTank.getY() + high) {
return true;
}
}
}
//更新offset计算,第二个点
switch (this.getDirect()){
case 0:
xOffset = 40;
yOffset = 0;
break;
case 1:
xOffset = 60;
yOffset = 40;
break;
case 2:
xOffset = 40;
yOffset = 60;
break;
case 3:
xOffset = 0;
yOffset = 40;
break;
}
}
return false;
}
附录
附录A
以this坦克,case 0的向上的情况为例:
//韩顺平源代码
if(this.getX() >= enemyTank.getX() &&
this.getX() <= enemyTank.getX()+40 &&
this.getY() >= enemyTank.getY() &&
this.getY() <= enemyTank.getY()+60){
return true;
}
//优化为如下代码
return pointInRectangle(this.getX(),this.getY(),enemyTank.getX(),enemyTank.getY(),40,60);
请各位大佬批评指正!