当前位置: 首页 > 工具软件 > Mars Rover > 使用案例 >

经典Java练习题 Mars Rover

微生良策
2023-12-01

假想你在火星探索团队中负责软件开发。现在你要给登陆火星的探索小车编写控制程序,根据地球发送的控制指令来控制火星车的行动。
火星车收到的指令分为:
初始化信息:火星车的降落地点(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());
    }
}
 类似资料: