经典Java练习题 Mars Rover

假想你在火星探索团队中负责软件开发。现在你要给登陆火星的探索小车编写控制程序,根据地球发送的控制指令来控制火星车的行动。
火星车收到的指令分为:
初始化信息:火星车的降落地点(x, y)和朝向(N, S, E, W)信息;
移动指令:火星车可以前进(M),一次移动X格;
移动指令:火星车可以前进(B),一次移动X格;
转向指令:火星车可以左转90度(L)或右转90度(R)。
由于地球和火星之间的距离很远,指令必须批量发送,火星车执行完整批指令之后,再回报自己所在的位置坐标和朝向。

package com.thoughtworks.b_mars_rover;
import java.util.ArrayList;
import java.util.List;

public class Run {
    public static void main(String[] args) {
        // Instruct (指令类型,角度,移动距离)
        List<Instruct> instructs = new ArrayList<>();
        instructs.add(new Instruct(InstructType.MOVE, 0, 4));
        instructs.add(new Instruct(InstructType.BACK, 0, 4));
        instructs.add(new Instruct(InstructType.TURN_RIGHT, 37, 0));
        instructs.add(new Instruct(InstructType.MOVE, 0, 5));
        instructs.add(new Instruct(InstructType.BACK, 0, 5));
        instructs.add(new Instruct(InstructType.TURN_LEFT, 164, 5));
        instructs.add(new Instruct(InstructType.MOVE, 0, 5));
        instructs.add(new Instruct(InstructType.BACK, 0, 5));

        //初始化小车位置 x,y,朝向,顺时针角度
        MarsRover marsRover = new MarsRover(0, 0, "N", 0);
        System.out.println("初始化:小车朝向:"+marsRover.getFaceTo()+"----小车角度:"+marsRover.getAngle()+"---小车X轴位置:"+marsRover.getX()+"---小车Y轴距离:"+marsRover.getY());

        for (Instruct instruct : instructs) {
            if (instruct.getInstructType() == InstructType.BACK||instruct.getInstructType() == InstructType.MOVE) {
               marsRover.move(instruct);
            } else {
                marsRover.wheel(instruct);
            }
            System.out.println("小车朝向:"+marsRover.getFaceTo()+"----小车角度:"+marsRover.getAngle()+"---小车X轴位置:"+marsRover.getX()+"---小车Y轴距离:"+marsRover.getY());
        }
    }
}


package com.thoughtworks.b_mars_rover;

import com.thoughtworks.b_mars_rover.move.MoveEnum;
import com.thoughtworks.b_mars_rover.move.MoveRule;
import com.thoughtworks.b_mars_rover.move.MoveRuleDispatchCentre;
import lombok.Data;

/**
 * 探测车x,y,朝向,角度
 */
@Data
public class MarsRover {
    private final static String allDirection = "NESW";
    private double x;
    private double y;
    private String faceTo;
    /**
     * 角度为当前方向的顺时针角度
     */
    private double angle;

    public MarsRover(double x, double y, String faceTo, double angle) {
        this.x = x;
        this.y = y;
        this.faceTo = faceTo;
        this.angle = angle;
    }

    //小车转弯
    public void wheel(Instruct wheelInstruct) {
        //增大一圈,避免为负
        double newAngel = this.getAngle() + wheelInstruct.getAngle();
        /**
         * 取探测车朝向
         * >=0时取90的余数与探险车的索引相加
         * <0时取90的余数与探险车的索引相减
         */
        this.faceTo = newAngel >= 0 ? String.valueOf(allDirection.charAt((allDirection.indexOf(this.faceTo) + (int) ((newAngel + 360) / 90)) % 4)) :
                String.valueOf(allDirection.charAt(((allDirection.indexOf(this.faceTo) + (int) (newAngel + 360) / 90) + 4) % 4));
        this.angle = (newAngel + 360) % 90;
    }

    // 小车移动
    public void move(Instruct instruct) {
        MoveRule moveRule = null;
        if (instruct.getInstructType() == InstructType.MOVE) {
            moveRule = MoveRuleDispatchCentre.getMoveRule(MoveEnum.getInstance(this.getFaceTo()));
        } else {
            moveRule = MoveRuleDispatchCentre.getMoveRule(MoveEnum.BACK);
        }
        instruct.xyMoveDistance(this);
        moveRule.move(instruct, this);
    }
}


