元胞自动机的头像

编程导论 :: 2 从执行中学习

2 从执行中学习
5
2 从执行中学习
2.1 修改并执行
2.1 修改并执行
2.2 HTML语言
2.2 HTML语言
2.3 轻松涂鸦
2.3 轻松涂鸦
2.4 其他语言
2.4 其他语言
2.5 程序的表达形式
2.5 程序的表达形式
上期回顾
上期回顾
顺序执行
顺序执行
计算2×2
计算2×2
计算3÷2
计算3÷2
画矩形
画矩形
非顺序执行
非顺序执行
计算器
计算器
看不懂程序
看不懂程序
婴儿阅读
婴儿阅读
HTML语法
HTML语法
其他文档
其他文档
MDN文档
MDN文档
执行结果
执行结果
绘制圆圈
绘制圆圈
计算11-5
计算11-5
几何图形
几何图形
矩形框
矩形框
加粗线条
加粗线条
换个颜色
换个颜色
圆圈
圆圈
圆弧
圆弧
画奥运五环
画奥运五环
不同语言
不同语言
VBScript语言
VBScript语言
Python语言
Python语言
C语言
C语言
探索JavaScript
探索JavaScript
表达形式
表达形式
自然语言
自然语言
符号系统
符号系统
计算机语言
计算机语言
目标是核心
目标是核心
形式转换
形式转换
奥运五环
奥运五环
探索织布机
探索织布机
暂告一段落
暂告一段落
素材来源
素材来源
单集封面
单集封面

编程导论 :: 2 从执行中学习

2022-08-29
48 次观看
2 讨论
元胞自动机的头像
元胞自动机
粉丝:5
主题:6
描述:10
例子:18
类比:1
验证:4
其他:4
字数:19041

编程导论 :: 2 从执行中学习

2022-08-29
48 次观看
2 讨论
元胞自动机的头像
元胞自动机
粉丝:5
元胞自动机的头像
元胞自动机
粉丝:5
主题:6
描述:10
例子:18
类比:1
验证:4
其他:4
字数:19041

2 从执行中学习

接续 上期回顾

上期的结尾,我们编写了一个计算机程序,计算1+1的结果,本期将以此为切入点,进行深入探索。

2.1 修改并执行

顺序执行

上期的程序,只实现了一个目标,计算1+1的结果,如果想接着计算2×2的结果,可以把这个目标也写上,两个目标会按先后顺序,依次完成。

计算2×2 顺序执行

例如,用文本编辑器(例如记事本)打开上期的程序文件,并修改为以下内容:

<script>
document.write(1+1)
document.write("<hr>")
document.write(2*2)
</script>

保存后,用浏览器打开,可以看到结果为2和4。

计算3÷2 顺序执行

如果还要计算3÷2的结果怎么办?依葫芦画瓢,修改为以下内容:

<script>
document.write(1+1)
document.write("<hr>")
document.write(2*2)
document.write("<hr>")
document.write(3/2)
</script>

保存后,用浏览器打开,可以看到结果为2、4、1.5。

画矩形 顺序执行

如果想要画几个矩形,可以修改为以下内容:

<canvas id="rects" width="500" height="500">

<script>
        my_canvas = document.getElementById("rects")
        my_context = my_canvas.getContext("2d")

        my_context.fillStyle = "red"
        my_context.fillRect(0, 0, 100, 250)
        my_context.fillStyle = "green"
        my_context.fillRect(0+50, 0+50, 100, 250)
        my_context.fillStyle = "blue"
        my_context.fillRect(0+50+50, 0+50+50, 100, 250)
</script>

保存后,用浏览器打开,可以看到红绿蓝三个部分重叠的矩形。

非顺序执行

当需要实现的目标比较复杂的时候,我们可以通过一些方式来编写非顺序执行的程序。

计算器 非顺序执行

例如,这个计算器程序总是等待用户的点击后才执行相应的功能:

