每年秋招季,我都能在牛客和知乎上看到大量关于笔试题的吐槽和求助帖。技术笔试这东西,对很多同学来说就像开盲盒——刷了几百道 LeetCode,结果发现题目风格完全对不上;或者以为游戏公司会考渲染管线、游戏引擎,结果拿到卷子发现全是算法和操作系统。这篇就以 iHandy(趣加)2019 年技术类笔试题为样本,聊聊游戏公司校招技术笔试背后的筛选逻辑、高频题型,以及一套可以直接拿去用的备考思路。虽然手头没有官方原卷,但这几年游戏公司校招技术笔试的出题风格基本稳定,结合我自己的做题和参与校招筛选的经验,这篇文章的参考价值不会比原卷低多少。
1. 一份校招技术笔试的真正意图:筛选信号而不是选拔天才
很多人拿到笔试题的第一反应是"我要全部做对",这个出发点就错了。你要是站在出题人的角度想,一份笔试的核心任务不是在 90 分钟里找出满分选手,而是用最低成本筛掉不合适的人。尤其是游戏公司,技术岗投递量动辄上千,面试资源有限,笔试题就是第一道漏斗。
1.1 游戏公司技术笔试和互联网大厂的差异点
同样是技术笔试,游戏公司和纯互联网公司出的题是有细微差别的。纯互联网公司更偏重工程实现和业务场景,有时候会直接给你一段业务代码让你找 bug、优化。游戏公司这几年我看到的校招笔试题,反而更偏重基础算法和计算机底层原理。原因不复杂:游戏引擎、物理模拟、网络同步这些东西,背后的基础就是数据结构、算法、操作系统和网络。一个能把滑动窗口算法和 TCP 拥塞控制讲清楚的人,学起 Unity 的渲染管线和帧同步来也快。
iHandy 这家的背景也可以参考一下。趣加当时有《阿瓦隆之王》《火枪纪元》这类 SLG 产品在跑,SLG 的核心技术难点是什么?大区服架构、实时战斗同步、大量玩家并发下的状态一致性。所以如果当年的笔试题里出现了分布式、网络通信、并发相关的题目,完全符合产品特征。你带着这个视角去准备,就能理解为什么有些知识点反复出现。
1.2 笔试成绩在整条筛选链路里的定位
笔试成绩通常不是一票定生死,但它是面试官和你聊天的起点。我见过不少同学笔试答得一般,但简历里有一个很有意思的个人项目,面试官照样愿意深聊。反过来也一样,笔试分数高但简历毫无亮点,面试时也容易陷入"算法题背得很熟,但一问项目就空白"的尴尬。
所以我的建议是:笔试要当回事,但别当成全部。你真正要展示的,是你的思维过程可被引导、基础概念没有死角、代码实现干净利落。这三个信号,才是几道算法题背后真正被考察的东西。
2. 笔试题型的整体分布:从题型结构反推复习优先级
把这类笔试题拆开看,大致是四块:编程题、计算机基础选择题、智力逻辑题,偶尔还会有一两道和游戏场景结合的情景设计题。不同公司占比不一样,但 2019 年前后游戏公司统一笔试的风格,编程题通常占 40%-50%,计算机基础占 30% 左右,剩下的智力题和简单问答占 20% 左右。
题型分布我整理了一张表,方便你对照复习节奏:
| 题型 | 常见考察点 | 建议复习优先级 | 单题建议用时 |
|---|---|---|---|
| 编程题 | 滑动窗口、动态规划、二叉树、字符串处理 | 最高 | 15-20 分钟/题 |
| 选择题 | 数据结构、操作系统、网络、数据库 | 高 | 1-2 分钟/题 |
| 智力题 | 逻辑推理、概率、数学归纳 | 中 | 3-5 分钟/题 |
| 情景设计 | 系统设计初级方案、场景拆解 | 中低 | 10 分钟/题 |
这个结构告诉你一个信息:如果你时间有限,优先刷算法题永远是性价比最高的选择。选择题再熟也就是一道题的分数,编程题一道往往顶好几道选择题的分值。
3. 编程题详解:两道典型题目从读题到 AC 的完整心路
编程题是整张卷子的主战场。这类题往往不是 LeetCode 原题照搬,而是把常见题型包了一层新的场景外衣。核心还是那些东西:数组、字符串、链表、二叉树、动态规划、贪心、二分。下面我用两道高频题型的变体,完整走一遍从读题、思路推导到代码实现的过程。
3.1 字符串处理与滑动窗口:最长无重复字符子串的变体
题目版本通常是这样的:给定一个字符串,找出其中不含有重复字符的最长子串的长度。这是 LeetCode 第 3 题的原型,也是 2019 年前后校招笔试里出现频率极高的一道题。它考的不是你会不会背解法,而是你能不能现场推导出"滑动窗口"这个思路。
我第一次见这道题时,第一反应是暴力解法:枚举所有子串,逐个判断是否有重复字符。复杂度是 O(n²) 甚至 O(n³),字符串一长直接超时。后来才明白,这里面存在大量的重复计算——每次移动右边界时,我其实只需要关注当前窗口内有没有重复,而不需要从 0 开始重新验证。
正确的打开方式是维护一个滑动窗口,用哈希集合记录窗口内出现过的字符。右指针每次向前移动一位,如果新字符不在集合里就加入并更新答案;如果新字符已经在集合里,就不断移动左指针,直到把重复的那个字符移出窗口。
Python 的实现很干净:
def length_of_longest_substring(s: str) -> int: char_set = set() left = 0 ans = 0 for right in range(len(s)): while s[right] in char_set: char_set.remove(s[left]) left += 1 char_set.add(s[right]) ans = max(ans, right - left + 1) return ans这里有一个细节值得停下来想:内层 while 循环看起来是 O(n) 的,为什么总体复杂度还是 O(n)?因为 left 指针在整个过程中一共只会向右移动 n 次。每个字符进入集合一次、移出集合一次,均摊下来就是 O(n)。这种"双指针均摊分析"的思路,在很多编程题里都会用到,理解了它,你就不是背题,而是真正掌握了滑动窗口的底层逻辑。
在笔试场景下,还有一个很重要的环节:写完代码后,主动在注释里标出时间和空间复杂度。我当年参加笔试时注意到,很多在线笔试系统会留一块空白让你写"解题思路",这个千万别空着。面试官看代码时,第一眼就是你的复杂度分析,写清楚了,即使代码有小 bug,也能传递出"这家伙思路是对的"的信号。
3.2 动态规划:从斐波那契到带条件的爬楼梯
动态规划是另一道绕不过去的坎。这类题的分值通常比较高,而且一旦做出来,很容易和竞争者拉开差距。常见的考法是给一个经典 DP 模型套上一点"坏境"条件。举一个典型的例子:你正在爬楼梯,每次可以爬 1 阶或 2 阶,但其中有一阶因为损坏不能踩,给定总阶数 n 和损坏台阶的编号,求到达顶部的不同方案数。
拆解一下:设 dp[i] 表示到达第 i 阶的方案数。正常情况下的转移方程是 dp[i] = dp[i-1] + dp[i-2]。损坏台阶的处理不复杂,如果第 i 阶是坏的,dp[i] = 0,因为你不能停在一个坏台阶上,只能跳过它。
写出来就是:
def climb_stairs_with_broken_step(n: int, broken: int) -> int: if n <= 1: return 1 dp = [0] * (n + 1) dp[0] = 1 # 从地面出发算一种起点 for i in range(1, n + 1): if i == broken: dp[i] = 0 else: dp[i] = dp[i - 1] + (dp[i - 2] if i >= 2 else 0) return dp[n]这道题真正的考点不是转移方程本身,而是你有没有意识到"损坏台阶要单独置零"这个边界条件。很多同学会把损坏台阶当成"不能通过",然后在遍历时直接 continue,这样会导致从它出发跳出去的路全部断掉,答案是错的。正确逻辑是 dp[i] 置零,但它后面的台阶仍然可以从更前面一跳跨过它到达,所以 dp[i+1] 和 dp[i+2] 的计算完全不受影响。
我拿这个例子出来说,是因为它代表了一类很典型的笔试考法:把经典模型包装成新场景,考你在理解原理基础上的迁移能力。刷题如果只背模板,遇到这种变形题就容易翻车。这就是为什么我更推荐按"题型背后的思维模型"去复习,而不是按题目名称去背。
4. 计算机基础题的高频考点:数据结构、操作系统、网络一个都不能少
编程题之外,选择题和简答题覆盖的范围很广,但高频考点相对集中。如果你时间紧,优先把这些知识点过一遍,大概率能拿下一大半基础题。
4.1 数据结构:重点是"原理理解"而不是"API 背诵"
选择题里最常见的一类,是给你一段代码或者一个操作序列,问你时间复杂度或者最终结果。比如"在链表中插入一个节点的时间复杂度""哈希表解决冲突的常见方式""二叉搜索树中序遍历的结果是什么"。
这里有个容易踩的坑:很多人把时间和空间复杂度背得滚瓜烂熟,但遇到具体的操作序列就蒙了。原因在于,复杂度分析需要基于"操作逻辑",而不是记忆结论。比如 HashMap 的 get 操作,平均是 O(1),但在大量哈希冲突的情况下会退化到 O(n)。笔试如果问"什么情况下 HashMap 会退化",考察的就是你有没有真正理解哈希表的底层实现。
复习数据结构时,建议画图理解,不要光看文字。链表反转、二叉树遍历、堆的插入和删除,这些动作你都能在白板上画出来,才算真正掌握。笔试虽然不要求你画图,但如果你脑子里有那个动画,代码写起来会顺畅很多。
4.2 操作系统:进程线程和死锁是永远的主角
操作系统这块,高频考点集中在进程与线程的区别、进程调度算法、死锁产生的四个必要条件、虚拟内存和页面置换算法。游戏公司尤其关注多线程相关的问题,因为游戏引擎里渲染、物理、网络都在不同线程上跑,线程安全是个逃不掉的话题。
常见的题干是:给一个多线程程序,问运行结果或者是否会有并发问题。这类题考的是你对"原子性、可见性、有序性"的理解。我建议复习时把经典的"银行转账"问题彻底搞清楚:两个线程同时对同一个账户做读改写,怎么保证不丢更新?答案无非是加锁、原子类、或者避免共享。把这个场景想明白,大部分并发选择题你都能应付。
死锁那个经典的"哲学家就餐"问题也很值得花时间想一遍。它考的不是你能不能背出死锁的四个条件(互斥、持有并等待、不可剥夺、循环等待),而是你能不能分析出一个具体场景是否满足这四条件,以及怎么破坏其中一个条件来解决死锁。笔试常给代码片段问你"是否会发生死锁",所以我会刻意练习在代码里识别这四个条件的习惯。
4.3 网络与数据库:两个"够用即可"但也别丢分的板块
网络方面,TCP 三次握手、四次挥手、TCP 与 UDP 的区别、HTTP 常见状态码,这几项几乎是必考的。游戏公司会额外关注"如何保证实时性",所以 UDP 和 TCP 在游戏场景下的取舍也是一个常见问法。比如 FPS 游戏的位置同步为什么用 UDP 而不是 TCP?因为 TCP 的重传机制会导致延迟累积,游戏内玩家的位置信息是"过期了就不要了",而不是"丢了就必须重传"。这个理解到位了,说明你对网络协议不是死记硬背。
数据库部分通常不会太难,考察 SELECT、JOIN、索引的原理。有一个容易被忽略的考点:索引为什么能加速查询?底层是 B+ 树还是哈希表?这两者各适合什么场景?能把 B+ 树和哈希索引的区别讲清楚,数据库的分数基本就稳了。
5. 智力题与逻辑推理题:游戏公司特有的"筛选器"
很多同学看到智力题就慌,觉得自己数学不好、逻辑不行。实际上,游戏公司校招笔试里的智力题,考察的不是"小聪明",而是你有没有拆解复杂问题的习惯。这个能力在游戏系统设计和运营活动设计中非常关键。
5.1 经典题型:概率题里的"换不换"陷阱
概率类智力题几乎是每年都会出现的。最经典的就是三门问题:有三扇门,一扇后面是奖品,另外两扇是空的。你选择一扇门后,主持人打开一扇没有奖品的门,然后问你要不要换另一扇门。换还是不换?
答案所有人都知道是"换",但笔试真正想看到的,是你能不能用概率语言把理由写清楚。我第一次认真推这个结论时也觉得反直觉——其实关键在于主持人不是随机开门的,他知道哪扇门有奖品,并且一定会开一扇空门。这个信息改变了概率分布:你初始选中的概率是 1/3,另外两扇门合起来是 2/3,主持人帮你排除掉一扇空门后,剩下那扇门就承接了全部的 2/3。所以换门的中奖概率是 2/3,不换只有 1/3。
这类题在笔试里的意义不是考你会不会算,而是看你能不能写清楚推导链条。答题时哪怕最终结论不对,只要推导过程有逻辑,也能得到部分分数。
5.2 逻辑推理题:从条件出发逐层推进
另一类常见的是纯粹的推理题。比如:有五个房子一排,每个房子的颜色、主人国籍、饮料、香烟、宠物各不相同,给出若干线索,问谁养鱼。这就是著名的爱因斯坦谜题。
面对这种题,不要直接在脑子里推,拿张纸画表格是最高效的方式。5x5 的表格列出来,一条一条线索往里填,能确定的打勾,能排除的打叉。实际上,笔试里的逻辑推理题绝大多数都可以用"约束传播"的思路解决:先找最确定的线索,然后逐步缩小范围。这种做题方式本身就是一种能力展示——你在草稿纸上是否有序地推进,会反映到你的答案质量上。
6. 备考路线图:从这段笔试经验反推出来的冲刺清单
聊完了具体的题型和解题思路,最后说说怎么高效准备这样一场笔试。我身边有同学刷了 300 道 LeetCode 结果笔试还是翻车,也有同学只刷了 100 道却顺利通过,差别不在数量,而在复习方式。
6.1 刷题顺序:按"题型模板"而不是"题目难度"来
LeetCode 上有按难度分级的标签,但按难度刷很容易陷入"简单题不想刷,难题刷不动"的尴尬。我更推荐按题型分类刷,每个类型集中攻克,直到形成肌肉记忆。
优先级排第一的是滑动窗口、双指针、前缀和这类数组技巧题;第二是动态规划的经典模型(背包、爬楼梯、最长递增子序列、编辑距离);第三是二叉树相关的遍历和递归。这三块覆盖了校招笔试题的大部分编程题。链表和栈/队列的题相对简单,花的时间不用太多,但要保证基础的题不丢分。
每道题做完之后,别急着 next,花两分钟想想:这题的解法能不能应用到其他场景?比如滑动窗口,除了最长无重复子串,还能用在"长度最小的子数组"和"字符串排列"上。这种举一反三的整理,才是刷题数量能转化为笔试分数的关键。
6.2 模拟笔试:用真实的体感校验节奏
至少提前一周做一次完整的模拟笔试。找一套题,设置 90 分钟闹钟,在安静的环境下从头做到尾。这个动作的价值在于:让你提前暴露两个大问题——时间分配不合理和写代码速度慢。
我自己的经验是,前 10 分钟先快速浏览全卷,标记出会做和不会做的题。编程题如果 10 分钟内没有清晰思路,就先跳到下一题,最后再回头啃。选择题控制在平均每题 1 分半以内,拿不准的题先凭第一感觉选一个,继续往下走,不要在单题上耗太久。
模拟笔试最容易被忽略的环节是复盘。做完题之后,不管对错,把每道题的思路重新整理一遍,特别是有思路但没写完整的题——这些题才是你能提分的点。错了的题看一遍标准解法就过,收获远不如把"没写完的题"补完整。
6.3 考场上的一些碎碎念
最后聊几个考场上很实用的小细节。代码尽量写得清晰、变量名用有意义的名称,不要图快写出一堆 a、b、c。笔试系统阅卷时,面试官会看你的代码风格,干净的代码即使有小 bug 也会留下好印象。
如果题目没有明确要求,我建议优先选择自己最熟悉、写起来最快的语言。2019 年的笔试系统通常支持 C++、Java、Python,选你最熟的那个,不要在考场上冒险换语言。
还有一点可能不太起眼但很重要:注意审题。很多同学编程题丢分不是因为不会,而是没看清输入格式和边界条件。比如字符串可能包含空格,数组可能是从 1 开始编号,题目要求的输出格式是"空格分隔"还是"逗号分隔"。这些细节,考场上读题时用笔圈出来,能避免非常多无谓的失分。