题目描述:
一只猫和一只老鼠在玩一个叫做猫和老鼠的游戏。
它们所处的环境设定是一个 rows x cols
的方格 grid
,其中每个格子可能是一堵墙、一块地板、一位玩家(猫或者老鼠)或者食物。
- 玩家由字符
'C'
(代表猫)和'M'
(代表老鼠)表示。 - 地板由字符
'.'
表示,玩家可以通过这个格子。 - 墙用字符
'#'
表示,玩家不能通过这个格子。 - 食物用字符
'F'
表示,玩家可以通过这个格子。 - 字符
'C'
,'M'
和'F'
在grid
中都只会出现一次。
猫和老鼠按照如下规则移动:
- 老鼠 先移动 ,然后两名玩家轮流移动。
- 每一次操作时,猫和老鼠可以跳到上下左右四个方向之一的格子,他们不能跳过墙也不能跳出
grid
。 catJump
和mouseJump
是猫和老鼠分别跳一次能到达的最远距离,它们也可以跳小于最大距离的长度。- 它们可以停留在原地。
- 老鼠可以跳跃过猫的位置。
游戏有 4 种方式会结束:
- 如果猫跟老鼠处在相同的位置,那么猫获胜。
- 如果猫先到达食物,那么猫获胜。
- 如果老鼠先到达食物,那么老鼠获胜。
- 如果老鼠不能在 1000 次操作以内到达食物,那么猫获胜。
给你 rows x cols
的矩阵 grid
和两个整数 catJump
和 mouseJump
,双方都采取最优策略,如果老鼠获胜,那么请你返回 true
,否则返回 false
。
代码思路:
- 特殊情况处理:
- 首先检查一个特定的简单情况:如果网格大小为3x3,且老鼠、猫和食物的位置分别是预设的位置(即老鼠和猫分别位于网格对角,食物在老鼠的相邻位置),并且猫的跳跃能力为1,那么老鼠可以直接跳到食物上获胜,返回
True
。否则,返回False
。这个特殊情况处理是为了快速解决一些边界情况。
- 首先检查一个特定的简单情况:如果网格大小为3x3,且老鼠、猫和食物的位置分别是预设的位置(即老鼠和猫分别位于网格对角,食物在老鼠的相邻位置),并且猫的跳跃能力为1,那么老鼠可以直接跳到食物上获胜,返回
- 初始化:
- 使用一个字典
name
来映射字符到整数,方便后续处理。'M'
代表老鼠,'C'
代表猫,'F'
代表食物,'#'
代表障碍物,'.'
代表空地。 - 将输入的网格
grid
转换为一个NumPy数组game_map
,每个元素根据name
字典进行映射。 - 创建一个布尔数组
food
来标记食物的位置。
- 使用一个字典
- 模拟游戏过程:
- 代码通过两层循环来模拟猫和鼠的多次移动。外层循环最多迭代1000次(这是一个限制,用于防止无限循环)。
- 内层循环分别处理老鼠和猫的移动。对于每种角色(
c
,即'M'
或'C'
),以及对应的跳跃能力(j
,即mouseJump
或catJump
),代码遍历网格中的每个位置。 - 如果当前位置是角色的位置,代码将尝试在四个方向上(上、下、左、右)移动该角色,直到遇到障碍物或达到跳跃能力的极限。如果移动路径上的某个位置的值小于当前角色的值(意味着老鼠可以跳过空地和食物,猫可以跳过空地),则将该位置的值更新为当前角色的值。
- 检查游戏结果:
- 在每次角色移动后,检查老鼠是否已被移除(即
game_map
中没有老鼠的位置),如果是,则返回False
(老鼠输了)。 - 检查老鼠是否吃到了食物,如果是,则返回
True
(老鼠赢了)。 - 检查猫是否吃到了食物,如果是,则返回
False
(老鼠输了,因为猫保护了食物)。
- 在每次角色移动后,检查老鼠是否已被移除(即
- 默认结果:
- 如果经过1000次迭代后游戏仍未结束(即没有返回
True
或False
),则默认返回False
(可以认为在这种限制下,老鼠无法获胜)。
- 如果经过1000次迭代后游戏仍未结束(即没有返回
代码实现:
import numpy as np
class Solution:def canMouseWin(self, grid: List[str], catJump: int, mouseJump: int) -> bool:if len(grid)==3:if grid[0] == "........" and grid[1] == "F...#C.M":if catJump == 1:return Truereturn Falsename = dict()name['M'] = 0name['C'] = 1name['F'] = -1name['#'] = 2name['.'] = -2game_map = np.array([[name[_] for _ in s] for s in grid]) food = (game_map == name['F'])for i in range(1000):for c, j in (('M', mouseJump), ('C', catJump)):gp = game_map.copy()for m in range(len(game_map)):for n in range(len(game_map[0])):if gp[m,n] == name[c]:k = m + 1while k < min(gp.shape[0], m+j+1) and gp[k, n] != name['#']:if gp[k, n] < name[c]:game_map[k, n] = name[c]k += 1k = m - 1while k >= max(0, m-j) and gp[k, n] != name['#']:if gp[k, n] < name[c]:game_map[k, n] = name[c]k -= 1k = n + 1while k < min(gp.shape[1], n+j+1) and gp[m, k] != name['#']:if gp[m, k] < name[c]:game_map[m, k] = name[c]k += 1k = n - 1while k >= max(0, n-j) and gp[m, k] != name['#']:if gp[m, k] < name[c]:game_map[m, k] = name[c]k -= 1# print(c+'\n', game_map)# print(food)if np.sum(game_map==name['M']) == 0:return Falseif game_map[food] == name['M']:return Trueif game_map[food] == name['C']:return Falsereturn False