<div class="calculator">
  <div class="input" id="input"></div>
  <div class="buttons">
    <div class="operators">
      <div>+</div>
      <div>-</div>
      <div>&times;</div>
      <div>&divide;</div>
    </div>
    <div class="leftPanel">
      <div class="numbers">
        <div>7</div>
        <div>8</div>
        <div>9</div>
      </div>
      <div class="numbers">
        <div>4</div>
        <div>5</div>
        <div>6</div>
      </div>
      <div class="numbers">
        <div>1</div>
        <div>2</div>
        <div>3</div>
      </div>
      <div class="numbers">
        <div>0</div>
        <div>.</div>
        <div id="clear">C</div>
      </div>
    </div>
    <div class="equal" id="result">=</div>
  </div>
</div>




<style>
body {
  width: 506px;
  margin: 4% auto;
  font-family: 'Source Sans Pro', sans-serif;
  letter-spacing: 5px;
  font-size: 1.8rem;
  -moz-user-select: none;
  -webkit-user-select: none;
  -ms-user-select: none;
}

.calculator {
  padding: 20px;
  -webkit-box-shadow: 0px 1px 4px 0px rgba(0, 0, 0, 0.2);
  box-shadow: 0px 1px 4px 0px rgba(0, 0, 0, 0.2);
  border-radius: 1px;
}

.input {
  border: 1px solid #ddd;
  border-radius: 1px;
  height: 60px;
  padding-right: 15px;
  padding-top: 10px;
  text-align: right;
  margin-right: 6px;
  font-size: 2.5rem;
  overflow-x: auto;
  transition: all .2s ease-in-out;
}

.input:hover {
  border: 1px solid #bbb;
  -webkit-box-shadow: inset 0px 1px 4px 0px rgba(0, 0, 0, 0.2);
  box-shadow: inset 0px 1px 4px 0px rgba(0, 0, 0, 0.2);
}

.buttons {}

.operators {}

.operators div {
  display: inline-block;
  border: 1px solid #bbb;
  border-radius: 1px;
  width: 80px;
  text-align: center;
  padding: 10px;
  margin: 20px 4px 10px 0;
  cursor: pointer;
  background-color: #ddd;
  transition: border-color .2s ease-in-out, background-color .2s, box-shadow .2s;
}

.operators div:hover {
  background-color: #ddd;
  -webkit-box-shadow: 0px 1px 4px 0px rgba(0, 0, 0, 0.2);
  box-shadow: 0px 1px 4px 0px rgba(0, 0, 0, 0.2);
  border-color: #aaa;
}

.operators div:active {
  font-weight: bold;
}

.leftPanel {
  display: inline-block;
}

.numbers div {
  display: inline-block;
  border: 1px solid #ddd;
  border-radius: 1px;
  width: 80px;
  text-align: center;
  padding: 10px;
  margin: 10px 4px 10px 0;
  cursor: pointer;
  background-color: #f9f9f9;
  transition: border-color .2s ease-in-out, background-color .2s, box-shadow .2s;
}

.numbers div:hover {
  background-color: #f1f1f1;
  -webkit-box-shadow: 0px 1px 4px 0px rgba(0, 0, 0, 0.2);
  box-shadow: 0px 1px 4px 0px rgba(0, 0, 0, 0.2);
  border-color: #bbb;
}

.numbers div:active {
  font-weight: bold;
}

div.equal {
  display: inline-block;
  border: 1px solid #3079ED;
  border-radius: 1px;
  width: 17%;
  text-align: center;
  padding: 127px 10px;
  margin: 10px 6px 10px 0;
  vertical-align: top;
  cursor: pointer;
  color: #FFF;
  background-color: #4d90fe;
  transition: all .2s ease-in-out;
}

div.equal:hover {
  background-color: #307CF9;
  -webkit-box-shadow: 0px 1px 4px 0px rgba(0, 0, 0, 0.2);
  box-shadow: 0px 1px 4px 0px rgba(0, 0, 0, 0.2);
  border-color: #1857BB;
}

div.equal:active {
  font-weight: bold;
}
</style>



<script>
"use strict";

var input = document.getElementById('input'), // input/output button
  number = document.querySelectorAll('.numbers div'), // number buttons
  operator = document.querySelectorAll('.operators div'), // operator buttons
  result = document.getElementById('result'), // equal button
  clear = document.getElementById('clear'), // clear button
  resultDisplayed = false; // flag to keep an eye on what output is displayed

