完美世界2017校招技术综合A卷:游戏公司笔试核心考点全解析 每次校招季总有人翻出前几年的经典笔试卷来研究。完美世界2017校招技术综合A卷就是这样一份被反复拿出来讨论的题目原因很简单它代表了一类游戏公司技术笔试的典型出题思路——覆盖面广、基础要求扎实、算法题占比重并且带明显的C倾向。哪怕放在今天这套卷子考察的知识点依然是游戏研发岗笔试的核心理解它的出题逻辑比刷十套新题更有用。我刚入行那会儿为了准备游戏公司校招把能找到的往年笔试题都刷了一遍完美世界的这套A卷是其中质量相当高的一份。它不偏不怪但每道题都能看出出题人对基础功底的重视。这篇文章我结合自己做过的题和后来带新人时总结的经验把这份卷子涉及的核心技术点、典型题型拆开讲一遍同时也聊聊这类笔试背后的考察逻辑。正在准备游戏公司校招的同学或者想系统复习CS基础的开发者都可以参考。1. 从这套综合卷看游戏公司校招笔试的出题逻辑先聊一个很多人忽略的问题为什么游戏公司的技术笔试要考综合卷了解出题动机比纠结每道题本身更有价值。完美世界这类做大型网游、端游、手游研发的公司技术岗位覆盖客户端、服务端、引擎、工具链、数据库运维等多个方向。但校招笔试阶段他们通常不会按具体岗位出得特别细而是先拿一套技术综合卷筛一遍基础。这套卷子的核心目的是确认两件事第一你的计算机基础是否成体系第二在时间压力下你能不能快速准确地解决问题。所谓综合体现在题目分布上。根据我接触过的信息和同类卷子的普遍规律这套A卷大体包含这样几个模块模块大致占比考察目标数据结构与算法35%-40%逻辑思维、编码功底、复杂度意识C/C语言20%-25%内存管理、指针、面向对象理解操作系统10%-15%进程线程、内存调度、并发基础计算机网络10%-15%TCP/IP、Socket、网络编程基础数据库5%-10%SQL基础、索引原理、事务概念逻辑/智力题5%左右临场反应、思维缜密度这个比例不是随便定的。游戏公司无论是客户端还是服务端日常开发都重度依赖C所以语言题占比高是必然的。而算法题占比最高是因为它最能筛选出底层思维能力强的人——这类人上手新项目、排查复杂bug通常更靠谱。有意思的是这套卷子很少出现偏题怪题。我印象中它考的东西都是教材里反复强调的知识点但出题角度会刻意绕开背诵题更多考理解题。比如不会直接问你什么是虚函数而是给你一段存在继承关系的代码让你推导输出结果。这种出题方式背概念的人会吃亏真正写过代码、调试过程序的人反而觉得简单。2. 数据结构与算法模块整张卷子的分水岭数据结构与算法是这套卷子的绝对核心也是面试官最看重的部分。我见过不少笔试成绩不错的同学算法模块就能拉开别人二三十分。这部分的题目往往不直接考会背哪种排序而是换个包装让你现场分析。2.1 链表与树的经典考察方式综合卷里链表和二叉树是高概率出现的考点。原因很直白游戏项目里场景管理、NPC列表、技能CD队列、消息分发底层大量用到链表和树结构。笔试不会考你刷LeetCode那种上百行的难题而是考基础操作的变体。一种典型考法是给定一个单链表判断是否有环并找出环的入口节点。这题看着简单但考察了两个层次第一层是快慢指针的判断方法第二层是找入口时为什么会有一个两倍速的推导过程。很多同学知道快慢指针能判断环但被追问相遇点和入口节点之间的数学关系时会卡壳。我当时复习时专门把这类推导过程写了一遍因为这个为什么比怎么做更能体现你懂不懂。另一种高频考法是二叉树遍历的非递归实现尤其是中序遍历。递归版本大部分人都能写但要求用栈模拟非递归时很多人会在何时入栈、何时出栈、何时访问节点三个状态里绕晕。我建议准备时自己推一遍模拟过程拿一棵三层满二叉树用纸笔画几轮入栈出栈的序列把细节刻进脑子里考场上就会条件反射式地写出来。2.2 排序与复杂度分析不是背是算排序算法几乎是所有综合卷的必考项。这套A卷涉及的排序题重点不在默写代码而在三类问题第一给一个特定数据分布比如近乎有序的数组问选择哪种排序最优。答案是插入排序因为近乎有序时它的比较次数接近O(n)。这题考察的是对不同排序算法特性的理解而不只是时间复杂度表。第二问快速排序在最坏情况下的时间复杂度和触发条件。最坏情况是每次划分都极度不均比如数组本身有序且每次选第一个元素作为基准时退化成O(n²)。我面过的人里有一半能答出O(n²)但说不清触发条件。这其实是排序原理的理解问题。第三要求分析某个排序算法是否稳定并说明原因。以选择排序为例它是不稳定的——比如{5, 3, 5, 1}里有两个5第一轮选出1交换到第一个位置第一个5被换到后面两个5的相对顺序就变了。这种细节题很能看出有没有真正理解排序的交换过程。复杂度分析也是重点。我建议大家复习时不要只记O(1)、O(n)、O(log n)这些记号要能说出每个量级的典型场景。比如哈希表平均O(1)但最坏O(n)二叉搜索树平均O(log n)但退化成链表后变O(n)这些边界情况正是笔试喜欢出题的角落。2.3 一道典型的综合算法题拆解结合这类卷子的普遍规律我复原一道很能代表综合A卷风格的题目给定两个有序数组要求合并后保持有序并分析时间复杂度。这题常见的坑有三个第一个是用concat再排序时间复杂度变成O((nm)log(nm))虽然能过功能测试但在笔试答案里会被扣分第二个是没考虑一个数组先遍历完的情况导致越界第三个是原地merge时从前往后覆盖会把原数组元素冲掉正确的做法是从后往前填。标准的归并写法是双指针从前往后扫描比较两个指针指向的元素小的放入结果数组时间复杂度O(nm)空间复杂度O(nm)。如果题目要求O(1)空间那就利用两个数组尾部有多余空间的特性从后往前移动。这类题目想表达的核心是你不仅要写出能跑的代码还要写出复杂度最优、边界完善的代码。3. 操作系统与网络游戏研发躲不开的底层功课很多准备校招的同学觉得操作系统和网络离游戏客户端开发很远这其实是个误解。客户端要处理多线程渲染、资源异步加载、网络同步服务端要处理高并发连接、内存管理、I/O模型——每一个都和操作系统、网络的底层机制强相关。所以这套卷子在OS和网络上的出题不会浮于表面通常会结合具体场景。3.1 进程与线程绝不只考概念关于进程和线程笔试题目常见的出法有几种线程和进程的优缺点对比、进程间通信方式列举、死锁产生的四个必要条件。但完美世界这类公司的卷子往往还会加一道场景题。我印象里比较典型的一道是多个线程同时对一个全局变量做自增操作最终结果一定等于线程数吗答案是不一定因为自增操作不是原子的它包含读取、加一、写回三步多个线程交错执行时会出现丢失更新。进一步追问就是如何解决加锁互斥锁、原子操作C11的std::atomic、或者无锁编程。这题考察的是对并发本质的理解而不是靠背概念能答好的。死锁那四个条件——互斥、占有并等待、不可抢占、循环等待——也是必背。但笔试常考的是变体给一段加锁代码判断是否可能死锁或者问怎么打破死锁条件。我记得当年复习时自己总结过一句解决死锁最实用的思路是让加锁顺序全局一致比如两个线程都按先锁A后锁B的顺序取锁循环等待就被破坏了。这句话在笔试论述题里很好用。3.2 TCP三次握手与Socket编程的常见考点网络模块里TCP三次握手和四次挥手几乎是必考。但程度好的卷子不会只让你默写过程而是会问为什么握手要三次挥手却要四次答案的关键在于握手时双方都能主动发起连接所以第三次握手是为了确认客户端的接收能力正常防止已失效的连接请求突然到达服务端造成资源浪费而挥手时服务端可能还有数据要发所以ACK和FIN分开发送就多了一次。Socket编程题也经常出现常见的考法是给一段代码让你指出错误或说明流程。比如客户端connect失败后立即close服务端在accept之前客户端就发数据这些问题都考察了对TCP状态机的理解。我建议复习时把listen、accept、connect、read、write、close这个流程在纸上默写一遍同时标出每步的系统调用可能返回的错误码比单纯看书有效得多。另外OSI七层模型和TCP/IP四层模型的对应关系也是基础题但通常不会单独出而是绑定在具体问题里。比如问HTTP和HTTPS各自工作在哪一层HTTPS在TCP和HTTP之间加了SSL/TLS层目的是加密和身份认证。这种题简单但能看出你是否有完整的网络分层意识。3.3 内存管理游戏客户端最敏感的话题游戏开发对内存是出了名的斤斤计较。客户端一份资源的加载、卸载、缓存策略服务端每个玩家对象的内存占用都直接影响性能。所以这套卷子里内存管理相关题目也有一席之地。虚拟内存、分页、分段这些概念属于基础常考的是虚拟内存解决了什么问题——让多个进程能隔离运行同时允许进程使用超过物理内存大小的地址空间。而堆和栈的区别几乎每年都考考察点包括分配方式栈自动分配、堆手动分配、分配方向栈向低地址增长、堆向高地址增长、效率差异栈高、堆低和存储内容栈存局部变量和函数调用信息堆存动态分配的对象。C相关的内存考察还会深入到内存泄漏——程序运行过程中不再使用的内存没有被正确释放。笔试常考的形式是给一段代码找出内存泄漏的位置或者问用哪些工具可以检测valgrind、AddressSanitizer等。这里我多说一句面试官问这些其实是想知道你有没有真正的调试经验因为内存泄漏这种问题光看不练是发现不了的。4. C/C语言与数据库游戏公司最看重的基本功游戏公司技术岗C是绕不开的主语言。无论是客户端引擎还是服务端逻辑绝大部分代码都是C写的。所以这套综合卷里C相关题目占的比重相当大而且考得非常细。数据库模块占比虽然不大但往往会有一道服务端玩家数据存储相关的SQL题。4.1 指针、引用与内存经典中的经典指针和引用的区别是C笔试的常青树这套卷子也不例外。两者的核心区别包括引用必须初始化且不能改变指向、引用没有独立的内存地址从语义上讲、sizeof(引用)得到的是所引用对象的大小而sizeof(指针)在64位系统下是8字节、指针可以有多级但引用不行。这些点不复杂但很多人被问到时容易漏项建议用表格把区别写全记忆。智能指针也是高频考点。C11引入的unique_ptr、shared_ptr、weak_ptr分别解决什么问题、各自的使用场景是什么这是校招生必须清楚的。我见过一道很典型的题多个shared_ptr循环引用会导致什么答案是引用计数无法归零造成内存泄漏。解决方法是把其中一个改为weak_ptr打破循环。这道题在游戏项目的对象管理里有非常实际的应用场景——比如场景对象和其子对象互相持有对方的shared_ptr时。const关键字的各种用法也是常考项。const修饰变量、指针const int* p和int* const p的区别、成员函数const成员函数承诺不修改对象状态、函数参数const引用避免拷贝基本都是送分点但如果平时没在意很容易在指向const的指针和const指针之间绕晕。4.2 面向对象三大特性的笔试出题方式面向对象——封装、继承、多态——在C笔试里很少直接问什么是多态而是通过代码题考。比如给一段包含基类、派生类和虚函数的代码问输出结果是什么如果析构函数没有加virtual会发生什么。这里有个经典考点基类析构函数不声明为virtual通过基类指针delete派生类对象时只会调用基类的析构函数派生类的析构函数不会执行导致派生类中动态分配的资源泄漏。正确答案是把基类析构函数声明为virtual。为什么因为虚析构让delete动作能沿着虚函数表找到最底层的派生类析构函数实现从外到内的完整析构。字节对齐、构造函数和析构函数的执行顺序先基类后成员再自身也是常出的题。纯虚函数和抽象类也是高频考点。抽象类不能实例化纯虚函数是接口约定由派生类实现。游戏开发里的组件系统、状态机、寻路算法经常用抽象基类定义接口再派生出不同实现。笔试考这个本质上是看你对面向接口编程有没有概念而不只是记语法。4.3 数据库SQL与索引基础数据库题在这套卷子里题目量不大但属于送分题级别丢了可惜。常见考点包括SQL基本增删改查、多表连接inner join、left join的区别、GROUP BY配合聚合函数的使用以及索引的基本原理。有个特别经典的考察点是给一张表问在哪些字段上建索引能提升查询效率为什么。答案不是全建索引就完事——因为索引会降低写入速度、占用存储空间。正确思路是在WHERE条件、JOIN关联字段、ORDER BY排序字段上建索引在高区分度字段比如玩家ID上的索引效果优于低区分度字段比如性别。同时使用函数包裹字段、隐式类型转换、LIKE前置通配符都会让索引失效这些都是在游戏日志查询中经常遇到的坑。事务的ACID特性、隔离级别、脏读/不可重复读/幻读的区别也偶尔出现。这些概念对服务端处理玩家并发操作非常关键——一个交易系统如果事务隔离级别没选对就可能出现玩家同时买一件物品导致超卖的问题。5. 笔试实战中的通用策略拿到题目后怎么思考这部分我想聊聊比具体知识点更重要的东西——考场上面对一套综合卷你的解题顺序和思考策略。我当年参加笔试时吃过亏后来帮别人做模拟面试也发现不少同学不是不会而是策略出了问题导致会做的题也丢了分。5.1 时间分配先拿稳定分再啃硬骨头技术综合卷的题量通常不小时间却只有两小时左右。我建议拿到卷子先花两分钟快速浏览一遍所有题目做一次难度分级第一档稳定分概念题、基础知识选择题。比如sizeof大小、SQL查询、简单复杂度判断。这类题要先做确保拿满。第二档重点分中等难度算法题、代码阅读题。这类题需要思考和一定时间放在中间做。第三档拔高分综合算法大题、开放性设计题。放到最后时间不够时至少写出思路框架能拿过程分。一个常见误区是死磕某道卡壳的算法题做完一道再说。笔试不是竞赛过线需要的是总分的稳定而不是单题的完美。我见过不少同学在快排的非递归实现上耗了二十分钟结果后面简单的SQL题和网络题没时间做非常不划算。5.2 代码题的答题规范思路比结果更重要手写代码题阅卷老师通常有两种评分方式一种对照测试用例看结果另一种按步骤看思路。很多公司的笔试题其实兼有两者——代码能跑通最好跑不通的话思路清晰也能拿到大部分分。所以写代码题时我会这样组织答案先在旁边用一两句话写明算法思路用什么数据结构、关键步骤是什么再写代码代码里注释重点行的作用。比如写归并排序时先写递归拆分有序合并时间复杂度O(nlogn)再开始写代码。这样就算个别边界条件写错阅卷人也能看出你懂这个算法。还有一点变量命名尽量语义化。笔试代码虽然不用达到工程标准但一个叫mergeHelper的函数总比f1、f2显得专业。这个细节在阅卷时是真的会加印象分的。5.3 心态与验证写完代码一定要走一遍示例笔试时最常见的丢分原因是代码写完不验证。建议写完一道算法题立刻用一个最简单的输入在脑子里跑一遍代码逻辑检查边界数组为空时怎么办只有一个元素时怎么办目标值不存在时返回值是什么比如写二分查找时检查左右指针的更新逻辑会不会死循环写链表反转时检查头节点为nullptr时会不会解引用空指针。这些小细节平时在自己电脑上编译运行根本发现不了但笔试考的就是你在无编译环境下的严谨度。平时练习时养成写完就走查的习惯考场上就不会心里发虚。6. 复盘与备战这套卷子教我的几件事最后聊点实际的关于这套2017年的试卷对后来备战校招的参考价值。虽然题目逐年更新但核心考察逻辑是稳定的。我复盘下来有几点想强调的。把基础概念理解透比刷题数量重要。这套卷子里的题目严格来说没有一道是超纲的全部来自教材里的基础知识。但为什么有人考高分、有人挂在60分线上区别就在于对为什么的理解深度。快慢指针为什么能判环、虚析构为什么能避免内存泄漏、TCP为什么三次握手——这些问题的答案教科书上有但没有深入思考过的人考场上很难自己推出来。动手写代码和纯看书的复习效果差别巨大。我准备校招那阵子每天坚持手写两三道经典算法题不依靠IDE提示写完用编译器验证。坚持一个月后笔试时手写代码的流畅度明显不一样。强烈建议准备阶段用纸笔写代码编译器验证的方式练习这能模拟考场环境又能得到反馈。最后想分享一个小心得不要把复习局限于单一公司的真题。完美世界这套2017年A卷的知识点覆盖面其实是很多游戏公司、互联网公司技术笔试的共性。我当年刷完这套卷子后再去参加其他公司的笔试发现很多题目只是换了层皮核心考点大同小异。把一套综合卷吃透比零散地刷几十套题效率高得多。如果你正在准备校招建议拿这套卷子做个自测卡好时间做完然后逐题复盘自己的卡壳点。那些让你犹豫的题目就是你接下来复习的重点方向。笔试没有捷径但走对方向、用对方法确实可以少走很多弯路。