# 前言

这次记录的是 3 月 3 日的面试。

这是也第二次技术面试 —— 前一次的记录也写过,就是 2 月 14 号的那一次

那么,以下是记录。

#

这次是去的成都 —— 应该算是一个大公司吧 —— 具体细节就不透露了,因为看见面试之前填的一个单子还是有保密保证的。

3 月 2 日 (还是 1 号呢?),星期四投的简历,然后下午 7 点左右接到了通知,问明天 (3 月 3 日) 有没有空?毕竟现在都是自由之身,所以直接就回答 “应该有” 了。然后收到了一条面试短信,邀请第二天 2:30 前往成都天府软件园去面试。
所以当天晚上,仔细查询了一下路线,估计了一下时间,订好了车票。

第二天一大早就起了床,出去买了早餐 —— 因为觉得下午或者晚上大约也回不来了,所以就没有按照平时的习惯,顺便买菜。
吃完早餐,再呆了一会儿,10 点左右出发了。
坐着轻轨到了重庆北站 - 南广场。

刚下地铁,就有一个女人问:你要到哪儿?

我想了下,如实回答道:“成都”。
问:“成都?买票了没?”
答:“买了”
问:“成都?是火车票还是动车票?”
答:“... 动车吧”
问:“是好久的?”
答:“11 点 42 的”

女人顿时很惊讶地说,你的票这边怕是来不及了,这边只有坐火车,北站那边还有好远!

我看了她下,感觉可能是在骗我。没有回话,就直接向出口那边走了。

不过眼角余光似乎看见她在向旁边,一个柱子下坐的男人招呼。
然后,那个男人就跟上来了。

出了地铁,我就直接向广场那边,液晶屏显示路线的告示那边走。没想到男人直接跟了上来,招呼我说,时间上来不及了,动车要去北广场坐车,那得江北机场那边了!

我说不怕,还有一个小时呢。

男人依然不死心地追着我,说我用摩托拉你过去,只要 30 块!你好办事儿嘛。

我摇头。

这时候差不多也走到广场告示牌前了,只看了一眼,心里 “咯噔” 一下,感觉坏了 —— 因为滚动播列车信息的告示牌下,有个蓝色的牌子,写着 “G、K、D...” 什么的动车车次请前往北广场乘车,还标示了一个 “右行 100 米乘坐 663 路公交前往北广场”—— 也就是说,那两人没骗我么?两年没坐过火车了,大概确实发生了些变化罢。

回头看了下,男人还在。立刻走过来说,这边去北广场好远的,少说也要四、五十分钟,你不够了,坐我的摩托吧。

我手上的百度地图一直是开着的,立即放大了地图信息,但是发现 “南广场”、“北广场” 明明是链接在一块区域的啊?地图上看,差不多相对而立,就是绕的路有点曲折。北广场更靠近龙头寺轻轨站。

我计算了一下路径及时间,发现差不多半个小时应该就能到 (事实是当时计算路径错误,坑地图给出的是步行 30 分钟....),当时差不多是 10 点 40 左右,算算时间应该足够 —— 就算不够,延误了时机,我也不想跟着这些车站招揽的人的意思走!(毕竟曾经确实被坑过了)

然后我就一直往公交车站走,上车。

公交车运行时,我也开着地图 GPS 查看着,结果很快发现,不到 2 分钟,公交车就走了好大一段路程。

几分钟后,北广场到了。

然后才终于松了口气,同时也庆幸自己没上当。不过,当时确实动摇了 —— 果然在紧急时候,容易被外力影响。所以车站才多骗子,多被骗。

车票是 G8516 11:42 重庆北 -> 成都东。

进了车站,在大厅坐了大概 20 几分钟就开始检票了。

一路无事。

到达成都东站,是在 1 点多,跟计划差不多,然后经过 40 分钟左右轻轨,应该能在 2:30 左右赶到公司。