// adding click handlers to number buttons
for (var i = 0; i < number.length; i++) {
  number[i].addEventListener("click", function(e) {

    // storing current input string and its last character in variables - used later
    var currentString = input.innerHTML;
    var lastChar = currentString[currentString.length - 1];

    // if result is not diplayed, just keep adding
    if (resultDisplayed === false) {
      input.innerHTML += e.target.innerHTML;
    } else if (resultDisplayed === true && lastChar === "+" || lastChar === "-" || lastChar === "×" || lastChar === "÷") {
      // if result is currently displayed and user pressed an operator
      // we need to keep on adding to the string for next operation
      resultDisplayed = false;
      input.innerHTML += e.target.innerHTML;
    } else {
      // if result is currently displayed and user pressed a number
      // we need clear the input string and add the new input to start the new opration
      resultDisplayed = false;
      input.innerHTML = "";
      input.innerHTML += e.target.innerHTML;
    }

  });
}

// adding click handlers to number buttons
for (var i = 0; i < operator.length; i++) {
  operator[i].addEventListener("click", function(e) {

    // storing current input string and its last character in variables - used later
    var currentString = input.innerHTML;
    var lastChar = currentString[currentString.length - 1];

    // if last character entered is an operator, replace it with the currently pressed one
    if (lastChar === "+" || lastChar === "-" || lastChar === "×" || lastChar === "÷") {
      var newString = currentString.substring(0, currentString.length - 1) + e.target.innerHTML;
      input.innerHTML = newString;
    } else if (currentString.length == 0) {
      // if first key pressed is an opearator, don't do anything
      console.log("enter a number first");
    } else {
      // else just add the operator pressed to the input
      input.innerHTML += e.target.innerHTML;
    }

  });
}

// on click of 'equal' button
result.addEventListener("click", function() {

  // this is the string that we will be processing eg. -10+26+33-56*34/23
  var inputString = input.innerHTML;

  // forming an array of numbers. eg for above string it will be: numbers = ["10", "26", "33", "56", "34", "23"]
  var numbers = inputString.split(/\+|\-|\×|\÷/g);

  // forming an array of operators. for above string it will be: operators = ["+", "+", "-", "*", "/"]
  // first we replace all the numbers and dot with empty string and then split
  var operators = inputString.replace(/[0-9]|\./g, "").split("");

  console.log(inputString);
  console.log(operators);
  console.log(numbers);
  console.log("----------------------------");

  // now we are looping through the array and doing one operation at a time.
  // first divide, then multiply, then subtraction and then addition
  // as we move we are alterning the original numbers and operators array
  // the final element remaining in the array will be the output

  var divide = operators.indexOf("÷");
  while (divide != -1) {
    numbers.splice(divide, 2, numbers[divide] / numbers[divide + 1]);
    operators.splice(divide, 1);
    divide = operators.indexOf("÷");
  }

  var multiply = operators.indexOf("×");
  while (multiply != -1) {
    numbers.splice(multiply, 2, numbers[multiply] * numbers[multiply + 1]);
    operators.splice(multiply, 1);
    multiply = operators.indexOf("×");
  }

  var subtract = operators.indexOf("-");
  while (subtract != -1) {
    numbers.splice(subtract, 2, numbers[subtract] - numbers[subtract + 1]);
    operators.splice(subtract, 1);
    subtract = operators.indexOf("-");
  }

  var add = operators.indexOf("+");
  while (add != -1) {
    // using parseFloat is necessary, otherwise it will result in string concatenation :)
    numbers.splice(add, 2, parseFloat(numbers[add]) + parseFloat(numbers[add + 1]));
    operators.splice(add, 1);
    add = operators.indexOf("+");
  }

  input.innerHTML = numbers[0]; // displaying the output

  resultDisplayed = true; // turning flag if result is displayed
});

// clearing the input on press of clear
clear.addEventListener("click", function() {
  input.innerHTML = "";
})
</script>

