[开发者心得] “数据结构课作业笔记”#004-数组-简单排列的变量和它们必然命运(下)

[复制链接]
873 |0
脑的研发记录 发表于 2023-11-7 13:25:25 | 显示全部楼层 |阅读模式
本帖最后由 脑的研发记录 于 2023-11-7 13:23 编辑

“数据结构课作业笔记”#004-数组-简单排列的变量和它们必然命运(下)

所用编辑器版本0.25.0.4

目录总览:
零.再前情提要
壹.第一个自由数组
贰.所需语法 (代码如本节图示)
叁.应用说明
肆.相关参考链接 (返回主站)

伍.专有名词的真相(类比之后,默认语境的调整,专业名词对照说明)
陆.告一段落,回顾语



零.再前情提要
       数组一次性赋值,实现了按计划传送。不过数组层面就只有读取数据,一切按既定计划进行。但是遇到临场变动,修改计划内容,想在第一次填充的数据的时候就可以符合新的需求就遇到了困难,代码报错说变量不存在,写入数据总是要一次性赋值然后再修改,精力消耗感觉大,膈应。这次补充数组的修改,完成第一个具有特殊身份的数组。
壹.第一个自由数组
     不多说,上代码,新建脚本,复制粘贴跑就完事。


interface see {
    a: number;
    check: Vector;
}

class seetest {
    public a: number;
    public check: Vector;
}
@Core.Class
export default class add extends Core.Script {

    /** 当脚本被实例后,会在第一帧更新前调用此函数 */
    protected onStart(): void {


        // var arr_names:see[] = new Array(4)
        // var i = 0;
        // arr_names[0].a = 2
        // console.log(arr_names.a);
        // 日志提示警告:数组每一项的成员a不存在,而且也确实无法输出a。
        // 原因是see类型不是默认直接直接转化的类型,
        // 需要Array<see>类型转换,才能让数组识别


        // var arr_names: Array<see> = new Array(4)
        // var i = 0;
        // arr_names[0].a = 2
        // console.log(arr_names.a);
        // 日志依然提示警告:数组每一项的成员仍然不存在,而且也确实无法输出a。
        // 原因是see类型是interface类别的,不是默认直接直接转化的类型,
        // 需要Array<see>类型转换,才能让数组识别



        // var arr_names: Array<seetest> = new Array(4)
        // var i = 0;
        // var m = new seetest();
        // m.a = 1;
        // m.check = new Vector(100, 0, 0);
        // console.log("m=" + m.a);


        // arr_names[0] = m;
        // console.log(arr_names[0].a);


        var i = 0;
        var arr_names: Array<seetest> = new Array(6)
        for (i = 0; i < arr_names.length; i++) {
            arr_names[i]= new seetest();
            arr_names[i].a = i * 2;
            arr_names[i].check = new Vector(500 * i, 0, 300);
            console.log(arr_names[i].check.x)
        }
        i = 5;

        // arr_names[2].check = new Vector(100, 0, 1000);

        var chara: Gameplay.Character;
        setTimeout(() => {
            chara = Gameplay.getCurrentPlayer().character;
            chara.worldLocation = arr_names[i].check;
            var timer = setInterval(() => {
                if (i < 0) {
                    // 如果i小于0,就清除定时器
                    clearInterval(timer);

                }
                chara.worldLocation = arr_names[i].check;
                console.log(arr_names[i].check.x)
                console.log(i);
                i--;
                // 每500毫秒i减少1
            }, 500);
        }, 2000);

    }

}



数组不用预先一个一个敲数字进行赋值,实现了自动填充。然后再按新的计划控制角色闪现。
绿色的大块字符是数组编写过程中遇到的bug,是在穷举到成功满足需求的之后才明白代码输出失败的问题。
代码拆解


对数组第一次赋值,人称“初始化”。

var i = 0;
        var arr_names: Array<seetest> = new Array(6)
        for (i = 0; i < arr_names.length; i++) {
            arr_names[i]= new seetest();
            arr_names[i].a = i * 2;
            arr_names[i].check = new Vector(500 * i, 0, 300);
            console.log(arr_names[i].check.x)
        }


先声明数组,类型是seetest, 长度是6

然后数组的每一项都新建了一个seetest的新变量,
每一项的名叫"a"的变量成员都存储了一个数字,
每一项的名叫“check”的变量成员都存储了一个位置信息。
然后打印每一项的位置信息的x坐标。


这也是一种初始化,其实这俩都相当于产生铭牌,每个铭牌给一个房子。只不过下面的代码是先一下子产生所需的铭牌,然后再把铭牌挂到房子上
 var i = 0;


          // 产生6个铭牌
        var arr_names: Array<seetest> = new Array(6)

        // 对每一个铭牌分配一个seetest户型的房子
        for (i = 0; i < arr_names.length; i++) {
            arr_names[i]= new seetest();

        }

        // 每个铭牌指定的房子里安排进家具
        for(i=0;i<arr_names.length;i++){
            arr_names[i].a = i * 2;
            arr_names[i].check = new Vector(500 * i, 0, 300);
            console.log(arr_names[i].check.x)
        }




