腾讯面试官:请使用冯诺依曼原理,编写石头剪刀布游戏
前言
在技术驱动的今天,腾讯以其前沿的科技实力吸引着全球的顶尖人才。而在其严格的面试流程中,一道经典而富有深意的题目经常被提及——如何依据冯·诺依曼原理设计并实现一个“石头剪刀布”游戏。此题目的精髓在于,它不仅考验面试者的编程技能,更要求他们对计算机科学的基础——冯·诺依曼体系结构有深刻的理解和应用能力。
正文
题目
请使用冯诺依曼原理,编写石头剪刀布的游戏(三局两胜制)。
解答
冯诺依曼原理
什么是冯诺依曼原理?
冯·诺依曼原理,作为现代计算机体系的基石,主要包含以下几个核心要素:
- 存储程序:程序指令和数据预先存入存储器中,计算机按序执行。
- 二进制表示:信息和指令均以二进制形式编码。
- 中央处理器:包含运算器和控制器,负责执行指令和控制程序流程。
- 输入输出:与外部世界交换信息。
设计思路
基于上述原理,设计一款“石头剪刀布”游戏,我们首先需将游戏规则、用户输入、计算逻辑以及结果显示等要素映射到冯·诺依曼架构的各个组成部分。
- 存储程序与数据:游戏规则:石头胜剪刀,剪刀胜布,布胜石头。用户的选择以及游戏过程中的得分也在运行时动态存储。
- 运算器:负责处理游戏逻辑,如比较用户输入与计算机随机生成的选择,根据规则判断胜负,并更新分数。
- 控制器:根据程序指令序列,控制游戏流程,包括接收用户输入、调用运算逻辑、判断游戏是否结束以及输出结果。
- 输入输出:玩家通过键盘输入选择,程序接收这些输入并反馈游戏结果,如胜利、失败或平局。
编码前的tips
在写代码之前要注意的要点:
- 要多写注释。
- 模块化设计,将不同功能进行封装。
- 代码风格。如:驼峰命名等。
代码实现
-
首先需要实现获取用户的输入。
process.stdin.on('data', (buffer) => { const action = buffer.toString().trim(); })
process.stdin是 Node.js 中代表进程标准输入的对象。这其实是一个事件监听器,当有数据输入时,就会触发回调函数,用action常量接收用户的输入。
你问buffer是什么?那我们输出一下吧。
buffer是一个二进制数据。
-
进行模块化设计,将实现电脑随机猜拳并得出猜拳结果的功能进行封装(不要忘记注释)。
-
对用户输入的内容进行校验,如果内容不规范就报错。
/* *@func 根据用户输入的参数,输出结果 *@return win(1) or lose(-1) or draw(0) */ const game = (action) => { const arr = ['rock', 'paper', 'scissors']; //输入校验 if (arr.indexOf(action) == -1) { throw new Error('用户输入错误'); } }
-
通过执行
Math.floor(Math.random() * 3)
可以随机生成0、1、2三数之一。通过数组arr和随机下标,这样就实现了电脑的选择功能。/* *@func 根据用户输入的参数,输出结果 *@return win(1) or lose(-1) or draw(0) */ const game = (action) => { const arr = ['rock', 'paper', 'scissors']; //输入校验 if (arr.indexOf(action) == -1) { throw new Error('用户输入错误'); } let computerAction; let random = Math.floor(Math.random() * 3); computerAction = arr[random]; console.log('电脑出了' + computerAction); }
-
对用户和电脑的输出进行判断,并且返回猜拳结果。
/* *@func 根据用户输入的参数,输出结果 *@return win(1) or lose(-1) or draw(0) */ const game = (action) => { const arr = ['rock', 'paper', 'scissors']; //输入校验 if (arr.indexOf(action) == -1) { throw new Error('用户输入错误'); } let computerAction; let random = Math.floor(Math.random() * 3); computerAction = arr[random]; console.log('电脑出了' + computerAction); if (action == computerAction) { //平局 return 0; } else if ((computerAction == 'rock' && action == 'scissors') || (computerAction == 'scissors' && action == 'paper') || (computerAction == 'paper' && action == 'rock')) { console.log('电脑赢'); return -1; } else { console.log('用户赢'); return 1; } }
-
-
实现三局两胜制,对比得分选取出获胜者并且退出游戏。
let userWinCount = 0;//用户分数 let computerWinCount = 0;//电脑分数 process.stdin.on('data', (buffer) => { const action = buffer.toString().trim(); const result = game(action); if (result == 1) { userWinCount++; if (userWinCount == 3) { console.log('恭喜你,你获胜了'); process.exit(); } } else if (result == -1) { computerWinCount++; if (computerWinCount == 3) { console.log('电脑获胜了,你输了'); process.exit(); } } else { console.log('平局,再来一局'); } })
到这里,整体代码就完成了。
完整代码:
let userWinCount = 0;//用户分数
let computerWinCount = 0;//电脑分数
process.stdin.on('data', (buffer) => {
const action = buffer.toString().trim();
const result = game(action);
if (result == 1) {
userWinCount++;
if (userWinCount == 3) {
console.log('恭喜你,你获胜了');
process.exit();
}
}
else if (result == -1) {
computerWinCount++;
if (computerWinCount == 3) {
console.log('电脑获胜了,你输了');
process.exit();
}
}
else {
console.log('平局,再来一局');
}
})
/*
*@func 根据用户输入的参数,输出结果
*@return win(1) or lose(-1) or draw(0)
*/
const game = (action) => {
const arr = ['rock', 'paper', 'scissors'];
//输入校验
if (arr.indexOf(action) == -1) {
throw new Error('用户输入错误')
}
let computerAction;
let random = Math.floor(Math.random() * 3);
computerAction = arr[random];
console.log('电脑出了' + computerAction);
if (action == computerAction) {
//平局
return 0;
}
else if ((computerAction == 'rock' && action == 'scissors') || (computerAction == 'scissors' && action == 'paper') || (computerAction == 'paper' && action == 'rock')) {
console.log('电脑赢');
return -1;
}
else {
console.log('用户赢');
return 1;
}
}
检验结果
让我们开启人机大战吧。
eg1:
真是一场酣畅淋漓的对决呀!!!
eg2:
这都能输!!!!
小结
通过这一面试题,腾讯旨在寻找那些能在平凡中见真章的程序员——他们不仅能够迅速准确地实现功能,还能在细节中展现技术深度与广度。记住,面试不仅是技术的较量,更是心态与应变能力的考验。将每一次挑战视为成长的契机,无论结果如何,都将是你技术生涯中宝贵的一页。
转载自:https://juejin.cn/post/7368692841299066934