不过,我似乎忽视了一个问题:1 点多了,午饭怎么办?
在车站的便利店买了一桶方便面,一瓶矿泉水。便利店提供了热水,站在附近匆忙解决了。

不过这时候,差不多 2 点了。

地铁差不多还有 20 个站,加上中途等车之类的时间 —— 预算堪忧啊。

后来坐到一般多路程,我还是忍不住向人事的电话发了一条短信,说明了一下迟到原因。

最后,3 点过几分的时候,到达了天府五街。

下了地铁,就到公司了。

# 面试

出地铁,感觉不愧是软件园,一切都显得那么 “高大上”,地面都是干干净净的 —— 原谅我的词语匮乏,反正就是感觉很厉害的样子。对面我还看见 “腾讯” 两个大字了。

按照短信上的地址,找到了公司所在大楼,一层大厅还有一个保安,不过进去的时候并没有检查什么。

到了指定楼层,稍微收拾了一下紧张的心情。右转的玻璃门中,似乎就是前台了。对着玻璃门,我考虑了一下,“啪” 地一声按下了门口右边的黑色开关 ———— 走廊的灯灭了,尴尬... 赶紧再打开。

走过去稍微推了一下玻璃门,纹丝不动 —— 证明这个门应该确实是自动的。这时里边的前台好像也注意到我了,玻璃门自动向两边分开。

正对面是许多的小圆桌子,以及看起来很奇怪的椭圆形椅子,而且高度很低。
左边的就是前台了。

我想了下,直接走到了前台,说:你好,我是面试的。

按照正常流程,应该会给我一张填写个人信息的纸 —— 确实给了我一张。

刚坐下把名字写上,就看见旁边要求写前公司的薪资以及期望薪资的栏目...... 真的,经过上一次公司的洗礼,我都已经打算不想填这个了,但是明显的栏目,不填的话.... 所以还是写了,然后期望薪资,就填写的以前工资上浮 30% 左右的值 (上一次也是这样要求的,但是结果是一分钱都没给上浮...)。

填好之后,最后还有一栏签名,不得透露面试环节中什么的,造成危害公司利益 —— 所以,后面我就只稍微记录一下尚可。
全部完成,交给了前台。

前台说稍等,然后我就坐了回去。

过了一会儿,前台接了一杯水递了过来,我道了一下谢谢。

再等了一会儿,我将杯子放在桌上,四处打量了下,注意到了前台对面的墙壁 —— 上面嵌满了透明的凸槽,里面放了很多像是奖杯、证书一类的东西。墙壁中间开了一道小门,所以将其分成了两块,不过两块都那般的装饰。

小门里面是一些座位,而且现在好像还正有些人在商量着什么。
略过这些,我站起来走到了右边靠大门位置的墙壁,开始观察那些证书、奖杯。

再过一会儿,听到身后有人在叫我的名字,我赶紧回到了前台,是个女生,拿着一叠像是试卷的东西。
看了我一下,递给我说,先做一份笔试题吧。

向前台要了一支笔,我又坐了下来。

笔试题分为了 A 卷 C# 基础和 B 卷 Unity 知识。分量看着还是挺足的。

在我埋头做笔试题期间,还来过一个应届毕业的女生,面试的是策划还是什么职位。后来被带到那两面 “奖杯墙” 里面,声音很大,不过感觉面试挺机械化的。听起来像是事先背诵的词。

然后一直做题一直做题.... 期间有送快递的、有请假的,也有要签字的人,虽然感觉到过了挺久,不过并不清楚时间,因为毕竟是在做笔试题,也不敢随便把手机掏出来。

后面写得桌子上沾了一大块墨水... 汗...

# 笔试

其中,令我印象最深 (或者说感觉做起来有问题) 的主要有三个题:

# (1) 单链表逆序;合并两个有序链表,并保持同样有序;使用递归合并链表

这个题有三问,三问都是要手写代码实现.... 做到这个题的时候,我把第一问做了,留下了后面两问... 没法实际测试,感觉相当烧脑。
第一问,我是采用递归实现的,大致代码就像这样:

