第八章 可以操作的程序,操作方块
(编程的“三大必备”:循环、局部程序、命名存储区)

1.程序是怎么知道键盘被按下的?
因为程序只能操作存储区,所以存储区是唯一的选项。(其实就是内存)
又因为方块像素在“存储区[50000]”-“存储区[59999]”,所以只要改变方块的“存储区”数值就行。

2.通过装置操纵存储区(也就是规定了哪个存储区编号,代替哪个按键,并且相关联。)

存储区编号      按键
50004           上
50005           下
50006           左
50007           右

次外,这些编号的存储区,是不能在程序中进行操纵的,否则会报错。

3.实现操作

存储区[60000]->存储区[50006]*999999    #左

即按下“左箭头”时,“存储区[50006]”就相当于变成了1。而乘以999999,也就是“存储区[60000]->999999”
如果没有按下“左箭头”,则“存储区[50006]”就相当于0。而乘以999999,也就是“存储区[60000]->0”

4.无限循环

只要 0<1
    {略}

毕竟程序不能操作一次就结束,那样就没法玩了。

5.移动一个点 (首先让一个像素自动向下移动)

存储区[0]->0
只要 存储区[0]<100
    存储区[60000+(存储区[0]*100)]->999999
    存储区[60000+(存储区[0]*100)]->0
    存储区[0]->存储区[0]+1

6.点击“向下箭头”,让像素点向下移动。

纵向位置->0
只要 0<1
    纵向位置->纵向位置+存储区[50005]  #“存储区[50005]”向下按钮
    存储区[60000+(纵向位置*100)]->999999
    存储区[60000+(纵向位置*100)]->0

由于这样的像素点会一闪一闪的,所以使用“存储区[55001]->1”关闭调控

存储区[55001]->1     #就追加了这一条“关闭调控”
纵向位置->0
只要 0<1
    纵向位置->纵向位置+存储区[50005]
    存储区[60000+(纵向位置*100)]->999999
    存储区[55000]->1
    存储区[60000+(纵向位置*100)]->0

7.向其他方向移动

纵向位置,向上。

纵向位置->纵向位置-存储区[50004]   #向上箭头按钮

纵向位置,向下。

纵向位置->纵向位置+存储区[50005]   #向下箭头按钮

纵向位置,“向上”和“向下”。

纵向位置->纵向位置+存储区[50005]-存储区[50004]   

一个像素点的上下移动!(但超出存储区的显示范围会报错)

存储区[55001]->1
纵向位置->0    #先给纵向位置一个初始值
只要 0<1
    纵向位置->纵向位置+存储区[50005]-存储区[50004]    #关键在这一行
    存储区[60000+(纵向位置*100)]->999999                   #由于上下像素间隔是100
    存储区[55000]->1
    存储区[60000+(纵向位置*100)]->0

上下完成了,再追加左右也就容易了。

存储区[55001]->1
纵向位置->0    #先定义一个纵向位置
横向位置->0    #再定义一个横向位置
只要 0<1
    纵向位置->纵向位置+存储区[50005]-存储区[50004]    #向下移动则+1,向上移动则-1
    横向位置->横向位置+存储区[50007]-存储区[50006]    #向右移动则+1,向左移动则-1
    存储区[60000+(纵向位置*100)+横向位置]->999999
    存储区[55000]->1
    存储区[60000+(纵向位置*100)+横向位置]->0

8.移动方块。(像素点实现了移动,那就替换成方块吧!)

存储区[55001]->1
纵向位置->0
横向位置->0
只要 0<1
    纵向位置->纵向位置+存储区[50005]-存储区[50004]
    横向位置->横向位置+存储区[50007]-存储区[50006]
    存储区[3]->纵向位置     #存储区[3]在方块的局部程序中
    存储区[4]->横向位置     #存储区[4]也在方块的局部程序中
    存储区[5]->999999
    方块()             #调用局部程序
    存储区[55000]->1
    存储区[5]->0
    方块()

    #局部程序
方块() 是
    纵向次数->0
    只要 纵向次数<4
    横向次数->0
    只要 横向次数<4
        存储区[60000+(存储区[3]*500)+(存储区[4]*5)+(纵向次数*100)+横向次数]->存储区[5]
        横向次数->横向次数+1
    纵向次数->纵向次数+1

基本上并没有改变多少,无非是将“纵向位置”和“横向位置”分别赋值给了“方块()”这个局部程序中的“存储区[3]”和“存储区[4]”,代表横向位置和纵向位置的存储区罢了。

9.避免过快的移动(争取按一下就移动一次,而不是一直移动下去)

