Python 练习讲解 · 07 / 25

模拟法:按指令移动坐标

不用猜最终结果,逐条执行指令,让程序里的状态跟着现实过程变化。

要学习的知识点

题目

练习 7:模拟 U/D/L/R 方向移动,输出终点坐标和移动步数。

坐标约定:向右 x+1,向左 x-1,向上 y+1,向下 y-1。

输入一行由 U、D、L、R 组成的方向序列。

参考程序:ex07.py;空白练习:lx07.py。

完整代码

以下内容与 ex07.py 一致,可对照右侧讲解阅读。

"""练习 7:模拟 U/D/L/R 方向移动,输出终点坐标和移动步数。
坐标约定:向右 x+1,向左 x-1,向上 y+1,向下 y-1。
输入一行由 U、D、L、R 组成的方向序列。

学习说明:
- strip() 去掉首尾空白,upper() 让小写指令也可以使用。
- x、y 从原点 (0, 0) 开始;moves 字典把方向映射到坐标变化量 (dx, dy)。
- for 循环逐个读取指令;不认识的字符跳过,合法指令则更新坐标和步数。
- 最终坐标表示位置;steps 统计实际执行的有效移动数。
"""
directions = input().strip().upper()
x = y = steps = 0
moves = {"U": (0, 1), "D": (0, -1), "L": (-1, 0), "R": (1, 0)}

for direction in directions:
    if direction not in moves:
        continue
    dx, dy = moves[direction]
    x += dx
    y += dy
    steps += 1

print("position:", x, y)
print("steps:", steps)

进阶写法

这版与初学版解决同一道题,使用更精炼的语法或标准库工具。

进阶源码:ex07_adv.py

"""练习 7 进阶版:用生成器表达式分别累计横纵坐标变化。"""
directions = input().strip().upper()
moves = {"U": (0, 1), "D": (0, -1), "L": (-1, 0), "R": (1, 0)}

x = sum(moves[direction][0] for direction in directions if direction in moves)
y = sum(moves[direction][1] for direction in directions if direction in moves)
steps = sum(1 for direction in directions if direction in moves)

print("position:", x, y)
print("steps:", steps)

生成器表达式逐条提供合法方向的坐标变化量,sum() 分别求横向和纵向总变化;第三个 sum() 统计有效指令数。

运行结果

示例输入:

URRDL

程序输出:

position: 1 0
steps: 5

逐个认识函数

下表根据程序中实际调用的函数和方法整理;自定义函数的实现与算法细节见后续说明。

函数形式功能与返回值注意事项
input(prompt='')读取一行文本,返回 str;若提供 prompt 会先显示提示。返回值默认是字符串,计算前通常要做类型转换。
str.strip(chars=None)返回去掉首尾空白或指定字符的新字符串。不会删除字符串中间的字符。
str.upper()返回转成大写的新字符串。原字符串不变。
print(*objects, sep=' ', end='\n')把对象转换为文本显示;返回 None。默认空格分隔并在末尾换行。

算法原理:维护当前状态

把位置 (x, y) 看作游戏角色当前状态。每条指令对应一个变化量:U 是 (0,1),R 是 (1,0) 等。拿到一条指令就把变化量加到坐标上。整个循环结束时,变量保存的就是终点。

  1. 读入整串指令,去掉首尾空白并统一大写。
  2. 初始化位置和步数为 0,建字典记录方向对应的坐标变化。
  3. 逐字符查字典;非法字符按程序约定跳过。
  4. 将 dx、dy 加到 x、y,并把有效步数加 1。

本题用到的方法

写法参数与返回值用法提示
input()读一行,返回字符串。本程序把整行当方向序列。
str.strip()默认移除字符串首尾空白,返回新字符串。不会删除中间字符。
str.upper()返回大写形式的新字符串。让 u/r 也能作为合法指令;原字符串不被修改。
dict[key]按键取对应值;键不存在时会报 KeyError。因此程序先用 if direction not in moves 检查,再取值。
print(...)显示一个或多个对象,返回 None。两个坐标变量分别输出,中间默认空格。

字典的值是二元组,如 (0, 1)。dx, dy = moves[direction] 称为解包,按位置把两个元素分别赋给变量。

重要约定与变化

程序只统计合法的四个方向;其他字符使用 continue 跳过本轮循环,既不改变坐标也不增加步数。若题目要求非法输入报错,就要把 continue 改成错误提示或异常。

试试指令 URDL:走一圈后回到 (0,0),但步数仍是 4。位置和已走步数是两种不同信息。

代码如何运行

  1. 先按左侧题目给出的格式输入数据;程序通过 input() 读取,并在需要时转换数据类型。
  2. 程序自上而下执行语句;遇到条件、循环或函数调用时,按照右侧算法说明更新变量和处理数据。
  3. 最后由 print() 输出计算结果。可将左侧示例输入与输出逐项对照。

先自己跟踪一组小数据,记录循环前后变量的值;这比只看最终答案更容易理解程序。

自己动手试一试

试试 URDL 回到原点但步数增加;输入小写方向或非法字符,观察程序的约定。

先在 lx07.py 中独立完成,再运行参考程序比较结果。修改程序时一次只改一个条件或步骤。