<p><a href="https://codepen.io/lalwanivikas/pen/eZxjqo">
    https://codepen.io/lalwanivikas/pen/eZxjqo
</a></p>
提问 看不懂程序

一定会有人问:上面这些写的是什么?我怎么完全看不懂啊?

其实看不懂就对了,如果初学者立马就能看懂计算机程序,那简直是聪明得可怕。

2.2 HTML语言

婴儿阅读

就像刚出生的婴儿,一般看不懂文章,因为婴儿还没有学会任何语言。

同样的,初学者一般也看不懂计算机程序,因为初学者也还没有学会计算机语言。

HTML语法

前面展示的几个程序是用一种叫做「HTML」的计算机语言编写的。既然是语言,那就有标准的语法规则和行文格式,现在主流的HTML标准是由名叫「WHATWG」的组织发布的,在其官方网站上有详细的语法规范

其他文档

但是语法规范对于初学者而言是比较难懂的,我们可以参考互联网上其他更简单的文档。

MDN文档 其他文档

例如,这篇MDN文档讲解了<script>的用法:

https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/script

而这篇文档讲解了 document.write 的用法:

https://developer.mozilla.org/zh-CN/docs/Web/API/Document/write

执行结果

虽然有丰富的文档,但是实际执行程序,然后观察执行结果才是学习计算机语言最快的方法。

绘制圆圈 执行结果

例如,这篇文档讲解了如何绘制圆圈,我们可以执行试试:

https://developer.mozilla.org/zh-CN/docs/Web/API/CanvasRenderingContext2D/arc#javascript

<canvas id="circle" width="500" height="500">

<script>
        my_canvas = document.getElementById("circle")
        my_context = my_canvas.getContext("2d")

        my_context.beginPath();
        my_context.arc(100, 100, 50, 0, 2*Math.PI);
        my_context.stroke();
</script>
计算11-5

请用HTML语言编写一个程序,实现「计算11-5的结果」。

2.3 轻松涂鸦

几何图形

接下来轻松一下,画一些几何图形。

矩形框 几何图形

先试试矩形框:

<canvas id="my_shape" width="500" height="500">

<script>
        my_canvas = document.getElementById("my_shape")
        my_context = my_canvas.getContext("2d")
        
        my_context.strokeStyle = "black"
        my_context.strokeRect(25, 25, 100, 100)
</script>

参考:https://developer.mozilla.org/zh-CN/docs/Web/API/CanvasRenderingContext2D/strokeRect

加粗线条 几何图形

然后加粗线条:

<canvas id="my_shape" width="500" height="500">

<script>
        my_canvas = document.getElementById("my_shape")
        my_context = my_canvas.getContext("2d")
        
        my_context.strokeStyle = "black"
        my_context.strokeRect(25, 25, 100, 100)
        
        my_context.lineWidth = 9.5
        my_context.strokeRect(25+120, 25, 100, 100)
</script>

参考:https://developer.mozilla.org/zh-CN/docs/Web/API/CanvasRenderingContext2D/lineWidth

换个颜色 几何图形

换个颜色:

<canvas id="my_shape" width="500" height="500">

<script>
        my_canvas = document.getElementById("my_shape")
        my_context = my_canvas.getContext("2d")
        
        my_context.strokeStyle = "black"
        my_context.strokeRect(25, 25, 100, 100)
        
        my_context.lineWidth = 9.5
        my_context.strokeRect(25+120, 25, 100, 100)
        
        my_context.strokeStyle = "red"
        my_context.strokeRect(25+120+120, 25, 100, 100)
</script>

参考:https://developer.mozilla.org/zh-CN/docs/Web/API/CanvasRenderingContext2D/strokeStyle

圆圈 几何图形

加两个圆圈:

<canvas id="my_shape" width="500" height="500">

