ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

畅游Java游戏开发笔试题拆解:考点、难点与答题技巧

畅游Java游戏开发笔试题拆解:考点、难点与答题技巧 搜狐畅游2018年校招的Java游戏开发工程师笔试题放在今天看依然有很强的参考价值。游戏公司的Java岗位笔试和普通互联网后端有着明显差异它会比纯业务后端多出一层“游戏基因”的考察比如游戏循环、AOI、状态同步这些概念同时又不会像客户端岗位那样深抠图形学和引擎源码。这篇文章我会结合当年笔试的常见出题方向、以及我后来带新人时反复强调的考点把这份Java游戏开发工程师笔试题拆开揉碎讲一遍帮正准备投游戏公司Java岗的同学理清复习重点。这篇文章适合两类人一是马上要参加游戏公司校招笔试的应届生二是想从传统Java后端转游戏服务端的开发同学。不管你是哪种只要你把下面这些考点吃透再去做畅游或者其他游戏公司的Java笔试题心里基本就有底了。1. 先说背景搜狐畅游的Java游戏开发笔试到底在考什么1.1 公司背景与岗位画像搜狐畅游是搜狐旗下的游戏公司代表作有《天龙八部》端游和手游系列后来又出了《星际战甲》国服、《俄罗斯方块环游记》等产品。这家公司的技术栈特点是既有自研引擎又有大量Java技术栈的服务端团队尤其在天龙八部IP系列产品上Java服务端承担了非常核心的业务逻辑。岗位名字叫“游戏开发工程师java”实际上这个岗位在畅游内部通常对应的是游戏服务端开发不是客户端。服务端用Java写游戏逻辑、排行榜、公会系统、跨服战、活动玩法等等这些场景和传统互联网后端最大的区别在于对实时性要求高、对内存和GC敏感、对并发模型有特殊需求。所以笔试出题的时候出题人会重点考察Java基础、并发编程、数据结构算法、网络通信以及少量游戏开发常识。当年这轮笔试是线上笔试时间大概90分钟到120分钟题型以选择题、填空题、简答题和两道左右的编程题为主。整体难度属于中等级别比纯互联网大厂的算法题要温和一些但对Java功底的考察会更细特别喜欢在一些容易混淆的知识点上做文章。1.2 试卷整体结构分析从当年参加过笔试的同学反馈来看试卷结构大致可以分成四块Java基础与集合框架占比约30%HashMap原理、ArrayList和LinkedList区别、异常处理机制、String相关、泛型、反射等。并发编程占比约20%线程创建方式、synchronized和lock区别、线程池参数、volatile关键字、CAS等。数据结构与算法占比约25%链表操作、二叉树遍历、排序算法、查找算法、简单的动态规划。计算机网络与数据库占比约15%TCP三次握手四次挥手、TCP和UDP区别、HTTP协议基础、MySQL索引和事务。游戏开发基础占比约10%游戏循环、帧率、碰撞检测、A*寻路、状态同步和帧同步的概念等。这个结构其实很有代表性。游戏公司招Java服务端最怕招进来的人只会写CRUD不懂游戏业务的特点。所以它会在基础题里穿插游戏场景的题目比如“在MMORPG游戏中玩家A和玩家B的位置同步用TCP还是UDP更合适”这种。这类题没有绝对标准答案考的是你对游戏网络模型的理解深度。2. 核心题型深度拆解每一类题背后的考察意图2.1 Java基础与集合框架HashMap是永远的主考点选择题里几乎必考HashMap。当年题目大概是“HashMap在JDK 1.8中链表转红黑树的阈值是多少为什么是8”这是个很经典的题。答案我就不卖关子了链表长度达到8且数组长度大于等于64时链表转红黑树。为什么是8这涉及到泊松分布JDK源码的注释里写了在随机哈希码的情况下链表节点数达到8的概率约为千万分之六这时候链表查询效率已经差到需要转红黑树。但实际上如果hash函数设计得好几乎不会触发这个转换。还有一道常见的题是“HashMap的默认负载因子为什么是0.75”这道题从两个角度答一是空间和时间的权衡负载因子越大空间利用率越高但冲突概率越大二是0.75这个值在数学上是一个比较均衡的选择JDK作者在注释里也引用了泊松分布的相关计算。答题的时候别只背结论要把“空间换时间”的底层逻辑说出来阅卷人会觉得你是真懂。集合框架的另一个高频考点是ArrayList和LinkedList的区别。笔试题不会只问“一个基于数组一个基于链表”这种废话而是会问“在ArrayList头部插入一个元素和在LinkedList头部插入一个元素时间复杂度分别是多少”很多人想都不想就答O(n)和O(1)这就错了。ArrayList头插要移动所有元素是O(n)没错但LinkedList头插需要找到头节点再插入虽然LinkedList本身维护了头尾节点引用所以插入确实是O(1)。但如果你在LinkedList中间插入那你还要先遍历到那个位置遍历就是O(n)。所以这道题真正的坑点是“头部插入”很多人没看清题目就答错了。String相关的题也经常出现“String、StringBuilder、StringBuffer三者的区别”这题太基础了但游戏公司特别爱考原因在于字符串拼接在游戏服务器里非常频繁比如拼日志、拼聊天消息、拼协议数据。笔试答案里要写清楚String是不可变的每次拼接都会生成新对象StringBuilder是线程不安全的可变字符串单线程下性能最好StringBuffer是线程安全的内部方法加了synchronized但性能比StringBuilder差。如果能补充一句“在游戏服务端单线程处理逻辑时优先用StringBuilder”这就是加分项。2.2 并发编程游戏服务器为什么这么看重多线程游戏服务端是典型的高并发场景尤其是MMORPG一个服务器同时在线几千人每个玩家都在不停地发消息、移动、战斗。如果不懂并发编程写出来的代码分分钟出线上事故。所以笔试里并发题的分量很重。当年常考的题包括“synchronized和ReentrantLock的区别”。这道题要答的点有synchronized是JVM层面的关键字ReentrantLock是JDK提供的类synchronized可以自动释放锁ReentrantLock必须手动释放ReentrantLock支持公平锁和非公平锁synchronized只能是非公平锁ReentrantLock支持中断响应和超时获取锁synchronized不支持JDK 1.6之后synchronized引入了偏向锁、轻量级锁、重量级锁的升级过程性能已经不输ReentrantLock了。还有一道很经典的题“volatile关键字的作用为什么不能保证原子性”volatile有两个核心作用保证可见性和禁止指令重排序。但它不保证原子性因为像i这种操作是“读-改-写”三步volatile只保证了读和写是可见的但三步之间可能被其他线程插入操作。游戏服务器里如果共享变量用volatile修饰但实际操作是累加依然会出现数据不一致。正确答案应该提到要保证原子性要么用AtomicInteger要么加锁。线程池也是必考而且会考得很细“ThreadPoolExecutor构造方法的七个参数分别是什么核心线程数怎么设置”七个参数分别是核心线程数、最大线程数、空闲线程存活时间、时间单位、阻塞队列、线程工厂、拒绝策略。核心线程数的设置其实没有标准答案看场景CPU密集型任务就设成CPU核数1IO密集型任务就设成CPU核数*2左右。游戏服务器属于混合型核心线程数往往要根据压测结果来定。另外“JDK提供了哪四种拒绝策略”答案是AbortPolicy直接抛异常、CallerRunsPolicy调用者线程执行、DiscardPolicy直接丢弃、DiscardOldestPolicy丢弃队列中最老的任务。游戏服务器里一般不会用DiscardPolicy因为丢任务等于丢玩家数据。2.3 JVM与内存管理线上OOM的排查意识从笔试开始游戏服务端对JVM的依赖比普通后端更深因为游戏服务器的内存里存了大量玩家对象、场景对象、定时任务。当年笔试考了这样一道题“Java内存区域分为哪几块哪些是线程共享的哪些是线程私有的”标准答案是堆和方法区JDK 1.8之后是元空间是线程共享的虚拟机栈、本地方法栈、程序计数器是线程私有的。但游戏公司更喜欢追问一句“游戏服务器哪些对象最容易进入老年代”这就要答到大对象直接进入老年代、长期存活的对象会晋升、以及动态年龄判断。游戏里的玩家对象如果被全局容器持有基本就是长期存活对象会一直晋升到老年代。还有一个高频题“什么时候会触发Full GC如何避免”触发条件包括老年代空间不足、元空间不足、调用System.gc()等。在游戏服务器里最怕的就是Full GC导致的全局停顿玩家会明显感觉到卡顿。所以游戏服务器往往会用G1收集器并且会通过JVM参数来控制GC暂停时间。笔试回答的时候如果能提到“游戏服务器通常设置-Xms和-Xmx相等避免运行期扩容”这就能看出你有实际的项目经验。当年还有个题很接地气“什么是内存泄漏Java中内存泄漏的场景有哪些”很多人以为Java有GC就不会内存泄漏这是错的。典型场景有静态集合类持有对象、数据库连接未关闭、内部类和外部模块的引用、重写equals和hashCode不规范导致HashMap中无法删除对象。游戏服务器常见的内存泄漏还有事件监听器注册后没有移除、定时任务没有取消、玩家下线后对象还被某些管理器引用着。2.4 数据结构与算法笔试里的“送分题”和“拉分题”编程题部分畅游常考的算法题不算太难但也不是白给的。首先链表类题目是必练的比如反转链表。这题递归和迭代两种解法都要会。迭代法用三个指针pre、cur、next每次把cur.next指向前一个节点然后三个指针整体后移直到cur为空。递归法更简洁但要注意递归深度。笔试的时候建议写迭代法不容易栈溢出。还有一道经典题“用两个栈实现队列”。这题很能考察基础数据结构能力思路是入队时把元素压入stack1出队时如果stack2为空把stack1所有元素弹出来压入stack2然后从stack2弹出栈顶。如果stack2不为空直接从stack2弹。注意出队操作的时间复杂度是均摊O(1)。排序算法里快排是必背的而且**“手写快速排序”经常作为编程题出现。快排的核心思想是分治加基准值选一个基准值把小于它的放左边大于它的放右边然后递归处理左右子数组。手写的时候要注意几个细节基准值怎么选、递归的终止条件、左右指针的移动顺序。通常选最左边的元素做基准值然后用两个指针从两端向中间扫描。还有一道容易考的是二分查找**这道题虽然简单但边界条件容易写错left和right的更新规则要反复确认。游戏公司偶尔还会考一些有趣的题比如**“实现一个简单的A*寻路算法”**。这题如果没准备过会慌但考的概率不大。如果真考到了核心思路是维护两个列表openList和closeListopenList存待考察的节点每次从openList中取出f值最小的节点f g hg是起点到当前节点的实际代价h是当前节点到终点的估计代价把它的邻居节点加入openList直到找到终点或者openList为空。用PriorityQueue做openList可以高效取最小f值节点。写不出来完整代码没关系但要能写出思路和伪代码。2.5 计算机网络基础手游通信绕不开的TCP/IP网络题在游戏公司笔试里出现频率很高因为游戏服务端本质上是一个网络服务器。最先考的就是“TCP三次握手和四次挥手的过程为什么握手三次挥手四次”三次握手是为了确认双方的发送和接收能力都没问题防止历史连接请求突然到达服务器造成资源浪费。四次挥手是因为TCP是全双工的关闭连接时双方都需要独立关闭自己的发送方向所以ACK和FIN往往是分开的。常考的还有“TCP和UDP的区别游戏里什么场景用TCP什么场景用UDP”这个题游戏公司必考而且喜欢让你结合游戏场景答。答案要点是TCP可靠、有序、面向连接UDP不可靠、无序、无连接TCP有拥塞控制和重传机制延迟高UDP快但丢包。游戏里登录、交易、聊天这些要求可靠性的场景用TCP实时战斗同步、移动同步这种对延迟敏感、可以容忍少量丢包的场景用UDP。但这只是最保守的答法真正有经验的人会补充很多游戏实际上是“TCP保证关键逻辑 UDP传输位置信息”的双通道方案或者干脆在UDP之上自己实现可靠性机制。还有一道题“HTTP和HTTPS的区别HTTPS的握手过程”。游戏客户端一般不用HTTP做实时通信但登录、支付、活动页面会走HTTP。HTTPS的核心是SSL/TLS层握手过程大概包括客户端发送支持的加密套件列表服务器返回证书和选定的加密套件客户端验证证书并生成预主密钥双方基于预主密钥计算出会话密钥之后用会话密钥对称加密通信。笔试如果时间不够答到“非对称加密交换密钥 对称加密传输数据”这一步就够拿大部分分了。2.6 游戏开发基础只有游戏公司才会考到的差异化题目这部分是游戏公司笔试题和普通互联网公司最大的区别。当年考了一道“游戏循环是什么帧率与Update频率的关系”答案要点游戏循环是游戏运行的核心机制每一帧做三件事处理输入、更新游戏状态、渲染画面。帧率是每秒渲染的帧数Update频率通常跟帧率绑定但有些游戏会采用固定时间步长的Update把逻辑更新频率和渲染帧率解耦避免帧率波动导致游戏速度不稳定。服务端也有类似的“心跳”机制常见的是1秒一个tick每tick处理一批消息和定时任务。另一道高频题“请简述帧同步和状态同步的区别。”这两个概念是游戏开发必知必会的。帧同步是所有客户端跑同样的输入靠相同的逻辑计算得到相同的输出特点是流量小、同步精度高但对逻辑一致性要求极高任何浮点数运算的差异都会导致结果分叉。状态同步是服务器负责计算和广播最终状态客户端只负责表现特点是安全性高、数据传输量大、开发效率高。MMORPG通常用状态同步MOBA和格斗游戏常用帧同步或帧同步的变种。还有个题偶尔出现“一个玩家攻击另一个玩家服务器要校验哪些东西”这是典型的游戏逻辑题答案可以从以下几个方面答攻击者与被攻击者是否在攻击范围内、技能是否在冷却中、目标是否存活、攻击方状态是否正常不能是死亡状态、是否有足够的资源蓝量/体力、是否处于无敌状态等。如果能提到“还要校验客户端传入的坐标是否合理防止瞬移外挂”这就是一个能体现游戏安全意识的加分回答。3. 实操过程与答题策略从拿到试卷到交卷的时间分配3.1 三阶段答题法笔试时间有限我建议把整场考试拆成三个阶段来分配精力。第一阶段前15分钟通读全卷标记难度。拿到卷子先别急着做题花5-15分钟把选择题、填空题、简答题、编程题全部扫一遍。标记出两类题一类是“秒杀题”看到答案就在脑子里冒出来的直接做完另一类是“拦路虎”题目长、涉及知识点多、需要大量计算的先放着。这个动作能帮你建立全局掌控感避免最后编程题没时间做而选择题又磨蹭了太久。第二阶段中间60-70分钟先攻编程题再回来做选择和填空。这个顺序很多人不理解我的理由是编程题的分值是最高的一道题顶好几道选择题而且编程题需要的是“心流状态”越往后越疲惫思路越不清晰。先把编程题写完相当于把大头分数揣到兜里后面做基础题心态会稳很多。编程题的代码不需要追求一次通过所有测试用例先把框架写对、主体逻辑写对拿到大部分分数再说。第三阶段最后15-20分钟检查边界和补充要点。编程题写完后回过去把选择题、填空题认真做一遍特别注意那些“下列说法错误的是”这种反向提问容易踩坑。简答题如果是“简述XXX和XXX的区别”这种不要只写一句“一个线程安全一个线程不安全”要分条列举把关键差异点都写出来。宁可写多了不要写少了阅卷是按点给分的。3.2 代码书写规范阅卷老师喜欢什么样的答案编程题不是只考“能不能跑通”还考代码风格。在校招笔试的线上编辑器里阅卷老师会看你的代码虽然未必会逐行读但以下几个好习惯能让你的代码被一眼看上第一变量命名要见名知意。比如链表反转题的三个指针命名成pre、cur、next比a、b、c高级太多了。第二边界条件要写清楚。数组为空、链表为空、n等于0这些都要在代码开头就做判断。第三核心逻辑给一行注释。不需要每行都注释但在关键步骤上注释一句能帮阅卷老师快速理解你的思路也是加分项。第四方法签名要优雅。如果题目要求写一个方法尽量把输入参数和返回类型定义清楚。比如实现LRU缓存写成public LRUCache(int capacity)的类结构就比写一个临时解决方案更接近生产代码风格。第五在时间复杂度上做文章。如果你的解法是O(n^2)而你知道有O(nlogn)的优化方案可以在注释里提一句表明你知道更优解。这样就算你的代码性能不够好阅卷老师也会觉得你有算法思维。另外我强烈建议在笔试前把一些高频算法模板背熟比如快排模板、二分查找模板、链表反转模板、二叉树遍历模板。不是让你死记硬背而是这些代码你练过100遍之后考场上根本不用思考就能写出来省下的时间去啃真正的难题。3.3 简答题的“分条作答”技巧简答题最容易丢分的地方是答得不够全。比如问“HashMap在JDK1.7和1.8之间的区别”你要是只答“1.8引入了红黑树”可能只能得一半分。完整的答案应该包括数据结构从数组链表变成数组链表红黑树头插法改成尾插法扩容时resize的优化hash函数简化等。这几条不是要求你一字不差而是要尽量覆盖不同的维度。我建议简答题按照“总分结构”来答先一句话给出核心答案这是总然后分条展开这是分。比如“TCP和UDP的区别”先写“TCP是面向连接的可靠传输协议UDP是无连接的不可靠传输协议”然后分条写机制上的差异连接方式、可靠性、传输效率、数据边界、适用场景。这样阅卷老师一眼就能看到答案骨架后面补再多的细节都是加分项。4. 常见问题与备考避坑实录4.1 笔试现场最容易犯的5个错误我在带人做模拟笔试的时候见过太多同学在同一个地方栽跟头。这些错误如果提前知道至少能多拿20分。第一个错误是审题不清。笔试题里经常出现“选出错误的一项”“下列说法不正确的是”这种反向提问很多同学看到熟悉的选项直接选结果选成了正确的一项。我的习惯是把“错误”“不正确”“不包括”这类词圈出来提醒自己反向作答。第二个错误是编程题只写思路不写代码。有些人觉得把思路写出来就能得分其实笔试的编程题大部分是机器测试用例验证的不写代码基本等于没分。而且在线编辑器不支持编译运行写完代码只能靠眼睛检查所以前期练习时一定要养成“盲写”的能力不依赖IDE提示手写代码一遍过。第三个错误是时间分配失衡。有些人选择题遇到不会的死磕了10分钟才放弃结果编程题只剩20分钟只能草草写几行。正确做法是选择题超过1分钟还没思路就先跳过去把会做的都做完再回头啃骨头。第四个错误是基础概念记忆模糊。比如让你手写线程池的拒绝策略你把AbortPolicy写成了CachePolicy这种低级错误最冤。备考时对于这类高频概念要用口诀或者表格反复记忆考场上不能有“好像大概也许是”这种状态。第五个错误是空白。简答题不会答或者记不清答案也绝对不能留白。哪怕你把相关的知识点写上去比如题目问“如何排查线上CPU飙高”你就算答不出jstack的具体命令也可以写“先用top命令查看进程ID再用jstack dump线程信息分析是否有死循环”。写多写错扣分但留白必然零分。4.2 这份笔试题折射出的备考路线如果你现在正准备投游戏公司的Java岗根据这份笔试题目往回倒推你的复习路线应该这样安排第一阶段1-2周Java基础查漏补缺。把集合框架源码、并发编程、JVM内存模型这三块过一遍。重点复习HashMap源码层面、线程池原理、synchronized和volatile的底层实现这部分内容吃透之后选择题和简答题的分数基本稳了。第二阶段1-2周刷数据结构和算法题。建议在LeetCode上刷Hot 100题重点覆盖链表、二叉树、动态规划、字符串处理这四类。游戏公司笔试的算法题不会变态到Hard难度但热门的Mid难度题目最好刷到融会贯通。第三阶段3-5天补充游戏开发常识。这一块是普通Java开发最容易忽略的。不需要你会写Unity或Unreal代码但要弄懂帧同步和状态同步的概念、AOI算法的大致思路、TCP/UDP在游戏场景中的应用、常见的反外挂校验思路。这些内容在面试环节也大概率会被问到。第四阶段考前1天全真模拟。找一套游戏公司往年的真题或者类似的笔试题掐着时间完整做一遍。重点不是刷了多少题而是提前适应笔试题量、时间压力和在线编辑器的手感。我见过太多人第一次用在线编辑器写代码连括号自动补全都没有直接懵了模拟几次就没这个问
返回列表