同样以一个像素为例,并向右移动

存储区[55001]->1
横向位置->0
之前按下了?->存储区[50007]
只要 0<1
    现在按下了?->存储区[50007]
    之前没有按下?->1-之前按下了?
    移动的话为1->现在按下了?*之前没有按下?
    横向位置-> 横向位置+移动的话为1
    之前按下了?->现在按下了?
    存储区[60000+横向位置]->999999
    存储区[55000]->1
    存储区[60000+横向位置]->0

这里涉及到一个式子
即“现在按下了?”和“之前没有按下?”就移动。其余情况都不移动。

通过表格就是

现在按下了?    之前没有按下?    结果  
0               0               0  
0               1               0   
1               0               1  
1               1               0

而想通过计算生成结果,就需要加减乘除。但从上述表格来看,加减乘除都不行,但换个方式,就马上能行了!也就是将“之前没有按下?”用1去减。
即 (1-之前没有按下?)*现在按下了?

现在按下了?   1-之前没有按下?          结果  
0        *      (1-0)     =          0  
0        *      (1-1)     =          0   
1        *      (1-0)     =          1  
1        *      (1-1)     =          0

(继续感叹,自己就想不到啊!)
然后将这部分追加到“横向位置”和“纵向位置”,就能实现“按一下”或“按住”就移动一格的效果。

横向位置->横向位置+(现在按下了?*(1-之前按下了?))#这是向右移动1
横向位置->横向位置-(现在按下了?*(1-之前按下了?))#这是向左移动1
纵向位置->纵向位置+(现在按下了?*(1-之前按下了?))#这是向下移动1
纵向位置->纵向位置-(现在按下了?*(1-之前按下了?))#这是向上移动1

当然,还需要与各个操作的存储区进行匹配!

10.完整的上下左右移动

存储区[55001]->1
纵向位置->0
横向位置->0
之前按下了上?->存储区[50004]
之前按下了下?->存储区[50005]
之前按下了左?->存储区[50006]
之前按下了右?->存储区[50007]
只要 0<1
    现在按下了上?->存储区[50004]
    现在按下了下?->存储区[50005]
    现在按下了左?->存储区[50006]
    现在按下了右?->存储区[50007]
    向上移动的话为1->现在按下了上?*(1-之前按下了上?)
    向下移动的话为1->现在按下了下?*(1-之前按下了下?)
    向左移动的话为1->现在按下了左?*(1-之前按下了左?)
    向右移动的话为1->现在按下了右?*(1-之前按下了右?)
    纵向位置->纵向位置+向下移动的话为1-向上移动的话为1
    横向位置->横向位置+向右移动的话为1-向左移动的话为1
    之前按下了上?->现在按下了上?
    之前按下了下?->现在按下了下?
    之前按下了左?->现在按下了左?
    之前按下了右?->现在按下了右?
    存储区[60000+(纵向位置*100)+横向位置]->999999
    存储区[55000]->1
    存储区[60000+(纵向位置*100)+横向位置]->0

先定义“横向”和“纵向”
再定义“之前的上下左右”是否按下,由“存储区”验证
然后是无尽循环
再定义“现在的上下左右”是否按下,由“存储区”验证
再计算公式“现在的上下左右*(1-之前的上下左右)”,确定是1还是0
再追加在“横向”和“纵向”里
再把“现在的上下左右”替换掉“之前的上下左右”
最后放进“显示的存储区”里。

修改的短一点(其实就是减少了命名的字数)

存储区[55001]->1
纵->0
横->0
前上->存储区[50004]
前下->存储区[50005]
前左->存储区[50006]
前右->存储区[50007]
只要 0<1
    现上->存储区[50004]
    现下->存储区[50005]
    现左->存储区[50006]
    现右->存储区[50007]
    上->现上*(1-前上)
    下->现下*(1-前下)
    左->现左*(1-前左)
    右->现右*(1-前右)
    纵->纵+下-上
    横->横+右-左
    前上->现上
    前下->现下
    前左->现左
    前右->现右
    存储区[60000+(纵*100)+横]->999999
    存储区[55000]->1
    存储区[60000+(纵*100)+横]->0

再换成英文字母

存储区[55001]->1
y->0
x->0
ou->存储区[50004]
od->存储区[50005]
ol->存储区[50006]
or->存储区[50007]
只要 0<1
    nu->存储区[50004]
    nd->存储区[50005]
    nl->存储区[50006]
    nr->存储区[50007]
    y->y+(nd*(1-od)-nu*(1-ou))
    x->x+(nr*(1-or)-nl*(1-ol))
    ou->nu
    od->nd
    ol->nl
    or->nr
    存储区[60000+(y*100)+x]->999999
    存储区[55000]->1
    存储区[60000+(y*100)+x]->0