package com.thoughtworks.b_mars_rover;

import lombok.Getter;

/**
 * 转向枚举
 */
public enum InstructType {
    TURN_LEFT("L"), TURN_RIGHT("R"), MOVE("M"), BACK("B");
    @Getter
    private String InstructType;

    InstructType(String instructType) {
        InstructType = instructType;
    }

    public static InstructType getInstance(String instructType) {
        if (TURN_LEFT.getInstructType().equals(instructType)) {
            return TURN_LEFT;
        }
        return TURN_RIGHT;
    }
}



package com.thoughtworks.b_mars_rover;

import com.thoughtworks.b_mars_rover.move.MoveEnum;
import lombok.Data;

/**
 * 指令对象
 */
@Data
public class Instruct {
    private InstructType instructType;
    private double angle;
    private double moveDistance;
    private double xMoveDistance;
    private double yMoveDistance;

    public double getRealAngel(InstructType instructType, double angle) {
        /**
         * 转向大于360度,取余数
         */
        angle = Math.abs(angle) >= 360 ? angle % 360 : angle;
        /**
         * 左转为负数,右转为正数
         */
        return instructType == InstructType.TURN_LEFT ? -angle : angle;
    }

    /**
     * 移动小车之前必须先计算小车位移的X和Y距离
     *
     * @param marsRover
     */
    public void xyMoveDistance(MarsRover marsRover) {
        if (MoveEnum.getInstance(marsRover.getFaceTo()) == MoveEnum.EAST || MoveEnum.getInstance(marsRover.getFaceTo()) == MoveEnum.WEST) {
            moveToEastAndWest(marsRover);
        } else {
            moveToNorthAndSorth(marsRover);
        }

    }

    private void moveToNorthAndSorth(MarsRover marsRover) {
        this.setYMoveDistance(Math.cos(Math.toRadians(marsRover.getAngle())) * this.getMoveDistance());
        this.setXMoveDistance(Math.sin(Math.toRadians(marsRover.getAngle())) * this.getMoveDistance());
    }

    private void moveToEastAndWest(MarsRover marsRover) {
        this.setXMoveDistance(Math.cos(Math.toRadians(marsRover.getAngle())) * this.getMoveDistance());
        this.setYMoveDistance(Math.sin(Math.toRadians(marsRover.getAngle())) * this.getMoveDistance());
    }


    public Instruct(InstructType instructType, double angle, double moveDistance) {
        this.instructType = instructType;
        this.angle = getRealAngel(instructType, angle);
        this.moveDistance = moveDistance;
    }
}
package com.thoughtworks.b_mars_rover.move;

import com.thoughtworks.b_mars_rover.Instruct;
import com.thoughtworks.b_mars_rover.InstructType;
import com.thoughtworks.b_mars_rover.MarsRover;

/**
 * 后退
 */
public class BackMove implements MoveRule {
    @Override
    public void move(Instruct moveInstruct, MarsRover marsRover) {
        moveInstruct.setXMoveDistance(0 - moveInstruct.getXMoveDistance());
        moveInstruct.setYMoveDistance(0 - moveInstruct.getYMoveDistance());
        moveInstruct.setInstructType(InstructType.MOVE);
        MoveRule moveRule = MoveRuleDispatchCentre.getMoveRule(MoveEnum.getInstance(marsRover.getFaceTo()));
        moveRule.move(moveInstruct, marsRover);
    }
}

package com.thoughtworks.b_mars_rover.move;

import com.thoughtworks.b_mars_rover.Instruct;
import com.thoughtworks.b_mars_rover.MarsRover;

/**
 * 小车朝向E到S
 */
public class EastMove implements MoveRule {
    public static void main(String[] args) {
        System.out.println(Math.cos(Math.toRadians(37)) * 5);
    }

    @Override
    public void move(Instruct eastInstruct, MarsRover marsRover) {
        marsRover.setX(marsRover.getX()+eastInstruct.getXMoveDistance());
        marsRover.setY(marsRover.getY()-eastInstruct.getYMoveDistance());
    }
}

package com.thoughtworks.b_mars_rover.move;

/**
 * 移动规则枚举
 */
public enum MoveEnum {
    NORTH("N"), WEST("E"), SORTH("S"), EAST("W"), BACK("B");
    private String faceTo;