s
private Node Reverse(Node node)
    {
        if (node.next != null)
        {
          	Node n = Reverse(node.next);
            n.next = node;
            return n;
        }
        else return node;
    }

大致思路就是:传入的肯定是链表的第一个节点,那么如果这个节点还有下级节点,那么递归,直到获取到的节点是最后一个。
这时候,最后一个节点被返回,并且其下级节点被设置为倒数第二个,倒数第二个返回,下级被设置为倒数第三个.... 直到最开始的第一个节点。

当时没法调试,也不知道对不对,不过感觉差不多应该是这样了.... 后来 (也就是今天), 越想越感觉不大对... 索性就自己试了一下... 结果真有问题 Orz... 上边那个递归代码,就算成功也只能把链表最后一个节点移到第一个节点而已,其它完全还是老样子么... 关键是因为没将 node 的下级节点置空,还会卡死... 真尴尬 Y (>_<、) Y。

真正的递归方式,应当是将当前节点的下级节点的下级设置为自己,然后将当前节点的下级节点置为空才对。这样就相当于交换了链表中两个节点的相互关系。而上边我写出的方法... 相当于每次递归,都把最后一个节点向前移动了一步,其它节点的关系却毫无变化....
不信上图,我专门实现了一下:

对比

左边为成功的,右边就是上述代码造成的结果 (之所以没死循环,是因为我加了最大循环次数限制的)

测试代码如下:

s
// Use this for initialization
    void Start()
    {
        Node node = new Node();
        node.Index = 1;
        Node tempNode = node;
        for (int i = 2; i < 5; i++)
        {
            tempNode.next = new Node();
            tempNode.next.Index = i;
            tempNode = tempNode.next;
        }
        PrintNode(node);
        node = ReverseNode(node);
        PrintNode(node);
    }
    private void PrintNode(Node node)
    {
        Debug.Log("___________________________________________");
        Node n = node;
        do
        {
            count++;
            if (count > 20) return;
            Debug.Log(n.Index);
            n = n.next;
        } while (n != null);
    }
    int count = 0;
    private Node ReverseNode(Node node)
    {
        count++;
        if (count > 20) return null;
        Node n;
        if (node.next != null)
        {
            n = ReverseNode(node.next);
            node.next.next = node;
            node.next = null;
            Debug.Log(n.Index + "  ->  " + node.Index);
        }
        else n = node;
        // 面试时候手写的代码,有错
        //if (node.next != null)
        //{
        //    n = ReverseNode(node.next);
        //    n.next = node;
        //    Debug.Log(n.Index + "  ->  " + node.Index);
        //}
        //else return node;
        return n;
    }
    private class Node
    {
        public int Index;
        public Node next;
    }

后面合并有序链表的问题..... 说实话,整张试卷就这题留空了... 因为当时完全没注意到 Date (即这儿的 Index 的类型),所以还在想什么有序?加上考虑做的时间恐怕太长,就留空了...

后来,在网上找了了一下,这个面试题题目竟然都是有很多。公司用过的... 网上全是相应分析...Orz...
看见分析,才注意到链表有序,指的是其中存储的 Index 有序....Σ(゚д゚;)

# (2) 解释 C# 中的域与程序集?(问题意思应该差不多)

当时对域的情况不是很了解,就回答了自己了解的程序集:程序集相当于包含了所有编译好的代码数据的 Dll 文件 (记得当时... 大概应该是这样回答的吧)。

下来后,查到域的解释:
应用程序域是.NET 引入的一个新概念,它比进程所占用的资源要少,可以被看作是一个轻量级的进程。
在一个进程中可以包含多个应用程序域,一个应用程序域可以装载一个可执行程序(.exe)或者多个程序集(.dll), 这样可以使应用程序域之间实现深度隔离,即使进程中的某个应用程序域出现错误,也不会影响其他应用程序域的正常运作。