这样之后,可以把用函数打包一些句子,变成这样,就可以实现存入数据,in一次就存入一项seetest格式的数据,in两次就存入两项seetest格式的数据。


       // 对每一个铭牌分配一个seetest户型的房子
        for (this.i = 0; this.i < this.arr_names.length; this.i++) {
            this.arr_names[this.i] = new seetest();
        }

        // 每个铭牌指定的房子里安排进家具
        for (this.i = 0; this.i < this.arr_names.length;) {
            this.in(new Vector(500 * this.i, 0, 300), this.i * 2);
        }



其中的in函数样子如下

public in(check: Vector, a: number) {
        this.arr_names[this.i].a = a
        this.arr_names[this.i].check = check;
        console.log(this.arr_names[this.i].check.x)
        this.i++;
    }



然后想着输入已经打包了,封装一个输出,注意到代码
 var chara: Gameplay.Character;
        setTimeout(() => {
            chara = Gameplay.getCurrentPlayer().character;
            chara.worldLocation = arr_names[i].check;
            var timer = setInterval(() => {
                if (i < 0) {
                    // 如果i小于0,就清除定时器
                    clearInterval(timer);

                }
                chara.worldLocation = arr_names[i].check;
                console.log(arr_names[i].check.x)
                console.log(i);
                i--;
                // 每500毫秒i减少1
            }, 500);
        }, 2000);



         找不同,对小学生来说有点幼稚,对大学生来说刚刚好。


var chara: Gameplay.Character;
        setTimeout(() => {
            chara = Gameplay.getCurrentPlayer().character;
            // chara.worldLocation = this.arr_names[this.i].check;
            chara.worldLocation = this.out().check;
            var timer = setInterval(() => {
                if (this.i < 0) {
                    // 如果i小于0,就清除定时器
                    clearInterval(timer);
                }

                // chara.worldLocation = this.arr_names[this.i].check;
                // console.log(this.arr_names[this.i].check.x)
                // console.log(this.i);
                // this.i--;
                // 每500毫秒i减少1

               

                // var c: seetest = new seetest();
                // c = this.out();
                // chara.worldLocation = c.check;
                // console.log(c.a);


                chara.worldLocation = this.out().check;


               
            }, 500);
        }, 2000);



out 函数具体如下


public out(): seetest {
        this.i--;
        var now: seetest = new seetest();
        now = this.arr_names[this.i];
        return now;
    }



最后来一个代码全景,新建脚本,复制粘贴就能跑。
最终成果


class seetest {
    public a: number;
    public check: Vector;
}


@Core.Class
export default class add extends Core.Script {

    public arr_names: Array<seetest> = new Array(6)
    public i: number = 0;

    /** 当脚本被实例后,会在第一帧更新前调用此函数 */
    protected onStart(): void {

        // 对每一个铭牌分配一个seetest户型的房子
        for (this.i = 0; this.i < this.arr_names.length; this.i++) {
            this.arr_names[this.i] = new seetest();
        }

        // 每个铭牌指定的房子里安排进家具
        for (this.i = 0; this.i < this.arr_names.length;) {
            this.in(new Vector(500 * this.i, 0, 300), this.i * 2);
        }

        var chara: Gameplay.Character;
        setTimeout(() => {
            chara = Gameplay.getCurrentPlayer().character;
            // chara.worldLocation = this.arr_names[this.i].check;
            chara.worldLocation = this.out().check;
            var timer = setInterval(() => {
                if (this.i < 0) {
                    // 如果i小于0,就清除定时器
                    clearInterval(timer);
                }

                chara.worldLocation = this.out().check;
               
            }, 500);
        }, 2000);

    }

    public in(check: Vector, a: number) {
        this.arr_names[this.i].a = a
        this.arr_names[this.i].check = check;
        console.log(this.arr_names[this.i].check.x)
        this.i++;
    }

    public out(): seetest {
        this.i--;
        var now: seetest = new seetest();
        now = this.arr_names[this.i];
        return now;
    }

}



对比前一节代码

interface have {
    i: number;
    check: Vector;
}
// 说明一个数据类型,如代码所示,这个叫“have"的类型
// 有一个叫“i“的变量,它的类型是numebr
// 还有一个叫“check"的变量,它的类型是Vector

@Core.Class
export default class stack extends Core.Script {

