1. 主页
  2. 文档
  3. 学习君土脚本
  4. 创建君土脚本代码块
  5. 循环吧代码

循环吧代码

编程语言可以很迅速方便地帮我们完成一些重复性的任务,从多个基本计算到几乎完成了很多类似工作的其他情况。现在, 我们看看君土脚本如何用循环结构来处理这种需求。

来, 一起循环

循环,循环,循环。一年四季往复, 音乐一遍又一遍播放和重复生产一个又一个的产品,与这些一样, 类似的情况存在于编程中。编程中的循环也是一直重复着去做一件事 – 此处循环便是编程中的术语.

让我们来想想下图,这位家长考虑为他的家庭做一周的食物计划,他或许就需要执行一段循环:

一段循环通常需要一个或多个条件:

  • 一个开始条件,它被初始化为一个特定的值 – 这是循环的起点(“开始:我没有食物”,上面的例子)。
  • 一个结束条件,这是循环停止的标准 – 通常计数器达到一定值。 以上所说的“我有足够的食物”吗? 假设他需要10份食物来养活他的家人。
  • 一个迭代器,这通常在每个连续循环上递增少量的计数器,直到达到退出条件。 我们以前没有明确说明,但是我们可以考虑一下成人能够每小时收集2份食物。 一小时后,他收集的食物量增加了两份,他检查他是否有足够的食物。 如果他已经达到10分(退出条件),他可以停止收集, 然后回家。

在伪代码中,这看起来就像下面这样:

循环(食物 = 0; 需要的食物 = 10) {
  若 (食物 = 需要的食物) {
    离开 循环;
    // 我们有足够的食物了,回家吧。
  } 别 {
    食物 += 2; // 花一个小时多收集两个食物。
    // 循环将会继续执行。
  }
}

所以需要的食物量定为10,家里目前有的数量为0。在循环的每次迭代中,我们检查家里的食物量是否等于他需要的量。 如果等于,我们可以退出循环。 如果小于,成人花一个小时收集两份食物,循环再次运行。

为何用循环?

在这一点上,您可能会了解循环中的高级概念,但您可能会认为“好的,但是,这有助于我编写更好的君土脚本代码?” 正如我们前面所说,循环所做的事情都是一样的,这对于快速完成重复任务是非常有用的。

通常,循环的每个连续迭代的代码将略有不同,这意味着您可以完成非常相似但略有区别的任务; 例如, 有很多不同的数需要计算,我们用同一种方式去计算这些数, 不是每一个数用不同的方式计算!