至于程序集,好像差不多。
权威一点解释:
程序集构成了基于 .NET 的应用程序的部署、版本控制、重用、激活范围和安全权限的基本单元。程序集以可执行 (.exe) 文件或动态链接库 (.dll) 文件的形式出现,是 .NET Framework 的生成块。它们向公共语言运行时提供了解类型实现所需要的信息。可以将程序集看成是构成逻辑功能单元并为一起工作而生成的类型和资源的集合。

# (3) 最后一个计算两个二维矩阵的题

我直接将其当作了两个矩阵相乘的计算 (后来想起符号是 “X”,也许是矩阵叉乘)。还算错了... 因为我就记得矩阵相乘是行乘列,然后就用第一行第一个数乘上右边矩阵对应列的值...... 最后相加。
最后面试的时候,第一个技术问题就是:你在学校学过线性代数么?
我就想到这个问题估计坏了 T_T。

其它诸如农夫送狼、羊、白菜过河,C# 基础题、Unity 基础题应该都还好。

# 面试

最终答题完成,对面窗户外已经有点发黑了。
将笔试题交给前台,然后去了下厕所,并查看了下时间,记得好像差不多 6 点了,至少做了 2 个半小时吧。

又过了一会儿,一个女生走过来,带我去了更里边。一路走过.... 经过了许多排电脑,不少人都还在上班(毕竟才 6 点多),感觉好些人都在盯我.....
最后进入了最里面的一间会议室吧。两个面试官也走了进来,每个人手里都拿着一份我的简历,其中一个人还带着我的笔试题。

面试开始了。

首先让我做一下知我介绍,虽然经常听说面试开始时这个问题,不过自己倒是第一次被这样问。我还简单回答了一下,说了一下自己名字、老家、工作地点、目前住址之类的。

面试基本上是结合之前的项目来问的,比如说到之前我主要做 AI,是怎么做的?
我说是使用的行为树,而且用一个叫 “Behavior Designer” 的插件。我主要是根据策划要求,添加相应的节点,然后策划来使用行为树配置具体的 AI 行为。

“然后寻路怎么做的?”
开始也是用的一个 “A* Pathfinding Project” 的插件,后来改成了 Unity 自带的 Navmesh 寻路功能。
“为什么要改呢?”
因为使用 A* Pathfinding Project 插件的时候,用的方格寻路,必须一直跟着玩家移动,性能消耗以及平时寻路消耗实际上都比 Navmesh 要大,况且策划也并没有什么高级的需要特殊定制的需求,所以就改成 Unity 自带的 Navmesh 了。

后来问到了我之前做的 Demo,说因为下载的时候太大,所以没看成...
然后问到如果想做一个天赋系统,该怎么实现?差不多类似于技能系统之类的。我就直接按照我实现 Demo 的技能系统回答,说在 Actor 中具有一个技能类,专门放置那些技能,外部调用 XXXX.
后面他们解释说,我的思维模式还在单机上,手游这边的业务不是很熟啊。其实网游很多逻辑都是放在服务器上的,也就是说,比如物品系统什么的,其实是服务器程序做的...

然后问了一些问题,比如喜欢玩什么游戏?玩手游吗?

想了下,单机玩过一些上古 5、辐射 4、巫师 3 之类的,不过还是没说单机的... 我就说最近、前些日子玩过一个网游《无限世界》。

他们想了一下,表示没有听说过,让我解释一下。

我就说无限世界其实是好几年前的游戏了,里面有四个职业 “武侠、机甲、特种兵、法师”,将古代、现代、奇幻、科幻什么的元素糅合在了一块,创意很不错,刚出来的时候还是蛮火的,不过现在.....(估计全服务器也就几十个人顶天了...) 就没落了。
而我之前做的 Demo,其实也有不少是参考无限世界做的。(比如属性值等)

然后又说还玩过《诛仙》。
至于手游... 就接触的少了,而且下来自己还有其它一些需要研究的,所以....

