课程 2:控制结构

  1. 三大控制结构:
      顺序结构分支结构循环结构
  2. 顺序结构: 顺序结构是程序中最基本的控制结构,指程序按照代码的先后顺序,从上到下、从左到右依次执行每一条语句。
    • 1.没有条件判断和跳转,所有语句都会被依次执行。
    • 2.是所有程序的基础,其他结构(如分支、循环)也常包含顺序结构。
        move()
        turn_left()
        move()
        put_beeper()

    上述代码会依次执行每一行:Karel先向前移动,然后左转,再向前移动,最后放置一个beeper。

  3. for循环: for 循环是一种用于已知重复次数可迭代对象的循环结构,适合遍历序列、集合等。
    • 常用于:需要对每个元素、每个数字、每个对象依次操作的场景。
    • 循环次数通常是确定的。
        for 变量 in 可迭代对象:
            # 循环体
            要重复执行的语句

    示例:

         # Karel向前移动5步
         for i in range(5):
             move()

    上述代码会让Karel向前移动5步。每次循环,Karel执行一次移动操作。

    区别: for 循环适合已知次数或遍历对象,while 循环适合次数不确定、依赖条件的重复。

  4. 嵌套循环: 嵌套循环是指在一个循环体内再包含另一个循环。常用于处理二维结构(如棋盘、表格等),可以让程序对每一行的每一列都进行操作。
    • 外层循环控制行,内层循环控制列。
    • 常见应用:遍历二维数组、绘制图形、处理网格等。
        for i in range(3):
            # 外层循环,控制行
            for j in range(4):
                # 内层循环,控制列
                print(i, j)

    上述代码会输出所有行列组合(共3×4=12次),即遍历一个3行4列的表格。

  5. while循环: while 循环是一种基于条件判断的循环结构,适用于循环次数不确定、需要根据某个条件反复执行的场景。
    • 每次循环前先判断条件,条件为真则执行循环体,否则结束循环。
    • 常用于:直到满足某个条件才停止的任务,如遇到障碍、收集完所有物品等。
        while 条件:
            # 循环体
            要重复执行的语句

    示例:

        while front_is_clear():
            move()

    上述代码会让Karel一直向前移动,直到遇到墙为止。只要前方畅通,就会继续移动。

    区别: for 循环适合已知次数的重复,while 循环适合次数不确定、依赖条件的重复。

  6. 循环的前置条件与后置条件:编写循环时最复杂的地方之一,就是你需要确保循环结束时的状态(后置条件)能够满足下一次循环开始时的要求(前置条件)。
    • 前置条件:在每次循环前先判断条件,只有条件为真才会执行循环体;
    • 后置条件:先执行一次循环体,然后判断条件,条件为真则继续循环。

    前置条件示例:使用while循环让Karel移动到墙边

        # 前置条件:每次循环前检查前方是否畅通
        while front_is_clear():
            move()

    在这个例子中,每次循环开始前都会检查前方是否畅通,只有前方没有墙时才会执行移动操作。

    后置条件示例:使用while循环让Karel移动到墙边

        # 后置条件:确保每次循环后Karel都移动到新位置
        while front_is_clear():
            move()

    在这个例子中,每次循环后Karel都会移动到新位置,确保下次循环时检查的是新的位置前方是否畅通,避免无限循环。

    循环状态一致性:确保循环前后状态匹配

        # 前置条件:Karel在起点,面向东
        while front_is_clear():
            move()
            # 后置条件:Karel移动到新位置,仍面向东(与前置条件一致)

    这个循环确保Karel在每次循环后都保持相同的方向,使得循环条件在下次检查时仍然有效。

  7. 栅栏柱错误: 栅栏柱错误(Fencepost Error),也叫“边界错误”或“off-by-one error”,是指在循环或计数时多算或少算了一次,常见于处理区间、数组下标等场景。
    • 常见原因:循环次数写错、区间端点包含/不包含混淆。
    • 例如:要在两端插柱子,柱子数比栅栏段数多1。
        # 例:让Karel向前移动5步
        for i in range(1,5):
            move()
        # 实际只移动了4步,漏掉了第5步

    避免方法:明确循环的起止条件,理解 range 的左闭右开特性,必要时多画图或举例验证。在Karel编程中,要特别注意移动步数的计算。

  8. 条件语句: 条件语句用于根据不同的条件执行不同的代码分支,是实现程序逻辑判断的基础。
    • 常用关键字:ifelifelse
    • 根据条件表达式的真假,选择性地执行某些语句。
        if 条件1:
            # 条件1为真时执行
        elif  条件2:
            # 条件2为真时执行
        else :
            # 以上条件都不满足时执行

    示例:

        if beepers_present():
            pick_beeper()
            move()
        else:
            turn_left()
            move()

    上述代码会根据当前位置是否有beeper来执行不同的操作:如果有beeper就收集并移动,如果没有beeper就左转后移动,实现了分支选择。

  9. match语句: match 语句是 Python 3.10 及以上版本引入的结构化模式匹配语句,类似于其他语言的 switch/case,但功能更强大。
    • 可以根据变量的不同值或结构,选择性地执行不同的代码块。
    • 支持对复杂数据结构(如元组、列表、字典等)进行模式匹配。
        match 变量:
            case 值1:
                # 变量等于值1时执行
            case 值2:
                # 变量等于值2时执行
            case _:
                # 其他情况

    示例:

        # 根据Karel的朝向执行不同动作
        direction = "north"
        match direction:
            case "north":
                move()
            case "south":
                turn_left()
                turn_left()
                move()
            case "east":
                turn_left()
                move()
            case _:
                put_beeper()

    上述代码会根据Karel的朝向执行不同的移动动作,实现了多分支选择。

  10. Karel编程中我们只使用if/else语句。
    作业2:修复拱桥