11.用方块绘制(其实就是多追加了“存储区[3]”和“存储区[4]”的接口)

存储区[55001]->1
纵->0
横->0
前上->存储区[50004]
前下->存储区[50005]
前左->存储区[50006]
前右->存储区[50007]
只要 0<1
    现上->存储区[50004]
    现下->存储区[50005]
    现左->存储区[50006]
    现右->存储区[50007]
    上->现上*(1-前上)
    下->现下*(1-前下)
    左->现左*(1-前左)
    右->现右*(1-前右)
    纵->纵+下-上
    横->横+右-左
    前上->现上
    前下->现下
    前左->现左
    前右->现右
    存储区[3]->纵
    存储区[4]->横
    存储区[5]->999999
    方块()
    存储区[55000]->1
    存储区[5]->0
    方块()

方块() 是
    纵向次数->0
    只要 纵向次数<4
    横向次数->0
    只要 横向次数<4
        存储区[60000+(存储区[3]*500)+(存储区[4]*5)+横向次数+(纵向次数*100)]->存储区[5]
        横向次数->横向次数+1
    纵向次数->纵向次数+1

12.如果想让方块自动向下,只需要在“纵”上+1即可。(由于下落的速度过快,所以下一章会有)

存储区[55001]->1
纵->0
横->0
前上->存储区[50004]
前下->存储区[50005]
前左->存储区[50006]
前右->存储区[50007]
只要 0<1
    现上->存储区[50004]
    现下->存储区[50005]
    现左->存储区[50006]
    现右->存储区[50007]
    上->现上*(1-前上)
    下->现下*(1-前下)
    左->现左*(1-前左)
    右->现右*(1-前右)
    纵->纵+下-上+1         #这里
    横->横+右-左
    {略}

13.将墙壁也放入后的完整代码

存储区[55001]->1

绘制墙壁()
绘制底部()

纵->0
横->5    #如果初始值是0,则会覆盖掉左边的墙壁。所以最少是1,最多是10
前上->存储区[50004]
前下->存储区[50005]
前左->存储区[50006]
前右->存储区[50007]
只要 0<1
    现上->存储区[50004]
    现下->存储区[50005]
    现左->存储区[50006]
    现右->存储区[50007]
    上->现上*(1-前上)
    下->现下*(1-前下)
    左->现左*(1-前左)
    右->现右*(1-前右)
    纵->纵+下-上
    横->横+右-左
    前上->现上
    前下->现下
    前左->现左
    前右->现右
    存储区[3]->纵
    存储区[4]->横
    存储区[5]->999999
    方块()
    存储区[55000]->1
    存储区[5]->0
    方块()

绘制墙壁() 是
    存储区[5]->999999
    次数->0
    只要 次数<20
    存储区[3]->次数
    存储区[4]->0
    方块()    #左
    存储区[3]->次数
    存储区[4]->11
    方块()    #右
    次数->次数+1

绘制底部() 是
    存储区[5]->999999
    次数->0
    只要 次数<10
    存储区[3]->19
    存储区[4]->1+次数
    方块()
    次数->次数+1


方块() 是
    纵向次数->0
    只要 纵向次数<4
    横向次数->0
    只要 横向次数<4
        存储区[60000+(存储区[3]*500)+(存储区[4]*5)+横向次数+(纵向次数*100)]->存储区[5]
        横向次数->横向次数+1
    纵向次数->纵向次数+1

总结 i。从计算机的外部获取信息时还是使用存储区。
(就是得先定义一下)

ii。判断上下左右键是否被按下的方法
(就是按下了为1,没按下为0)

iii。可以进行操作的程序是不会终止的程序,因此需要进行无限的循环。
(就是无限的循环操作)

iv。在一般人看来很简单的逻辑,要让计算机明白的话,需要进行相当程度的转换才行。
(就是通过某种算法进行计算。)

v。想得到需要的结果,就需要“创造”出算式
(就是创造出需要得出结果数的式子)

本章结尾的一段话:
将代入的数字替换为“操作”,得到的数字替换为“图形”,算式替换为“程序”,就会变成“想要生成一个针对某一操作得到所需图形的程序”。这正是编写游戏程序的精髓。程序就像是一个巨大的算式,“创造”它就是编程本身。

这句话挺有意思!而通过这一章的学习,也深刻感受到:我也就处于这个阶段的程度啊!自己好弱。