<script>
        my_canvas = document.getElementById("my_shape")
        my_context = my_canvas.getContext("2d")
        
        my_context.strokeStyle = "black"
        my_context.strokeRect(25, 25, 100, 100)
        
        my_context.lineWidth = 9.5
        my_context.strokeRect(25+120, 25, 100, 100)
        
        my_context.strokeStyle = "red"
        my_context.strokeRect(25+120+120, 25, 100, 100)

        my_context.strokeStyle = "#fcb131"
        my_context.beginPath()
        my_context.arc(25+110, 25+100, 50, 0, 2*Math.PI)
        my_context.stroke()
        
        my_context.strokeStyle = "#00a651"
        my_context.beginPath()
        my_context.arc(25+120+110, 25+100, 50, 0, 2*Math.PI)
        my_context.stroke()
</script>

参考:https://developer.mozilla.org/zh-CN/docs/Web/API/CanvasRenderingContext2D/arc

https://developer.mozilla.org/zh-CN/docs/Web/API/CanvasRenderingContext2D/beginPath

圆弧 几何图形

加两段圆弧:

<canvas id="my_shape" width="500" height="500">

<script>
        my_canvas = document.getElementById("my_shape")
        my_context = my_canvas.getContext("2d")
        
        my_context.strokeStyle = "black"
        my_context.strokeRect(25, 25, 100, 100)
        
        my_context.lineWidth = 9.5
        my_context.strokeRect(25+120, 25, 100, 100)
        
        my_context.strokeStyle = "red"
        my_context.strokeRect(25+120+120, 25, 100, 100)

        my_context.strokeStyle = "#fcb131"
        my_context.beginPath()
        my_context.arc(25+110, 25+100, 50, 0, 2*Math.PI)
        my_context.stroke()
        
        my_context.strokeStyle = "#00a651"
        my_context.beginPath()
        my_context.arc(25+120+110, 25+100, 50, 0, 2*Math.PI)
        my_context.stroke()
        
        my_context.strokeStyle = "#0081c8"
        my_context.beginPath()
        my_context.arc(25+50, 25+50, 50, -1/6*Math.PI, 1/4*Math.PI)
        my_context.stroke()
        
        my_context.strokeStyle = "red"
        my_context.beginPath()
        my_context.arc(25+50+120, 25+50, 50, 1/2*Math.PI, 3/4*Math.PI)
        my_context.stroke()
</script>

参考:https://developer.mozilla.org/zh-CN/docs/Web/API/CanvasRenderingContext2D/arc

画奥运五环

尝试画一个奥运会五环图案。

2.4 其他语言

不同语言

除了HTML,还有很多不同的计算机语言,不同的语言也有独特的语法和格式,而执行不同语言编写的程序,也需要相应的执行环境。

VBScript语言 不同语言

例如,VBScript语言是这个样子的:

MsgBox 1+1

我们可以在桌面上新建一个文本文件,然后把上面的内容复制到文件,保存并把文件后缀名修改为 .vbs,然后打开文件,可以看到,出现一个窗口,并显示了结果:2。

VBScript的执行环境是一个叫做 Windows Script Host 的程序(这里省略了计算机硬件和操作系统),由于这个程序是Windows操作系统自带的,所以在其他操作系统上不容易执行VBScript。

Python语言 不同语言

例如,Python语言是这个样子的:

print(1+1)
input()

我们可以在桌面上新建一个文本文件,然后把上面的内容复制到文件,保存并把文件后缀名修改为 .py,然后打开文件,可以看到,出现一个窗口,并显示了结果:2。

但是Python语言也需要对应的执行环境,如果操作系统中没有安装 Python解释器 之类的程序,就无法执行。

好在现在有很多网站都提供在线执行环境,我们可以把上面的内容复制到下面的在线环境中执行:

https://c.runoob.com/compile/9/

C语言 不同语言

还有著名的C语言:

#include <stdio.h>

int main()
{
    printf("%d", 1+1);
    return(0);
}

同样可以使用下面的在线环境:

https://c.runoob.com/compile/11/

探索JavaScript

通过查找资料,大致了解一下「HTML」和「JavaScript」这两种语言之间的关系。

2.5 程序的表达形式

表达形式

计算机语言是一种表达形式,我们可以粗略地说,程序的表达形式是指用什么形式来表达程序的目标。

自然语言 表达形式

例如,我们可以用自然语言的形式来表达程序的目标,像是「计算壹加壹」、「Find the value of one plus one」都属于自然语言。

