如何在Java中使用动态值调用枚举方法
我正在做一个程序,我必须找到一个机器人在网格中的位置,它可以向前移动,可以改变它的朝向北、南、东、西,并且有一个给定的命令序列。那么,机器人的最终位置是什么呢。 禁止使用任何类型的条件分支,例如if/else、switch/case 范例- 网格-100*500 机器人的初始位置-5,3 可能的命令- 北, E-East, W-West, 南南方, M-前进 样本输入-{N,S,M.M,E,W,E,S,M,S,M} 我尝试使用Enum,但我面临的问题是如何使用使用命令获得的动态值调用Enum方法如何在Java中使用动态值调用枚举方法,java,multidimensional-array,enums,Java,Multidimensional Array,Enums,我正在做一个程序,我必须找到一个机器人在网格中的位置,它可以向前移动,可以改变它的朝向北、南、东、西,并且有一个给定的命令序列。那么,机器人的最终位置是什么呢。 禁止使用任何类型的条件分支,例如if/else、switch/case 范例- 网格-100*500 机器人的初始位置-5,3 可能的命令- 北, E-East, W-West, 南南方, M-前进 样本输入-{N,S,M.M,E,W,E,S,M,S,M} 我尝试使用Enum,但我面临的问题是如何使用使用命令获得的动态值调用Enum方法
public class RobotMovesInGrid {
Scanner input = new Scanner(System.in);
String command=input.next();
int commLength = command.length();
static enum Command {
N{@Override public void execute(String g, String r){ System.out.println("do the N move here"); }},
E{@Override public void execute(String g, String r){ System.out.println("do the E move here"); }},
S{@Override public void execute(String g, String r){ System.out.println("do the S move here"); }},
W{@Override public void execute(String g, String r){ System.out.println("do the W move here"); }},
M{@Override public void execute(String g, String r){ System.out.println("do the M move here"); }};
public abstract void execute(String g, String r);
}
public void nextPosition() {
Command c1;
for(int i=0;i<commLength;i++) {
if (command.charAt(i)=='N'||command.charAt(i)=='E'|| command.charAt(i)=='S'|| command.charAt(i)=='W'||command.charAt(i)=='M')
c1= Command.M;// Here instead of M, I am trying to give dynamic commands but it is not taking it
System.out.println("Current position is"+c1);
}
}
}
有人可以建议我如何使用作为输入的命令调用枚举方法。最简单的方法是将字符输入转换为字符串,然后调用枚举的valueOfString方法来检索枚举,例如:
for(int i=0;i<commLength;i++) {
Command command = Command.valueOf(String.valueOf(command.charAt(i))
.toUpperCase());
if (command != null){
command.execute(...);
}
}
它会起作用,但我认为枚举值的名称实际上毫无意义。
您应该根据它们的含义重命名它们,使用包含映射字符的构造函数丰富enum类,并引入静态方法来检索与输入字符关联的enum值:
static enum Command {
NORTH('N'){@Override public void execute(String g, String r){ System.out.println("do the N move here"); }},
EAST('E'){@Override public void execute(String g, String r){ System.out.println("do the E move here"); }},
SOUTH('S'){@Override public void execute(String g, String r){ System.out.println("do the S move here"); }},
WEST('W'){@Override public void execute(String g, String r){ System.out.println("do the W move here"); }},
MOVE_FORWARD('M'){@Override public void execute(String g, String r){ System.out.println("do the M move here"); }};
private char mappingChar;
Command (char mappingChar){
this.mappingChar = mappingChar;
}
public abstract void execute(String g, String r);
public static Optional<Command> getFrom(char mappingChar) {
for (Command command : values()) {
if (Character.toUpperCase(mappingChar)==command.mappingChar) {
return Optional.of(command);
}
}
return Optional.empty();
}
}
现在,您可以动态检索枚举值并使用它:
for(int i=0;i<commLength;i++) {
Optional<Command> optCommand = Command.getFrom(command.charAt(i));
if (optCommand.isPresent()){
optCommand.get().execute(...)
}
// or alternatively
optCommand.ifPresent(c -> c.execute(...));
}
最简单的方法是将char输入转换为字符串,然后调用枚举的ValueOfsString方法来检索枚举,例如:
for(int i=0;i<commLength;i++) {
Command command = Command.valueOf(String.valueOf(command.charAt(i))
.toUpperCase());
if (command != null){
command.execute(...);
}
}
它会起作用,但我认为枚举值的名称实际上毫无意义。
您应该根据它们的含义重命名它们,使用包含映射字符的构造函数丰富enum类,并引入静态方法来检索与输入字符关联的enum值:
static enum Command {
NORTH('N'){@Override public void execute(String g, String r){ System.out.println("do the N move here"); }},
EAST('E'){@Override public void execute(String g, String r){ System.out.println("do the E move here"); }},
SOUTH('S'){@Override public void execute(String g, String r){ System.out.println("do the S move here"); }},
WEST('W'){@Override public void execute(String g, String r){ System.out.println("do the W move here"); }},
MOVE_FORWARD('M'){@Override public void execute(String g, String r){ System.out.println("do the M move here"); }};
private char mappingChar;
Command (char mappingChar){
this.mappingChar = mappingChar;
}
public abstract void execute(String g, String r);
public static Optional<Command> getFrom(char mappingChar) {
for (Command command : values()) {
if (Character.toUpperCase(mappingChar)==command.mappingChar) {
return Optional.of(command);
}
}
return Optional.empty();
}
}
现在,您可以动态检索枚举值并使用它:
for(int i=0;i<commLength;i++) {
Optional<Command> optCommand = Command.getFrom(command.charAt(i));
if (optCommand.isPresent()){
optCommand.get().execute(...)
}
// or alternatively
optCommand.ifPresent(c -> c.execute(...));
}
您可以使用Command.valueOf
像
这会将c1设置为与输入的命令相对应的命令的枚举值
toUpperCase确保其与枚举的名称相同。您可以使用Command.valueOf
像
这会将c1设置为与输入的命令相对应的命令的枚举值
toUpperCase确保它与枚举的名称相同。这里是另一个解决方案
static enum Command {
N(-1,0),E(0,1),W(0,-1),S(1,0);
private int rowIncrement;
private int colIncrement;
private Command(int rowIncrement, int colIncrement)
{
this.rowIncrement = rowIncrement;
this.colIncrement = colIncrement;
}
public int getRowIncrement()
{
return rowIncrement;
}
public int getColIncrement()
{
return colIncrement;
}
}
这是命令评估的代码
//input
String command = "NSMMEWESMSM";
int[] pos = new int[]{5,3};
int[] size = new int[]{100, 500};
char[] chars = command.toCharArray();
//replace M by the previous char, ie move in the same direction
for (int i = 0; i < chars.length; i++)
{
char dir = chars[i];
//this assumes that M cannot be the first char
if (dir == 'M')
{
dir = chars[i-1];
chars[i] = dir;
}
}
for (char dir : chars)
{
Command cmd = Command.valueOf(String.valueOf(dir));
pos[0] += cmd.rowIncrement;
//row is within the region
pos[0] = Math.min(Math.max(pos[0], 0), size[0] -1);
pos[1] += cmd.colIncrement;
//col is within the region
pos[1] = Math.min(Math.max(pos[1], 0), size[1] -1);
}
这是另一个解决方案
static enum Command {
N(-1,0),E(0,1),W(0,-1),S(1,0);
private int rowIncrement;
private int colIncrement;
private Command(int rowIncrement, int colIncrement)
{
this.rowIncrement = rowIncrement;
this.colIncrement = colIncrement;
}
public int getRowIncrement()
{
return rowIncrement;
}
public int getColIncrement()
{
return colIncrement;
}
}
这是命令评估的代码
//input
String command = "NSMMEWESMSM";
int[] pos = new int[]{5,3};
int[] size = new int[]{100, 500};
char[] chars = command.toCharArray();
//replace M by the previous char, ie move in the same direction
for (int i = 0; i < chars.length; i++)
{
char dir = chars[i];
//this assumes that M cannot be the first char
if (dir == 'M')
{
dir = chars[i-1];
chars[i] = dir;
}
}
for (char dir : chars)
{
Command cmd = Command.valueOf(String.valueOf(dir));
pos[0] += cmd.rowIncrement;
//row is within the region
pos[0] = Math.min(Math.max(pos[0], 0), size[0] -1);
pos[1] += cmd.colIncrement;
//col is within the region
pos[1] = Math.min(Math.max(pos[1], 0), size[1] -1);
}
一种方法是在内部类enum命令中使用一个常量静态映射;它将字符串与命令相关联。Command.parse在映射中查找该命令
import java.lang.String;
import java.util.Map;
import java.util.HashMap;
import java.util.Collections;
import java.util.function.Function;
import java.awt.Point;
import java.util.Scanner;
class Robot {
public static void main(String args[]) {
try(Scanner input = new Scanner(System.in)) {
input.useDelimiter(",\\s*|\n");
Robot r = new Robot();
while(input.hasNext()) {
try {
Command.parse(input.next().trim()).apply(r);
} catch(NullPointerException e) {
System.out.printf("Syntax error.\n");
} catch(RuntimeException e) {
System.out.printf("Can't go that way: %s.\n",
e.getMessage());
}
}
} catch(Exception e) {
System.err.printf("%s: %s.\n", e, e.getMessage());
}
}
Point x;
static Point dim;
Command last;
Robot() {
dim = new Point(100, 500);
x = new Point(5, 3);
}
enum Command {
N("N", "north", true, (r) -> new Point(r.x.x, r.x.y - 1)),
E("E", "east", true, (r) -> new Point(r.x.x + 1, r.x.y)),
S("S", "south", true, (r) -> new Point(r.x.x, r.x.y + 1)),
W("W", "west", true, (r) -> new Point(r.x.x - 1, r.x.y)),
M("M", "farther",false, (r) -> r.last != null ?r.last.go.apply(r):null);
private String command, name;
private boolean isDir;
private Function<Robot, Point> go;
private static final Map<String, Command> map;
/* Map for turning commands into Directions; mod->const map. */
static {
Map<String, Command> mod = new HashMap<>();
for(Command c : values()) mod.put(c.command, c);
map = Collections.unmodifiableMap(mod);
}
/** Called from definition of enum. */
private Command(final String command, final String name, boolean isDir,
final Function<Robot, Point> go) {
this.command = command;
this.name = name;
this.isDir = isDir;
this.go = go;
}
/** @param str A string representing the direction.
@return The command or null. */
public static Command parse(final String str) { return map.get(str); }
/** Applies this command to r. */
public void apply(Robot r) {
Point x = this.go.apply(r);
if(x == null)
throw new RuntimeException("don't have a direction");
if(x.x < 0 || x.x >= dim.x || x.y < 0 || x.y >= dim.y)
throw new RuntimeException("at the edge");
r.x = x;
if(this.isDir == true) r.last = this;
System.out.printf("Went %s to (%d, %d).\n", r.last.name, x.x, x.y);
}
/** @return The name of the direction. */
public String toString() { return name; }
}
}
它在EOF结束。我觉得这些很有帮助
一种方法是在内部类enum命令中使用一个常量静态映射;它将字符串与命令相关联。Command.parse在映射中查找该命令
import java.lang.String;
import java.util.Map;
import java.util.HashMap;
import java.util.Collections;
import java.util.function.Function;
import java.awt.Point;
import java.util.Scanner;
class Robot {
public static void main(String args[]) {
try(Scanner input = new Scanner(System.in)) {
input.useDelimiter(",\\s*|\n");
Robot r = new Robot();
while(input.hasNext()) {
try {
Command.parse(input.next().trim()).apply(r);
} catch(NullPointerException e) {
System.out.printf("Syntax error.\n");
} catch(RuntimeException e) {
System.out.printf("Can't go that way: %s.\n",
e.getMessage());
}
}
} catch(Exception e) {
System.err.printf("%s: %s.\n", e, e.getMessage());
}
}
Point x;
static Point dim;
Command last;
Robot() {
dim = new Point(100, 500);
x = new Point(5, 3);
}
enum Command {
N("N", "north", true, (r) -> new Point(r.x.x, r.x.y - 1)),
E("E", "east", true, (r) -> new Point(r.x.x + 1, r.x.y)),
S("S", "south", true, (r) -> new Point(r.x.x, r.x.y + 1)),
W("W", "west", true, (r) -> new Point(r.x.x - 1, r.x.y)),
M("M", "farther",false, (r) -> r.last != null ?r.last.go.apply(r):null);
private String command, name;
private boolean isDir;
private Function<Robot, Point> go;
private static final Map<String, Command> map;
/* Map for turning commands into Directions; mod->const map. */
static {
Map<String, Command> mod = new HashMap<>();
for(Command c : values()) mod.put(c.command, c);
map = Collections.unmodifiableMap(mod);
}
/** Called from definition of enum. */
private Command(final String command, final String name, boolean isDir,
final Function<Robot, Point> go) {
this.command = command;
this.name = name;
this.isDir = isDir;
this.go = go;
}
/** @param str A string representing the direction.
@return The command or null. */
public static Command parse(final String str) { return map.get(str); }
/** Applies this command to r. */
public void apply(Robot r) {
Point x = this.go.apply(r);
if(x == null)
throw new RuntimeException("don't have a direction");
if(x.x < 0 || x.x >= dim.x || x.y < 0 || x.y >= dim.y)
throw new RuntimeException("at the edge");
r.x = x;
if(this.isDir == true) r.last = this;
System.out.printf("Went %s to (%d, %d).\n", r.last.name, x.x, x.y);
}
/** @return The name of the direction. */
public String toString() { return name; }
}
}
它在EOF结束。我觉得这些很有帮助
感谢您的解决方案,但在使用您的代码后,我发现了两个错误。一个是构造函数RobotMoveInGrid。命令未定义,另一个是方法getchar未定义。欢迎使用!检查是否在枚举中添加了命令构造函数,例如命令char mappingChar{this.mappingChar=mappingChar;}。对于第二个错误,很抱歉,我没有使用IDE。应该调用的不是get而是getFrom。我更新了它。谢谢你的解决方案,但是在使用你的代码后我发现了两个错误。一个是构造函数RobotMoveInGrid。命令未定义,另一个是方法getchar未定义。欢迎使用!检查是否在枚举中添加了命令构造函数,例如命令char mappingChar{this.mappingChar=mappingChar;}。对于第二个错误,很抱歉,我没有使用IDE。应该调用的不是get而是getFrom。我更新了它。这是一个简单而伟大的解决方案。。非常感谢!!这是一个简单而伟大的解决方案。。非常感谢!!我唯一感觉到的是,我认为在新闻中,命令机器人只会改变它的方向,不会移动。这需要解释一下:在命令内部类中,go是一个函数,它接收机器人并返回一个点,该点在机器人位置的N,E,W,S方向上偏离1。Command.apply获取该点,检查它是否为有效点-如果不是,则异常,并且r.x=x更新该点。我确实有一个更复杂的lambda,但这涉及到大量的代码重用。我唯一感觉到的是,我认为在新闻中,命令robot只会改变它的方向,不会移动。这需要解释一下:在命令内部类中,go是一个函数,它接收一个robot并返回一个在N,E,W方向上偏离一个的点,他从机器人的位置离开。Command.apply获取该点,检查它是否为有效点-如果不是,则异常,并且r.x=x更新该点。我确实有一个更复杂的lambda,但这涉及到大量的代码重用。