写过游戏公司实习生笔试的人都知道,笔试这一关刷人有多狠。搜狐畅游18届游戏开发实习生笔试(20170705场次)我印象很深,当时考完出来,很多同学都在吐槽题量大、覆盖面广,而且部分题目看起来不像“游戏开发”而像“后端开发”。但回过头看,这场笔试其实很典型地反映了大厂游戏部门对实习生的真实要求:不是招一个只会写玩法逻辑的码农,而是招一个基础扎实、能快速上手工程、又懂一点游戏底层的人。这篇文章就把我复盘这场笔试的经验整理出来,包括题型结构、核心考点、典型题目的解题思路,以及几个我当时踩过的坑。目标是让后面准备游戏开发实习的同学,无论是准备搜狐畅游还是其他游戏公司,都能有一份可参考的“作战地图”。
1. 笔试整体评价与考察逻辑
1.1 这场笔试到底在考什么
很多准备游戏开发实习的同学,第一反应是把重心放在Unity或Unreal的API、GamePlay逻辑、物理碰撞、动画系统这些“游戏感”很强的知识上。但搜狐畅游这场笔试给我的感觉是:它更看重的是计算机基础功底,而不是引擎API的熟练度。
整张试卷的构成大概可以分成四块:C/C++语言基础、数据结构与算法、操作系统/网络基础、游戏数学与少量游戏开发常识。其中C++和算法占了最大的比重,游戏数学次之,纯引擎API的题目反而很少。这和大厂游戏工作室的用人逻辑是一致的——实习生入职后需要快速融入项目,而游戏引擎只是工具,真正决定你能走多远的,是你能不能写出高性能、低Bug、可维护的底层代码,能不能理解服务器架构和帧同步逻辑。换句话说,笔试筛选的是“底子好、可塑性强”的人,而不是“背了很多引擎属性的人”。
1.2 从题型配比看公司期望
我当时拿到的试卷,题型大致包括:单选、多选、填空题、简答题和两道编程题。前两类主要考C++语言细节、数据结构复杂度、操作系统基础;填空和简答会涉及一些游戏数学计算、内存对齐、虚函数表这类偏底层的问题;编程题则是一道算法题和一道简单逻辑题。
从配比来看,选择题和填空题覆盖的知识面极广,经常有那种“你知道就知道,不知道只能蒙”的冷门细节。这不是为了刁难人,而是游戏开发中确实会遇到这些细节:C++内存模型、多线程同步、网络字节序、定点数精度……每一个都可能成为线上Bug的来源。公司希望实习生在校招阶段就具备这些基本素养,降低培养成本。所以,如果你现在还在准备阶段,建议把重心从“背引擎API”转移到“啃C++和算法”上,这是性价比最高的策略。
提示:如果你的目标是游戏客户端开发,也不要忽略服务器和网络基础。笔试中出现网络协议、同步机制相关题目是常态,因为游戏开发本质上是一个分布式实时交互系统。
2. 核心考点拆解:每一个知识点背后的游戏开发场景
2.1 C++语言细节:比想象中更“刁钻”
游戏客户端和服务器的核心代码,绝大多数是C++写的。所以笔试中C++部分的题目,往往不是简单的“构造函数和析构函数调用顺序”,而是会深入到内存布局、虚函数、STL底层实现等细节。
比如我印象中有一类题目:给你一个类,里面有普通成员、虚函数、静态成员,问你sizeof(类)是多少?这类题目考的是内存对齐和虚表指针。如果没有真正研究过C++对象模型,很容易算错。我当时就因为在“空类的大小为什么是1”和“虚表指针在内存中的位置”这两个点上犹豫,多花了不少时间。
这类知识点对应到游戏开发中非常实际。比如一个游戏实体类,可能同时有位置、速度、渲染组件、网络状态等字段,如何在内存中紧凑排列,减少Cache Miss,直接影响帧率。再比如网络同步中需要序列化对象,如果你不理解内存对齐和Padding,序列化出来的数据可能多出很多无用的字节,导致网络包变大。所以C++对象模型不仅是面试题,更是游戏开发的基本功。
另一个高频点是const和static的各种组合用法,比如const成员函数、const引用返回、static局部变量生命周期。这类题目看起来基础,但很容易在特定场景下出错。例如std::sort的比较器如果写成非const成员函数,编译不过;全局静态变量的初始化顺序问题,可能导致启动崩溃。游戏项目里往往有大量全局管理器,如果不注意静态变量初始化顺序,游戏在特定机器上一启动就崩溃,排查起来非常痛苦。
2.2 数据结构与算法:用什么姿势解题更吃香
算法题在笔试中的占比通常为一道中等难度的编程题,以及若干选择填空。搜狐畅游的题目风格偏向于实际应用,不会出太偏的竞赛题,但也不像LeetCode那样直接给你一个“判断回文链表”的模板题,而是会套一层“游戏场景”的壳。
比如常见的题干有:在网格地图上,从起点到终点的最短路径,考虑不同地形的移动代价;或者给你一个技能冷却时间数组,求某一时刻可以释放的技能;或者模拟一个排行榜,支持插入和查询TopK。这些题本质上是BFS/DFS、优先队列、二分查找等经典算法的变种。如果你只会背模板,不理解算法背后的场景建模,看到题目会发懵。
我当时遇到的一道编程题,大致是:在一个二维数组中,每个格子有一个数值,代表从该格子出发能跳跃的最大步数,问是否可以从左上角跳到右下角。这其实是“跳跃游戏”的二维版本,用BFS或者动态规划都可以做。我用的BFS,因为路径搜索思路直观,而且不容易漏解。如果你准备这类题目,建议把LeetCode上的搜索类、DP类、TopK类题目刷熟,特别是BFS/DFS和优先队列的组合应用。
另外,有些选择题会考排序算法的稳定性、时间复杂度、堆和栈的区别、哈希冲突的解决方式。这些都非常基础,但却是游戏开发中会真实遇到的。比如Unity中每次FindGameObject都要遍历场景中的所有对象,如果你不想卡顿,就需要自己用哈希表建立索引;再比如技能系统的Buff排序、伤害结算顺序,可能就是一个稳定排序问题。这些看上去“低端”的知识点,恰恰是实际工程中最常碰到的。
2.3 游戏数学:绕不开的向量、矩阵与插值
游戏开发笔试中必然会有数学题,通常是向量加减、点乘叉乘、矩阵变换、四元数概念。这些内容在Unreal和Unity的API中都有封装,但笔试会直接考察你的数学原理,因为你需要理解它们才能正确使用API,更别说自己写Shader或物理逻辑。
常见的考点:
- 点乘判断两个向量夹角,常用于视野判断、前后方向判断;
- 叉乘计算法向量,用于计算朝向、左右方向;
- 矩阵乘法与变换顺序,例如“先旋转后平移”和“先平移后旋转”的结果差异;
- 四元数表示旋转,以及它为什么优于欧拉角(避免万向节锁);
- 平滑插值(Lerp)、线性插值与球面插值(Slerp)的区别。
笔试中可能会给你一个具体数值,让你手算点乘或叉乘结果。我当时就遇到一道给两个三维向量求叉乘的填空题,由于太久没手算,愣是卡了几分钟。这里提醒大家,不要只依赖引擎API,一定要能自己写出向量运算公式。因为在实际开发中,你可能要写采样点计算、AOI(Area of Interest)检测、技能扇形范围判断,这些都是手写向量运算的活。
另外一个比较容易忽略的点是“右乘和左乘”的区别。游戏引擎中坐标变换经常写Matrix * Vector,但不同的数学库(行主序/列主序)写法不同,很容易搞反。笔试中不会直接考API,但会考“一个物体先绕Y轴旋转90度,再沿X轴平移10个单位,最终变换矩阵是什么?”如果你对矩阵乘法的顺序没有刻到骨子里,这种题必错。
注意:四元数和欧拉角的转换是高频考点。不需要背公式,但必须理解为什么欧拉角在俯仰角接近正负90度时会丢失一个旋转轴,以及Unity中
Quaternion.Euler的实现原理。这些在第三人称相机控制中极易踩坑。
2.4 操作系统、网络与设计模式:容易被忽略的“隐藏科目”
游戏开发实习笔试中,操作系统和网络知识一般占比不高,但一旦出现,就是拉开差距的地方。搜狐畅游的笔试题里有一两道关于线程/进程区别、锁的类型、死锁条件的选择题。这很好理解:游戏服务器要处理大量并发请求,客户端也要做资源的异步加载,多线程编程是游戏开发刚需。
我印象比较深的是一道关于“自旋锁和互斥锁区别”的题。很多人只知道一个忙等待一个睡眠,却不知道自旋锁适用于临界区极短的场景,而互斥锁在锁竞争激烈时涉及线程切换开销。游戏引擎的渲染线程和逻辑线程之间的同步,往往会用自旋锁来避免过高的上下文切换成本。这类知识点如果没有实操经验,很难答好。
网络部分则偏向TCP/UDP的区别,Socket编程的基本流程,以及游戏同步中的帧同步和状态同步概念。可能出一道简答题:MMORPG中玩家移动同步,你会选择TCP还是UDP?为什么?答案不是简单的“UDP快所以选UDP”,要结合可靠性、顺序性、延迟和丢包补偿机制来答。我当时把帧同步和状态同步的区别写了一下,并提到UDP上可以自己实现可靠传输(例如KCP协议),应该是一个加分项。
设计模式在笔试中通常以选择题或简答题出现,比如单例模式、观察者模式、状态模式的优缺点,以及适合的游戏场景。游戏客户端里,单例模式常用于全局管理器(如UI管理器、音频管理器);观察者模式用于事件系统;状态模式用于角色动画状态的切换。笔试可能会让你写出“观察者模式的简单实现”,这种题目需要你真正写过事件系统,才能流畅作答。
3. 实操过程与核心环节实现:还原一道笔试题的全流程解法
3.1 典型编程题的现场思路还原
虽然每年的题目不同,但游戏开发笔试的编程题风格相对稳定。这里我以一道在多个游戏公司笔试中出现过的经典题目为例,讲解一下现场做题的完整思路。题目如下:
给定一个
N x N的网格,每个格子上的数字表示“能量消耗”。角色从左上角出发,每次只能向下或向右移动一格,求到达右下角的最小能量消耗路径,并输出最小消耗值。
这道题看起来像LeetCode的“最小路径和”,但在笔试环境下,还要考虑到越界、数据规模、是否需要输出路径等问题。我当时第一反应是用动态规划,因为状态转移方程非常清晰:
dp[i][j] = grid[i][j] + min(dp[i-1][j], dp[i][j-1])边界处理是i=0或j=0时只能从左边或上边过来。这个解法时间复杂度O(n²),空间复杂度可以优化到O(n)。如果你在笔试中只是写一个二维DP,也能通过,但如果能进一步写出空间优化版本,哪怕是伪代码,也能给面试官留下好印象。
另一个思路是Dijkstra算法,因为这个问题本质上是一个网格上的最短路径问题。不过因为每一步只能向右或向下,没有“回头路”,所以DP足够。如果题目改成可以上下左右移动,那就必须用Dijkstra或A*了。所以拿到题目先不要急着写代码,先判断状态转移是否存在环,再选算法。
我当时的代码大致是:
#include <vector> #include <algorithm> using namespace std; int minPathSum(vector<vector<int>>& grid) { int n = grid.size(); if (n == 0) return 0; int m = grid[0].size(); vector<int> dp(m, INT_MAX); for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { if (i == 0 && j == 0) dp[j] = grid[i][j]; else if (j == 0) dp[j] = dp[j] + grid[i][j]; else dp[j] = min(dp[j], dp[j-1]) + grid[i][j]; } } return dp[m-1]; }注意边界条件:第一行和第一列需要单独处理,不然dp[j-1]会越界。这个代码用一维数组滚动更新,空间复杂度从O(n²)降到O(n)。笔试中如果时间紧张,先写出二维DP保证正确性,再优化一维,也是一个稳妥的策略。
3.2 简答题的答题策略:从“会做”到“能拿分”
简答题往往比编程题更考验表达能力和知识体系。比如常见的简答题:“请简述游戏服务器同步中帧同步与状态同步的区别,并说明各自的优缺点和适用场景。”这种题没有标准答案,但想拿高分,需要结构清晰、点面结合。
我个人推荐的答题框架是:先一句话定义,再分别说明数据同步方式、客户端表现、容错性、开发复杂度,最后举例。比如状态同步中,服务器拥有最终权威,客户端发送操作指令,服务器决定结果后广播;帧同步中,所有客户端执行相同输入序列,每个客户端模拟整个游戏世界。状态同步适合MMORPG、手游等弱交互或慢节奏游戏,帧同步适合MOBA、格斗等强实时性游戏。
还有一个简答题高频点:“如何设计一个游戏背包系统?”回答时千万不要只说“用一个List存物品”。你需要提到物品的唯一ID、堆叠逻辑、格子索引、物品配置表、背包界面与数据层的解耦、排序/筛选、网络同步等。其实这就是一个模块设计题,考察的是你的工程思维。我当时回答时画了一个简单的类图(笔试是在纸上),把Item、Bag、ItemConfig、BagManager的关系整理出来,再加一句“通过事件系统通知UI刷新”,这样基本就能拿满这道题的分数。
提醒:简答题中不要只写一堆“高大上”的词汇,比如“高内聚低耦合”“事件驱动”“多线程异步”,一定要结合具体场景说明如何应用。面试官更希望看到你真实的思考过程,而不是概念堆砌。
3.3 时间分配与做题顺序:策略也能提分
一场笔试通常持续90到120分钟,题量在30到40题之间,包含选择题、填空题、简答题、编程题。如果不控制节奏,很容易出现前面选择题抠太细,后面编程题没时间写的情况。我根据经验总结了一个比较稳定的时间分配方案:
- 选择题和填空题:建议40分钟做完。单题耗时超过2分钟的先标记跳过,不要恋战。游戏公司笔试题中经常有一些“看起来眼熟但需要精确计算”的题,比如给一段C++代码让你判断输出,如果你不确定,先放着,等完成其他题再回来算。
- 简答题:建议30分钟。每道简答题控制在8分钟左右,按“定义—原理—优缺点—应用场景”的顺序组织答案。如果某道简答题完全没思路,不要空白,把你理解的相关概念写上去,也能拿一些步骤分。
- 编程题:建议30分钟。优先做最有把握的那道。笔试环境通常不支持本地调试,所以代码格式、变量命名、边界情况要一次性写对。如果编程题有多个测试用例要求,一定要在写完代码后手动跑一遍简单例子,尤其是数组越界和空数组的情况。
这个时间分配不一定适合所有人,但核心思想是:先拿基础分,再争取高分,不要因为一道难题打乱全局。我当时的失误就是在几道C++的选择题上反复纠结(比如“vector::resize和reserve的区别”),导致后面简答题只能赶着写,必然影响卷面分。
4. 常见问题与备战建议:从这场笔试看游戏开发实习准备
4.1 笔试中的“非典型”坑点盘点
游戏公司笔试和普通互联网公司的笔试,表面看都是C++/算法,但实际有很多专属的坑。第一个坑是“定点数精度”问题。有的选择题会问:在游戏服务器中,为什么不用float表示金币数量,而用int存最小单位?这其实是金融类游戏和MMORPG经济系统里很常见的陷阱,因为float在2的幂附近会出现精度丢失,导致玩家交易出现“钱越花越多”的Bug。如果只把它当成普通C++题,你可能会掉坑。
第二个坑是“渲染管线”相关题目。有些题会问“Alpha Blend”和“Alpha Test”的区别,或者“Z-Buffer”的作用。这些知识点在Unity中可能只是几个勾选项,但笔试会从原理层面考你。我当时答“Alpha Test是丢弃像素,Alpha Blend是混合像素”,并补充了Shader中clip和Blend命令的区别,应该没错。但如果你平时只做GamePlay,不看渲染,这类题基本靠蒙。建议实习前至少弄清楚:渲染管线流程(顶点着色器—光栅化—片元着色器—输出合并)、深度测试、光照模型(Lambert/Blinn-Phong)等基础概念。不需要深入看源码,但需要知道“为什么”。
第三个坑是“多人游戏同步”问题。笔试可能会以选择题形式问:“两个客户端同时攻击同一个敌人,如何确保伤害结算一致?”选项包括帧同步、状态同步、服务器权威、客户端预测。这需要你理解几种同步方案的差异,而不是单纯背概念。我的建议是找一篇“帧同步与状态同步对比”的文章认真读一遍,理解它的优缺点就好。
4.2 针对搜狐畅游这类游戏公司的备战路线
如果你现在距离笔试还有1-2个月,建议按以下路线准备:
第一,C++语言基础刷一遍。重点看:指针与引用、内存管理(栈/堆/内存泄漏)、类与继承、虚函数与多态、static/const/extern、STL容器与算法复杂度、C++11/14常用特性(智能指针、lambda、auto、右值引用)。推荐把《C++ Primer》的重点章节过一遍,加上LeetCode上用C++刷题,边用边查。如果基础薄弱,不需要看太深的模板元编程,但一定要掌握智能指针和移动语义,这是现在游戏项目的标配。
第二,数据结构和算法刷高频题。游戏开发笔试中出概率最大的题目是:数组/字符串、链表、二叉树、DFS/BFS、动态规划、贪心、优先队列、并查集。不需要碰太多计算几何、数论、线段树这类竞赛内容,但“求网格最短路径”“判断技能释放范围是否覆盖目标点”这类偏游戏场景的题要多练。建议把LeetCode标签为“数组”“动态规划”“图/搜索”的中等难度题刷50道以上,并在纸上模拟过答题过程,因为笔试现场没有办法用IDE的自动补全。
第三,游戏数学梳理一遍。你需要能默写出二维/三维向量的点乘、叉乘公式,知道四元数卷积公式和公司常见应用场景。另外,Unity中的Raycast、OverlapSphere底层其实都涉及向量和几何计算,有时间可以尝试用Unity的Debug.DrawLine画线,来可视化解法,加深理解。
第四,了解一点游戏服务器和网络。至少要能回答这几个问题:TCP与UDP的区别,如何用UDP实现可靠传输(序列号+ACK+重传);同步方案中“帧同步”和“状态同步”的优劣;AOI(兴趣区域管理)的基本思想(九宫格/十字链表/四叉树)。这些知识在笔试中不一定每题都考,但一旦考到,就是区分度很大的题。
4.3 需要提醒的“应试习惯”:如何避免无谓失分
最后聊几个很多人容易忽略的应试习惯。第一,卷面整洁。简答题手写时,字不要太小,不要用箭头乱指,按“1、2、3”分条写。面试官每天改很多试卷,一个清晰的答题结构本身就加分。第二,写代码时预留缩进和空行。笔试环境大多是在线编辑器,代码会自动整理还好;但如果是纸质笔试,代码挤在一起会严重影响可读性。第三,管理好心态。游戏公司笔试题目量偏大,出现一两道不会的题很正常。我当时在看到一道“关于网络同步的帧号同步原理”的简答题时,瞬间懵了一下,但深呼吸之后,我先把能确定的“帧同步是指所有客户端以相同输入帧进行模拟”写上去,再补充了“需要处理延迟和断线重连”的思考,虽然不完美,但至少把基础分拿到了。
注意:不要觉得笔试完了就万事大吉,很多公司笔试通过后还有一轮技术面,面试官会拿着你的笔试答卷追问。所以笔试结束后最好把不确定的题目记录下来,回去查清楚。这可能成为你面试过程中最有价值的复习资料。
5. 从一道真题到游戏开发思维:笔试之外的长期积累
5.1 笔试题目背后的工程思维
有些同学可能觉得,刷题和背知识点是在做无用功,实际开发中谁还会手写退避算法?但我的体会是,笔试最大的价值不是考察你是否记住了某个API,而是检验你是否具备“把复杂问题拆解成简单逻辑”的能力。
比如“判断一个点是否在扇形区域内”这个常见需求,拆解之后就变成:先判断点到扇形圆心的距离是否小于半径,再判断点与圆心连线的方向是否在扇形的起始角度范围内。这里要用到向量点乘、叉乘和角度范围归一化。如果笔试考了向量计算,你答不上来,那在游戏开发中遇到类似问题,你可能依然要用“试错法”去调角度参数,效率极低。游戏开发不是背API,而是需要你从数学和逻辑层面理解系统如何工作,笔试正是这种能力的试金石。
另外,我也从这场笔试里意识到,游戏开发实习生和普通后端的差异在于“实时性”和“表现力”。后端可以容忍几百毫秒的延迟,但游戏客户端每一帧只有16毫秒(60FPS)或33毫秒(30FPS)的时间预算。笔试中考复杂度、考内存、考性能优化,就是在提醒你:你的代码最终要跑在每一帧里,不能只满足“功能正确”。
5.2 长期建议:动手做一个小项目胜过刷一百道题
如果看完这篇文章,你还有2到3个月的准备时间,我强烈建议你亲手做一个小游戏Demo。不一定要完整上线,也不需要多好的美术,只要把你学到的C++、算法、数学、同步知识真正用起来。比如用Unity做一个2D Roguelike Demo,实现房间生成、A*寻路、背包系统、敌人AI状态机、存档与读取,最后发布到itch.io。做完之后,你会对游戏开发的整个链路有体感,再回头看笔试题,很多“死记硬背”的知识点自然而然就通了。
比如你在做背包系统时,会自然理解为什么需要唯一ID而不是直接用数组下标。你在做A*寻路时,会充分理解优先队列和启发式函数。你在写角色状态机时,会理解为什么状态模式比一堆if-else更好维护。这些在做Demo之前,可能只是书上的抽象概念;做完之后,它们就是你自己的经验。笔试考的从来不是“知识面有多广”,而是“你能不能把知识变成解决问题的能力”。这也是为什么有些非科班同学能够逆袭,因为他们用项目弥补了理论,用热情驱动了学习。
所以我最后的建议是:以笔试题为导向,但不要停留在刷题。每做一套题,把不懂的知识点还原到一个可运行的小Demo里验证一遍。你会发现,游戏开发笔试虽然有点“吓人”,但其实是把你推向真正游戏开发者的第一道门。