他们解释说,程序经常玩游戏还是有好处的,很多时候策划提出来的要求,都不用想,就直接明白了,甚至可以帮助策划完善其想法。

游戏优化呢?
我说像我之前的 Demo 主要就是代码的优化 (对象池、字符串链接处理、尽量避免触发 GC 等等自己 Demo 都用到过.... 但是没能说出来...),美术资源方面的优化就管的少了,毕竟都是 Assetstore 上找的,而且那些涉及到东西都比较麻烦,多数还是美术配合更好。
那你说说你知道的?
比如减少 DrawCall,使用 LOD.. 使用 StaticBatch,但是这个又要求材质一样效果才好,所以又需要合并贴图啊之类的操作,所以... 美术配合才好办。还有优化模型本身、合并 Mesh 等等。因为是面试,考虑的时间很短 —— 基本上刚问出问题,就要开始回答,所以就大致边想边说,说了这么些。

此外林林总总就不叙述了。

快结束时,之前通知面试的女生也走了进来。

最后还问了一下工资要求,是低于期望工资就不考虑吗,还是?
.... 因为当时刚坐了长途车,想到后面换城市的话,还有搬家、各种麻烦事... 所以考虑了下,回答说差不多吧,那样我想就直接在重庆找工作更方便了。

“要求的期望薪资,是家庭原因还是觉得自己能力足够?”
后者吧。

“你感觉自己做的笔试题怎么样嗯?”
想了下,除了上面那三个印象比较深可能有问题的话,其它应该还好。所以也回答说:应该还算可以吧。

后面又聊了一些其它的,就告辞了。

临走时,还问了下我怎么打算?还有面试吗?
我老实回答说:暂时没了,打算先找个旅馆休息一下,明天直接回去了。

她说道,面试其实可以商量下的,另外从重庆过来,也是可以提前通知,他们也好安排一下后续,比如帮忙找找旅店之类的。

我道了声谢,表示没关系。

跟她一块儿走到了出口处,道别之后,我走出了大门,准备下楼。

# 回归

下了大楼,正值下班时间,天色也有些暗淡了。
路上行人来来往往,相比刚过来时,竟变得有些熙熙攘攘。
空气中飘荡着一股凉风。不过,因为毕竟三月份了,温度已经开始上升,所以也不觉得冷了。

出门就是轻轨,我走了几步,站在了轻轨入口旁。
首先,查询了一下旅馆、酒店。不过收获甚小。

这时,突然收到一条短信.... 显示我已经使用超出流量 35M...?!
于是赶紧关闭了网络,觉得不应该,毕竟我至少还有 100 多 M 的流量才对!在查询流量的时候,才发现套餐流量竟然是 “省内” 的 —— 也就是说,一路上我都是在烧 RMB...

所以决定先前往成都东站,要是没车了,就在车站那边歇一晚 —— 毕竟一般旅馆还是车站附近最多了。
中途因为百度地图发疯,给我找了个需要行走 2 公里的 “快捷路径”,导致 “出站、入站” 了两次,花了两倍地铁的价格才到达成都东站。
最后,本着不再相信车站拉客的人的想法,从阿里的未来酒店订了一个小旅馆,住了一晚。

上午起床的时候,是在 8:30 左右 —— 这也是我一直设定的闹钟时间。

洗了来成都就带着的一个梨,再加上头一天晚上买的晚餐 —— 一包烧饼,晚上也没吃多少,所以剩的挺多。解决了早餐。

本来打算立刻把票订好,不过想到附近就是火车站,所以想直接去火车站买。

9 点多时,打开软件查了下列车信息.... 结果发现,上午的列车票竟然几乎全没了?
剩下的好多都是 “无票”。这时候才发觉得自己的想法有点天真,现在这时代,想准点去车站买票绝对会出问题的。所以赶紧找了个 10:20 的 D 次列车,订了一个一等座 —— 虽然稍微贵点,不过还有票的就这了...

于是在 3 月 4 日,即昨天中午的样子,回到了重庆。

记录结束。