符号系统 表达形式

也可以用数学符号表达程序的目标:「1+1=?」。

计算机语言 表达形式

还可以用我们正在学习的计算机语言:

<script>
document.write(1+1)
</script>

要注意的是,虽然很多计算机语言使用了大量的英语单词,但是计算机语言并不是英语,因为计算机语言的语法和英语很不一样,而且一般非常严格。

目标是核心

可以看出,上述的各种表达形式虽然各不相同,但是核心都是表达了程序的目标,这里就是计算1+1的结果。而且其中最关键的部分是动作类型和施加对象,这里就是加法和数字。

形式转换

因此,程序可以在不同表达形式之间相互转换,编写计算机程序的时候如果没有思路,不妨先用自然语言把程序表达出来,然后再转换成计算机语言。

奥运五环 形式转换

例如,绘制奥运五环,可以先用如下的自然语言表达,然后再转写成计算机语言。

自然语言表达:

1. 准备好画布和画笔。
2. 切换到蓝色画笔,在特定位置,绘制一个圆圈。
3. 切换到黑色画笔,向右移动位置,绘制一个圆圈。
4. 切换到红色画笔,向右移动位置,绘制一个圆圈。
5. 切换到黄色画笔,在蓝圆圈右下方位置,绘制一个圆圈。
6. 切换到绿色画笔,向右移动位置,绘制一个圆圈。
7. 切换到蓝色画笔,在蓝圆圈和黄圆圈交界处画一段圆弧。
8. ……

转写成HTML:

<canvas id="my_shape" width="500" height="500">

<script>
        my_canvas = document.getElementById("my_shape")
        my_context = my_canvas.getContext("2d")

        my_context.lineWidth = 9.5
        my_context.strokeStyle = "#0081c8"
        my_context.beginPath()
        my_context.arc(25+50, 25+50, 50, 0, 2*Math.PI)
        my_context.stroke()
        
        my_context.strokeStyle = "black"
        my_context.beginPath()
        my_context.arc(25+50+120, 25+50, 50, 0, 2*Math.PI)
        my_context.stroke()

        my_context.strokeStyle = "red"
        my_context.beginPath()
        my_context.arc(25+50+120+120, 25+50, 50, 0, 2*Math.PI)
        my_context.stroke()
        
        
        my_context.strokeStyle = "#fcb131"
        my_context.beginPath()
        my_context.arc(25+110, 25+100, 50, 0, 2*Math.PI)
        my_context.stroke()
        
        my_context.strokeStyle = "#00a651"
        my_context.beginPath()
        my_context.arc(25+120+110, 25+100, 50, 0, 2*Math.PI)
        my_context.stroke()
        
        
        my_context.strokeStyle = "#0081c8"
        my_context.beginPath()
        my_context.arc(25+50, 25+50, 50, -1/6*Math.PI, 1/4*Math.PI)
        my_context.stroke()
        
        my_context.strokeStyle = "black"
        my_context.beginPath()
        my_context.arc(25+50+120, 25+50, 50, -1/6*Math.PI, 1/4*Math.PI)
        my_context.stroke()
        
        my_context.strokeStyle = "black"
        my_context.beginPath()
        my_context.arc(25+50+120, 25+50, 50, 1/2*Math.PI, 3/4*Math.PI)
        my_context.stroke()
        
        my_context.strokeStyle = "red"
        my_context.beginPath()
        my_context.arc(25+50+120+120, 25+50, 50, 1/2*Math.PI, 3/4*Math.PI)
        my_context.stroke()
</script>
探索织布机

通过查找资料,大致了解一下「雅卡尔织布机」(英文:Jacquard machine)。

尾声 暂告一段落

本期学习了入门计算机编程的快捷方法,也就是通过实际执行和观察结果来体会程序,但为了能够更专业地编程,接下来将会系统地学习计算机编程的各种常识和术语。

素材 素材来源

视频和音乐:

https://www.videvo.net

字体:

https://fonts.google.com/noto

https://github.com/liberationfonts/liberation-fonts

讨论
随记