让我们来看一个例子来说明为什么循环是一件好事。 假设我们想在终端上打印10行随机数量的星号(:

*
*****
****
*
****
***
***
****
***
******
******

您现在不需要理解所有代码,但我们来看看这些代码:

  务 随机数(最大: 数): 数 {
    回 算.顶(算.随机() * 最大)
  }

  务 绘制星号() {
    常 打印行数 = 10;
    常 每行最多星数 = 15;
    为 (定 甲 = 0; 甲 < 打印行数; 甲++) {
      定 星数 = 随机数(每行最多星数);
      为 (定 乙 = 0; 乙 < 星数; 乙++) {
        进程.输出.写('*');
      }
      进程.输出.写("\n");
    }
  }

  绘制星号();
  • 随机数(),我们编写的函数,它返回一个 0 到 最大-1 间的整数。

您应该有一个基本的想法 – 我们使用两个循环嵌套来运行这个代码的迭代。 无论我们打印10行,1000还是10,000,所需的代码量将是相同的。 只有一个数字必须改变。

如果我们在这里没有使用循环,我们必须为我们想要打印重复以下代码:

进程.输出.写('*\n');
进程.输出.写('**\n');
......

这将非常无聊而且很难维持高速。 循环真的相当好用。

循环的标准

我们开始探索一些特定的循环结构。 第一个,你会经常使用到它,为/*for*/循环 – 以下是循环的语法:

为 (初始化器; 退出条件; 最后表达式) {
  // 运行这里的代码
}

我们有:

  1. 关键字,后跟一个括号。
  2. 在括号内,我们有三个项目,以分号分隔:
    1. 一个初始化器 – 这通常是一个设置为一个数字的变量,它被递增来计算循环运行的次数。它也有时被称为计数变量
    2. 一个退出条件 -如前面提到的,这个定义循环何时停止循环。这通常是一个表现为比较运算符的表达式,用于查看退出条件是否已满足的测试。
    3. 一个最后表达式 – 每次循环经过完整的迭代时,都会对其进行计算(或运行)。它通常用于增加(或在某些情况下减少)计数器变量,使其更接近退出条件值。
  3. 一个包含代码块的花括号 – 每次循环迭代时都会运行这个代码。

让我们看一个真实的例子,这样我们可以更清楚地想象它们的作用。

定 课程 = ['君土脚本编程入门', '超文本入门', '样式表入门', '数据结构', '软件工程'];
定 信息 = '我要学习的课程有';
为 (定 甲 = 0; 甲 < 课程.长; 甲++) {
  信息 += 课程[甲] + ', ';
}
控制台.日志(信息);

这将给我们以下输出:

我要学习的课程有君土脚本编程入门, 超文本入门, 样式表入门, 数据结构, 软件工程, 

这显示了一个循环用于迭代数组中的项,并对每个项执行一些操作——这是君土脚本中非常常见的模式。 这里:

  1. 迭代器从0开始(定 甲 = 0)。
  2. 循环被告知一直运行到不再小于课程数组的长度为止。这一点很重要——退出条件是循环仍然运行的条件。在这个例子中,当甲 < 课程.长仍然为真,循环仍然会运行。
  3. 在循环中,我们将当前的循环项(课程[甲]课程[当前下标的任何东西])以及逗号和空格连接到 信息 变量的末尾。 所以:
    1. 在第一次运行中,甲 = 0,所以课程[0] +','(课程[0]的值是”君土脚本编程入门”) 将被连接到信息上。
    2. 在第二次运行中,甲 = 1,所以课程[1] +','(课程[1]的值是”超文本入门”) 将被连接到信息上。
    3. 等等。 每次循环运行后,1将被添加到甲(甲 ++),然后流程将再次启动。
  4. 当等于课程.长时,循环将停止,代码运行将移动到循环下面的下一个代码位。

注意: 我们将退出条件设为甲 < 课程.长,而不是甲 <= 课程.长,因为计算机从0开始计数,而不是1——我们从0开始,一直到甲 = 4(最后一个数组项的下标)。课程.长返回5, 数组中有5个项目, 我们不希望达到甲 = 5, 因为这将返回未定义的最后一个项目(没有索引为5的数组项目)。所以我们想要比课程.长少1(甲 < 课程.长),而不是课程.长(甲 <= 课程.长)。

意:  退出条件的一个常见错误是使它们使用“等于”(===)而不是说“小于或等于”(<)。 如果我们想要运行我的循环到甲 = 4,退出条件将需要是甲 < 课程.长。如果我们设置为甲 === 课程.长 -1,循环将不会运行,因为在第一次循环迭代时 甲 不等于4,所以循环会立即停止。

我们留下的一个小问题是最后的输出句子形式不是很好:

我要学习的课程有君土脚本编程入门, 超文本入门, 样式表入门, 数据结构, 软件工程,

理想情况下,我们想改变最后循环迭代中的拼接,以便在句子末尾没有逗号。 嗯,没问题 – 我们可以很高兴地在我们的循环中插入一个条件来处理这种特殊情况:

为 (定 甲 = 0; 甲 < 课程.长; 甲++) {
  若 (甲 === 课程.长 - 1) {
    信息 += '和' + 课程[甲] + '。';
  } 别 {
    信息 += 课程[甲] + ', ';
  }
}

警告:对于循环——就像所有循环一样——你必须确保初始化器是递增的,或者是递减的(取决于具体情况),这样它最终会到达条件不为真的点。如果没有,循环将永远继续下去,运行环境将迫使它停止,或者它将崩溃。这被称为无限循环。

使用断退出循环

如果要在所有迭代完成之前退出循环,可以使用 断/*break*/ 语句。 当我们学习 语句时,我们已经在上一篇文章中遇到过这样的情况 – 当 语句中符合输入表达式的情况满足时, 语句立即退出 语句并移动到代码之后。

循环中也相同 – 语句将立即退出循环,并执行跟随它的任何代码。

说我们想搜索一系列联系人和电话号码,只返回我们想要找的号码?

  定 联系人 = ['张三:2232322', '李四:3453456', '王五:7654322', '赵六:9998769', '孙七:9384975'];
  务 查找(查找名字: 文) {
    为 (定 甲 = 0; 甲 < 联系人.长; 甲++) {
      定 联系人分解 = 联系人[甲].分(':');
      若 (联系人分解[0] === 查找名字) {
        控制台.日志(联系人分解[0] + '的号码是' + 联系人分解[1] + '。');
        断;
      } 别 若 (甲 === 联系人.长 - 1) {
        控制台.日志('没有找到联系人');
      }
    }
  }

  查找('张三');
  查找('周八');
  1. 首先我们有一些变量定义 – 我们有一个联系信息数组,每个项目是一个字符串,包含一个以冒号分隔的名字和电话号码。
  2. 接下来,我们定义一个函数 查找,参数为 查找名字
  3. 现在是有趣的部分,循环:
    1. 我们的计数器开始时为0,直到计数器不再小于联系人.长,并在循环的每次迭代之后将甲递增1。
    2. 在循环中,我们首先将当前联系人(联系人 [甲])用冒号字符拆分,并将生成的两个值存储在名为 联系人分解 的数组中。
    3. 然后,我们使用条件语句来测试 联系人分解[0](联系人名字)是否等于输入的查找名字。 如果是,我们显示一个字符串来报告联系人的号码,并使用来结束循环。
  4. (联系人.长 - 1) 次迭代后,如果联系人姓名与输入的搜索不符,则显示“未找到联系人”,循环继续迭代, 结束。

使用续跳过迭代

续/*continue*/ 语句以类似断的方式工作,但不是完全跳出循环,而是跳过当前迭代, 执行下一个迭代。 我们来看另外一个例子,它把一个数字作为一个输入,只返回小于等于这个数字并且开平方之后为整数的数字(整数)。

  务 平方数(输入数:数) {
    定 输出信息 = '';
    为 (定 甲 = 1; 甲 <= 输入数; 甲++) {
      定 平方根 = 算.方根(甲);
      若 (算.底(平方根) !== 平方根) {
        续;
      }
    
      输出信息 += 甲 + ' ';
    }

    控制台.日志(输出信息);
  }

  平方数(1);
  平方数(20);
  平方数(100);

这是输出:

1 
1 4 9 16 
1 4 9 16 25 36 49 64 81 100 
  1. 循环给定一个从1开始的计数器(在这种情况下,我们对0不感兴趣),一个退出条件,当计数器大于输入输入数时循环将停止,并且迭代器的计数器将每次增加1。
  2. 在循环中,我们使用算.方根(甲)找到每个数字的平方根,然后测试平方根是否是一个整数,通过判断当它被向下取整时,它是否与自身相同(这是算.底(...)对传递的数字的作用)。
  3. 如果平方根和平方根向下取整的不相等(!==),则表示平方根不是整数,因此我们对此不感兴趣。 在这种情况下,我们使用语句跳过当前循环而执行下一个循环迭代,而不在任何地方记录该数字。
  4. 如果平方根是一个整数,我们完全跳过块,所以语句不被执行; 相反,我们将当前值加上一个空格连接到输出信息的末尾。

复语句和行复语句

 不是君土脚本中唯一可用的循环类型。 实际上还有很多其他的,虽然你现在不需要了解所有这些,但有必要看看其他几个的结构,这样你就可以在稍微不同的方式中识别出相同的功能。

首先,我们来看看 复/*while*/ 循环。 这个循环的语法如下所示:

初始化器
复 (退出条件) {
  // 运行这里的代码

  最后表达式
}

除了在循环之前设置初始化器变量,并且在运行代码之后,循环中包含 最后表达式 ,而不是这两个项目被包含在括号中,这与以前的循环非常类似。 退出条件包含在括号内,前面是关键字而不是

同样的三个项目仍然存在,它们仍然以与循环中相同的顺序定义 – 这是有道理的,因为您必须先定义一个初始化器,然后才能检查它是否已到达退出条件; 在循环中的代码运行(迭代已经完成)之后,运行最后的条件, 再次检查它是否已到达退出条件。

我们再来看看我们的课程列表示例,但是重写了一个循环:

  定 甲 = 0;
  复 (甲 < 课程.长) {
    若 (甲 === 课程.长 - 1) {
      信息 += '和' + 课程[甲] + '。';
    } 别 {
      信息 += 课程[甲] + ', ';
    }
    甲++;
  }

注意: 它正如我们期望的那样工作。

行/*do*/...复/*while*/ 循环与非常类似, 但提供了结构的一个变体:

初始化器
行 {
  // 运行这里的代码

  最后表达式
} 复 (退出条件)

在这种情况下,在循环开始之前,初始化器先重新开始。 关键字直接在包含要运行代码的花括号和终止条件之前。

这里的区别在于,条件出现在其他内容之后,用圆括号括起来,前面有一个关键字。 在 行 ... 复 循环中,花括号中的代码总是在检查之前运行一次,以查看是否应该再次执行(在中,检查首先出现,因此代码可能永远不会执行)。

我们再次重写我们的课程列表示例,以使用行...复循环:

  定 甲 = 0;
  行 {
    若 (甲 === 课程.长 - 1) {
      信息 += '和' + 课程[甲] + '。';
    } 别 {
      信息 += 课程[甲] + ', ';
    }
    甲++;
  } 复 (甲 < 课程.长);

注意: 再一次,它正如我们期望的那样工作。

重要: 使用 行...复 — 所有循环都一样 — 你必须保证初始变量是迭代的,那么它才会逐渐地达到退出条件。不然,它将会永远循环下去, 要么系统强制终止它,要么它自己会崩溃. 这称为无限循环.

应该使用哪种循环类型?

对于基本用途,行复循环大部分可互换。 他们都可以用来解决相同的问题,你使用哪一个将在很大程度上取决于你的个人偏好 – 哪一个你最容易记住或是最直观的。 我们再来看看他们。

首先是 :

为 (初始化器; 退出条件; 最后表达式) {
  // 运行这里的代码
}

:

初始化器
复 (退出条件) {
  // 运行这里的代码

  最后表达式
}

最后是 行...复:

初始化器
行 {
  // 运行这里的代码

  最后表达式
} 复 (退出条件)

我们建议使用,因为它可能是最简单地帮你记住一切 – 初始化程序,退出条件和最后表达式都必须整齐地放入括号,所以很容易看到他们在哪里并检查你没有丢失他们。

注:还有其他循环类型/特性,这些特性在 高级/专门 的情况下是有用的,超出了本文的范围。如果您想进一步了解循环学习,请阅读我们的高级循环和迭代指南。

结论

本文向您展示了君土脚本循环代码背后的基本概念和不同的选项。现在您应该清楚为什么循环是处理重复代码的好机制,并渴望在您自己的例子中使用它们!

如果您有什么不明白的地方,可以再通读一遍,或者联系我们寻求帮助。