MARS ROVERS问题
一小队机器人探测器将由NASA送上火星高原,探测器将在这个奇特的矩形高原上行驶。用它们携带的照相机将周围的全景地势图发回到地球。每个探测器的方向和位置将由一个x,y系坐标图和一个表示地理方向的字母表示出来。为了方便导航,平原将被划分为网格状。位置坐标示例:0,0,N,表示探测器在坐标图的左下角,且面朝北方。为控制探测器,NASA会传送一串简单的字母。可能传送的字母为: ‘L ‘, ‘R ‘和 ‘M ‘。 ‘L ‘,和 ‘R ‘分别表示使探测器向左、向右旋转90度,但不离开他所在地点。 ‘M ‘ 表示向前开进一个网格的距离,且保持方向不变。假设以广场(高原)的直北方向为y轴的指向。
输入:首先输入的line是坐标图的右上方,假定左下方顶点的坐标为0,0。剩下的要输入的是被分布好的探测器的信息。每个探测器需要输入wo lines。第一条line 提供探测器的位置,第二条是关于这个探测器怎样进行高原探测的一系列说明。位置是由两个整数和一个区分方向的字母组成,对应了探测器的(x,y)坐标和方向。每个探测器的移动将按序完成,即后一个探测器不能在前一个探测器完成移动之前开始移动。
输出:每个探测器的输出应该为它行进到的最终位置坐标和方向。输入和输出 测试如下:
地图边界:5 5
当前位置:1 2 N
移动指令:LMLMLMLMM
当前位置:3 3 E
移动指令:MMRMMRMRRM
期待的输出
1 3 N
5 1 E
思路: 1、该问题传达我们这样几个关键实例:“一队探测器”、“矩形高原”、“xy系坐标”、“当前位置”、“方向”、“左|右”。 2、当前位置代表这对探测器在矩形高原的位置。而这个位置信息除了包含x、y坐标值以外还包含一个朝向,而指令是通过[左转|右转]控制。但结果输出需要的是方向。 3、我们需要的”类”,究竟是什么? No1、方向 我们需要一个方向的枚举,用以代表四个方向。 ``\` public enum TowardEnum { N, S, W, E }
这里我们必须停一下,指令是通过"L"/"R"传达的,也就是左转右转可以代表任意方向。这里我们需要一个转换一下思路。 先来观察一下这个图例 N->W->S->E的指令为LLL N->E-->S->E的指令为RRR [![](http://www.abelzhou.com/wp-content/uploads/2012/02/20120227130906.jpg "20120227130906")](http://www.abelzhou.com/wp-content/uploads/2012/02/20120227130906.jpg) 可以理解为L:逆时针 R:顺时针 一个L或者R标识一个90°旋转。那么我们可以认为以90°为一个标量。没执行一个L/R则自增或者自减了1。那么这个枚举就会变成这个样子。 public enum TowardEnum { N=0, W=1, S=2, E=3 }
这段代码就有点意思了,假设当前朝向为N,L和R分别代表的方位为 L--> (TowardEnum.N+1)%4 -->TowardEnum.W R--> (TowardEnum.N+3)%4 -->TowardEnum.E No2、地图边界。 车辆是不能够超出(0~n,0~n)这个范围的,所以需要有个地图坐标范围。 public class Map { int x; int y; }
No3、当前位置 小车当前的位置信息。 public class Position { int x, int y, TowardEnum towardEnum; }
No4、控制类。 根据当前位置,以及朝向(这个在上面已经大概说明了),区分到底是该操作x还是操作y。由于是单指令控制一次移动、每次移动一个单位。故可以用自增或者自减判断。 No5、处理类 既处理传入的参数以及最终获得完成指令的车辆位置出口。 完整代码 namespace MarsExploration {
class Program
{
static void Main(string[] args)
{
Console.Write("请输入右上角边界值x(5 5 ):");
String mapStr = Console.ReadLine();
Console.WriteLine();
Console.Write("请输入当前车辆的位置(1 2 N):");
String positionStr = Console.ReadLine();
Console.WriteLine();
Console.Write("请输入指令(LMLMLMLMM):");
String insStr = Console.ReadLine();
Console.WriteLine();
//暂未处理异常信息
string[] strChar = mapStr.Split(' ');
int xMax = Int32.Parse(strChar[0]);
int yMax = Int32.Parse(strChar[1]);
strChar = positionStr.Split(' ');
int x = Int32.Parse(strChar[0]);
int y = Int32.Parse(strChar[1]);
string toward = strChar[2];
//构造地图信息
Map map = new Map(xMax, yMax);
Position position = new Position();
position.X = x;
position.Y = y;
position.TowardEnum = (TowardEnum)Enum.Parse(typeof(TowardEnum), toward);
try
{
Progress progress = new Progress(insStr, map, position);
Position resultPosition = progress.GetPosition();
Console.WriteLine(resultPosition.X + " " + resultPosition.Y + " " + resultPosition.TowardEnum.ToString());
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
Console.ReadKey();
}
}
//处理类
public class Progress
{
//指令集
private char[] instructions;
//位置信息
private Position position;
//地图边界
private Map map;
//车辆控制中心
private CarContorller contorller;
///
///指令
///地图
///当前位置
public Progress(string instruction, Map map, Position position)
{
this.instructions = instruction.ToCharArray();
this.position = position;
this.map = map;
}
///
///
public Position GetPosition()
{
this.contorller = new CarContorller(this.position, this.map);
Position resultPosition = new Position();
foreach (var item in instructions)
{
resultPosition = contorller.ExecInstruction(item);
}
return resultPosition;
}
}
//控制类
public class CarContorller
{
private Position position;
private Map map;
public CarContorller(Position position, Map map)
{
this.position = position;
this.map = map;
}
///
/// 当前位置
public Position ExecInstruction(char instruction)
{
switch (instruction)
{
case 'L':
this.position.TowardEnum = (TowardEnum)((int)(this.position.TowardEnum + 1) % 4);
break;
case 'R':
this.position.TowardEnum = (TowardEnum)((int)(this.position.TowardEnum + 3) % 4);
break;
case 'M':
this.Move();
break;
default:
throw new Exception("无法识别的指令" + instruction);
}
return this.position;
}
///
private void Move()
{
switch (this.position.TowardEnum)
{
case TowardEnum.N:
this.position.Y++;
break;
case TowardEnum.W:
this.position.X--;
break;
case TowardEnum.S:
this.position.Y--;
break;
case TowardEnum.E:
this.position.X++;
break;
default:
break;
}
if (this.position.X < 0 || this.position.X > map.XMax || this.position.Y < 0 || this.position.Y > map.YMax)
{
throw new Exception("数据错误,该车辆将走出地图边界!");
}
}
}
//地图边界
public class Map
{
//初始化右上角X坐标
private int xMax;
//初始化右上角Y坐标
private int yMax;
public int XMax
{
get { return xMax; }
set { xMax = value; }
}
public int YMax
{
get { return yMax; }
set { yMax = value; }
}
public Map(int xInit, int yInit)
{
this.xMax = xInit;
this.yMax = yInit;
}
}
//位置
public class Position
{
private int x;
public int X
{
get { return x; }
set { x = value; }
}
private int y;
public int Y
{
get { return y; }
set { y = value; }
}
private TowardEnum towardEnum;
public TowardEnum TowardEnum
{
get { return towardEnum; }
set { towardEnum = value; }
}
}
//朝向
public enum TowardEnum
{
N = 0,
W = 1,
S = 2,
E = 3
} } \`\`\\\`