    MoveEnum(String faceTo) {
        this.faceTo = faceTo;
    }

    public static MoveEnum getInstance(String faceTo) {
        switch (faceTo) {
            case "N":
                return NORTH;
            case "E":
                return EAST;
            case "S":
                return SORTH;
            case "W":
                return WEST;
            default: {
                return BACK;
            }
        }
    }
}

package com.thoughtworks.b_mars_rover.move;

import com.thoughtworks.b_mars_rover.Instruct;
import com.thoughtworks.b_mars_rover.MarsRover;

/**
 * 移动规则父类
 */
public interface MoveRule {
    void move(Instruct moveInstruct, MarsRover marsRover);
}

package com.thoughtworks.b_mars_rover.move;

import java.util.HashMap;
import java.util.Map;

public class MoveRuleDispatchCentre {
    private static Map<MoveEnum, MoveRule> moveTypes = new HashMap<>();

    static {
        moveTypes.put(MoveEnum.NORTH, new NorthMove());
        moveTypes.put(MoveEnum.WEST, new EastMove());
        moveTypes.put(MoveEnum.SORTH, new SouthMove());
        moveTypes.put(MoveEnum.EAST, new EastMove());
        moveTypes.put(MoveEnum.BACK, new BackMove());
    }

    public static MoveRule getMoveRule(MoveEnum moveEnum) {
        return moveTypes.get(moveEnum);
    }
}

package com.thoughtworks.b_mars_rover.move;

import com.thoughtworks.b_mars_rover.Instruct;
import com.thoughtworks.b_mars_rover.MarsRover;

/**
 * 小车朝向N到E
 */
public class NorthMove implements MoveRule {
    @Override
    public void move(Instruct northInstruct, MarsRover marsRover) {
        marsRover.setX(marsRover.getX()+northInstruct.getXMoveDistance());
        marsRover.setY(marsRover.getY()+northInstruct.getYMoveDistance());
    }
}

package com.thoughtworks.b_mars_rover.move;

import com.thoughtworks.b_mars_rover.Instruct;
import com.thoughtworks.b_mars_rover.MarsRover;

/**
 * 小车朝向S到W
 */
public class SouthMove implements MoveRule {
    @Override
    public void move(Instruct sorthInstruct, MarsRover marsRover) {
        marsRover.setX(marsRover.getX()-sorthInstruct.getXMoveDistance());
        marsRover.setY(marsRover.getY()-sorthInstruct.getYMoveDistance());
    }
}

package com.thoughtworks.b_mars_rover.move;

import com.thoughtworks.b_mars_rover.Instruct;
import com.thoughtworks.b_mars_rover.MarsRover;

/**
 * 小车朝向W到N
 */
public class WestMove implements MoveRule {
    @Override
    public void move(Instruct westInstruct, MarsRover marsRover) {
        marsRover.setX(marsRover.getX()-westInstruct.getXMoveDistance());
        marsRover.setY(marsRover.getY()+westInstruct.getYMoveDistance());
    }
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java设计模式练习是指通过实际编码实现,学习和掌握各种设计模式的使用方法和场景。Java设计模式是一套被广泛应用于软件开发经典模式,它们提供了一种解决常见问题的标准化方案,并能够提高代码的可读性、可维护性和可扩展性。 在Java设计模式练习,我们可以选择一些常用的设计模式,如单例模式、工厂模式、观察者模式等进行实践。通过实际编写代码,我们可以更好地理解各种设计模式的实现原理和使用方法。 在练习过程,我们可以使用一些简单的场景进行模拟,例如创建一个线程池管理类来实现单例模式,或者使用工厂模式创建图形对象,然后通过观察者模式来实现图形的更新通知。 通过这些练习,我们可以学习到设计模式的思想和原则,并能够将其应用于实际开发。这不仅可以提高我们的编码能力,还能够培养我们的设计思维和解决问题的能力。 值得一提的是,设计模式并不是一成不变的,它们可以根据实际需求进行灵活地应用和调整。因此,在练习过程,我们也应该注重模式的灵活运用,根据具体情况选择适合的设计模式,并善于组合多种模式进行代码的优化和重构。 总之,Java设计模式练习是一种提高编码能力和设计思维的有效方式,通过实践我们能够更好地掌握各种设计模式的使用方法和场景,从而写出更加可读、可维护和可扩展的代码。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值