# 2069. 模拟行走机器人 II (Medium)

## 问题描述

[2069. 模拟行走机器人 II][link] (Medium)

[link]: https://leetcode.cn/problems/walking-robot-simulation-ii/

给你一个在 XY 平面上的 `width x height` 的网格图， **左下角** 的格子为 `(0, 0)` ， **右上角** 的格子
为 `(width - 1, height - 1)` 。网格图中相邻格子为四个基本方向之一（ `"North"`， `"East"`， `"South"`
和 `"West"`）。一个机器人 **初始** 在格子 `(0, 0)` ，方向为 `"East"` 。

机器人可以根据指令移动指定的 **步数** 。每一步，它可以执行以下操作。

1. 沿着当前方向尝试 **往前一步** 。
2. 如果机器人下一步将到达的格子 **超出了边界** ，机器人会 **逆时针** 转 90 度，然后再尝试往前一步。

如果机器人完成了指令要求的移动步数，它将停止移动并等待下一个指令。

请你实现 `Robot` 类：

- `Robot(int width, int height)` 初始化一个 `width x height` 的网格图，机器人初始在 `(0, 0)` ，方向
朝 `"East"` 。
- `void step(int num)` 给机器人下达前进 `num` 步的指令。
- `int[] getPos()` 返回机器人当前所处的格子位置，用一个长度为 2 的数组 `[x, y]` 表示。
- `String getDir()` 返回当前机器人的朝向，为 `"North"` ， `"East"` ， `"South"` 或者 `"West"` 。

**示例 1：**

![example-1](https://pic-upyun.zwyyy456.tech/smms/2023-12-26-065459.png)

```
输入：
["Robot", "step", "step", "getPos", "getDir", "step", "step", "step", "getPos", "getDir"]
[[6, 3], [2], [2], [], [], [2], [1], [4], [], []]
输出：
[null, null, null, [4, 0], "East", null, null, null, [1, 2], "West"]

解释：
Robot robot = new Robot(6, 3); // 初始化网格图，机器人在 (0, 0) ，朝东。
robot.step(2);  // 机器人朝东移动 2 步，到达 (2, 0) ，并朝东。
robot.step(2);  // 机器人朝东移动 2 步，到达 (4, 0) ，并朝东。
robot.getPos(); // 返回 [4, 0]
robot.getDir(); // 返回 "East"
robot.step(2);  // 朝东移动 1 步到达 (5, 0) ，并朝东。
                // 下一步继续往东移动将出界，所以逆时针转变方向朝北。
                // 然后，往北移动 1 步到达 (5, 1) ，并朝北。
robot.step(1);  // 朝北移动 1 步到达 (5, 2) ，并朝 北 （不是朝西）。
robot.step(4);  // 下一步继续往北移动将出界，所以逆时针转变方向朝西。
                // 然后，移动 4 步到 (1, 2) ，并朝西。
robot.getPos(); // 返回 [1, 2]
robot.getDir(); // 返回 "West"

```

**提示：**

- `2 <= width, height <= 100`
- `1 <= num <= 10⁵`
- `step` ， `getPos` 和 `getDir` **总共** 调用次数不超过 `10⁴` 次。


## 解题思路

这是一道有点麻烦的模拟题，但其实注意到两点就不难了：

1. 机器人只会位于网格最外层的这一圈上；
2. 我们可以记录机器人总共移动了多少步，这样就可以以 $(0, 0)$ 为起点进行计算，而不需要使用机器人的上一个位置；

## 代码

```cpp
class Robot {
  public:
    Robot(int width, int height) {
        wid_ = width;
        hei_ = height;
    }

    void step(int num) {
        total += num;
        if (total == 0) {
            return;
        }
        int realmove = total % (wid_ - 1 + hei_ - 1 + wid_ - 1 + hei_ - 1);
        if (realmove == 0) {
            direct = 3;
            posx = 0;
            posy = 0;
        } else if (realmove > 0 && realmove <= wid_ - 1) {
            direct = 0;
            posx = realmove;
            posy = 0;
        } else if (realmove > wid_ - 1 && realmove <= wid_ - 1 + hei_ - 1) {
            posx = wid_ - 1;
            posy = realmove - (wid_ - 1);
            direct = 1;
        } else if (realmove > wid_ - 1 + hei_ - 1 && realmove <= wid_ - 1 + hei_ - 1 + wid_ - 1) {
            posy = hei_ - 1;
            posx = wid_ - 1 - (realmove - (wid_ - 1 + hei_ - 1));
            direct = 2;
        } else {
            posx = 0;
            posy = hei_ - 1 - (realmove - (wid_ - 1 + hei_ - 1 + wid_ - 1));
            direct = 3;
        }
    }

    vector<int> getPos() {
        return {posx, posy};
    }

    string getDir() {
        switch (direct % 4) {
        case 0:
            return "East";
        case 1:
            return "North";
        case 2:
            return "West";
        case 3:
            return "South";
        }
        return "";
    }

  private:
    int posx = 0;
    int posy = 0;
    int direct = 0;
    int wid_;
    int hei_;
    int total = 0;
};
```