    /** 当脚本被实例后,会在第一帧更新前调用此函数 */
    protected onStart(): void {
        var a: have[] = [
            { i: 0, check: new Vector(500, 0, 100) },
            { i: 1, check: new Vector(1000, 0, 100) },
            { i: 2, check: new Vector(1500, 0, 100) },
            { i: 3, check: new Vector(2000, 0, 100) },
            { i: 4, check: new Vector(2500, 0, 100) },
            { i: 5, check: new Vector(3000, 0, 200) }
        ];


        var i = 5;
        var chara: Gameplay.Character;
        setTimeout(() => {
            chara = Gameplay.getCurrentPlayer().character;
            chara.worldLocation = a[i].check;
            var timer = setInterval(() => {
                if (i < 0) {
                    // 如果i小于0,就清除定时器
                    clearInterval(timer);

                }
                chara.worldLocation = a[i].check;
                i--;
                // 每500毫秒i减少1
            }, 500);
        }, 2000);
    }
}


代码就着文案现写现改,总得来说分成两个部分:封装和解决封装遇到的报错。
把i变量从里面提到外部,其他函数可以直接获取i,进行修改,原来传进参数修改的路线失败了。
然后封装过程中,使用的数据seetest类型的改变,从interface到class,每个数据初始化都需要new 来执行分配空间。
初始化数组的时候,数组也需要重新传入数据格式,传入数据格式的方法也变化了。
其他就按照前节的代码手动输入。
总得来说,代码修改,像从小房子装水管,从水管到简单挂起,再到管线臃肿混乱,在意料之外的报错中拿到经验,最后拆除重写,小房子才有了新的管道线路。
本质来说是代码之间的联系更准确了,准确的同时,也多了支持精准处理的变量,变量位置调整。

功能依旧是 提前写入,按计划使得角色倒退。
但是封装之后,in out的操作,使得总是处理数组一段的数据,最后产生的却先使用,最先产生的最后使用。
500 1000 1500 2000 2500 3000
输出是
3000 2500 2000 1500 1000 500
倒着输出了

但是如果在输出3000之后,输出2500之前,又输入一个数字3500
下次输出的就是3500

输出3500之后,再输出2500之前,又输入4000,
下次输出的就是4000。


进进出出,数字还是数字,代码层面确实是这样就结束了。


贰.参考语法
      TypeScript 类 | 菜鸟教程 (runoob.com)
          别看太久,我觉得代码跑起来就行,看了不能立即敲代码改参数的还不是这个阶段的事情。
叁.应用说明
       数字进出,可以赋予数字意义,数字代表,数字进出,方向进出,走迷宫,走到死路,回滚步数,倒回一步换另一个方向,再探测,不通,回到原来方向,换另另一个方向再探测,不通,回到原来方向,换另另另外一个方向探测。穷举完倒数第一步的四种方向,再穷举倒数第二步,换另一个方向上的倒数第一步,再穷举四个方向,如果不通,就在倒回第二步,换再穷举倒数第三步。
           以上操作的高大上名称为“深度优先寻路”。“一直往下走,走不通回头,换条路再走,直到无路可走”。
            以上操作的代码层面的名称——栈,后进先出。
           游戏方面,走迷宫,回退到上一个分支。
        
肆.相关参考链接 (返回主站)

普通大学生“数据结构”课作业笔记#000-目录-逻辑结构与存储结构 口袋方舟论坛|面向全年龄的UGC互动内容平台与交流社区 (ark.online)

伍.专有名词的真相(拓展视野,饭后闲聊)


不过是在默认语境(直觉)下,为了一语中的,才产生的专有名词。
成员变量(简称 “成员”)(member variable
类(class)
指针(pointer

地址(address)
分配内存(函数new)
指针数组(Array of pointers
只要铭牌挂在房子上,就能修改数组里面的具体变量
铭牌就是变量名,房子就是一块地,就是内存,
铭牌刻上的就是房子的地址,
变量存着的是内存的地址,
底层支持:CPU找内存
用腿跑路,拿着铭牌里的名字比对去找房子,如何奔跑按图索骥到达房子不多说,
用CPU找,拿着数组里的地址比对去找内存,如何遍历按图索骥到达内存不多说。
底层优化本质:让CPU找更少次数



陆.告一段落,回顾语

文案现写,代码现写,注释无数,回滚无数,踩坑无数。
这是量大的预兆,这是标记的提醒。
标记换个顺序,代码就得天翻地覆一次。
教程不好写。
现在才知道教材原来是势力平衡的结果:省略一步,穷举十次,省略两步,穷举百次。不省略,细节多如牛毛。


从数组到栈,中间我们老师讲了其他的数据,铺垫了如数据类型,如抽象数据对象,数据项,数据元素,队列,顺序表,链表等等。
我觉得还是离代码有点远,或者是从一个已经预料到结果的视角开始入手,就会跳过了自己的那部分随意发挥才华故事。
等着,哪天咱也出点靠谱教材,第一人称,全过程记录,平地起高楼。

回复

使用道具 举报

热门版块
快速回复 返回顶部 返回列表