韩顺平坦克大战5--防止敌人坦克重叠的优化实现

背景

        韩顺平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);

请各位大佬批评指正!

  • 6
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值