likes
comments
collection
share

面试官最爱问的业务逻辑:《石头、剪刀、布》— 冯·诺依曼原理下的人机对决

作者站长头像
站长
· 阅读数 24

在腾讯的面试中给出过这样一道题:根据冯诺·依曼原理,编写出一个三局两胜制的剪刀石头布游戏

很多人一听当场就蒙了,冯·诺依曼是谁啊,冯·诺伊曼原理又是啥啊?没关系,这又没在面试呢,咱不知道还不能百度么,于是:

冯诺依曼理论要点:

1、计算机硬件设备存储器、运算器、控制器、输入设备和输出设备5部分组成。

2、存储程序思想——把计算过程描述为由许多命令按一定顺序组成的程序,然后把程序和数据一起输入计算机,计算机对已存入的程序和数据处理后,输出结果。

3、美籍匈牙利科学家冯·诺依曼最先提出程序存储的思想,并成功将其运用在计算机的设计之中,根据这一原理制造的计算机被称为冯·诺依曼结构计算机,由于他对现代计算机技术的突出贡献,因此冯·诺依曼又被称为“计算机之父”。

简单来说这道题考察的就是我们对计算机底层原理的熟知程度良好代码所必需的模块化业务逻辑中不可缺少的参数校验方面。

游戏设计思路:

输入:玩家在终端输入rockscissorspaper,通过键盘拿到玩家的输入。

处理:终端接收到数据,随机生成rockscissorspaper中的一个对抗玩家,根据游戏规则判断输赢或平局。

输出:显示游戏结果,累计玩家与电脑的胜负次数,当一方胜利次数到达2时,宣布获胜者。

完整代码:

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 (computerAction == action) {
        console.log("平局!");
        return 0;
    }else if (computerAction == "rock" && action == "scissors" || 
                computerAction == "paper" && action == "rock" || 
                computerAction == "scissors" && action == "paper") {
        console.log("你输了!");
        return 'lose';
    }else {
        console.log("你赢了!");
        return 'win';
    }
}
let winCount = 0;
let loseCount = 0;
process.stdin.on('data', (buffer) => {
    const action = buffer.toString().trim();
    const result = game(action);
    if (result === 'win') { 
        winCount++;
        if (winCount === 2) {
            console.log('你赢得了比赛!'); 
            process.exit(); 
        }
    } else if (result === 'lose') { 
        loseCount++; 
        if (loseCount === 2) { 
            console.log('电脑赢得了比赛!');
            process.exit(); 
        }
    }
})

代码说明:

首先建立一个game函数去接收参数actionaction为玩家在数组const arr=["rock", "paper", "scissors"]中选择的一个行动,同时在这个地方设置了参数校验,如果玩家输入的并非数组中的元素,则抛出错误:“用户输入错误”。

const game = (action) => {
    const arr=["rock", "paper", "scissors"];
    if (arr.indexOf(action) == -1) {
        throw new Error("用户输入错误");
    }

玩家做出了行动,相应的电脑几乎同时也做出了行动行动,此处通过生成一个随机数 random 来确定计算机选择的动作。

let random = Math.floor(Math.random()*3);
    computerAction = arr[random];
    console.log("电脑出了"+computerAction);

根据玩家与电脑做出的行动,电脑给出以下三种判断,分别是"平局!"、"你输了!"、"你赢了!",需要注意的是,题目给出的是设计一个三局两胜制的猜拳游戏,于是我们又分别设立winCountloseCount两个计时器,分别计数胜利局数和失败局数。

if (computerAction == action) {
        console.log("平局!");
        return 0;
    }else if (computerAction == "rock" && action == "scissors" || 
                computerAction == "paper" && action == "rock" || 
                computerAction == "scissors" && action == "paper") {
        console.log("你输了!");
        return -1;
    }else {
        console.log("你赢了!");
        return 1;
    }
}
let winCount = 0;
let loseCount = 0;

后端运行 js 访问输出设备stdin,当用户输入时触发回调函数,最终当任意一方的计数器达到2时,宣布获胜者,并结束整个进程。

if (result === 'win') { 
        winCount++;
        if (winCount === 2) {
            console.log('你赢得了比赛!'); 
            process.exit(); 
        }
    } else if (result === 'lose') { 
        loseCount++; 
        if (loseCount === 2) { 
            console.log('电脑赢得了比赛!');
            process.exit(); 
        }
    }

开始游戏:

游戏开始,通过终端输入我们的选择,当我们赢得两场次时,电脑宣布玩家的胜利,至此,游戏运行成功!

面试官最爱问的业务逻辑:《石头、剪刀、布》— 冯·诺依曼原理下的人机对决

总结:

正如开头所说,面试考察这种业务逻辑方面题,最重要的就是看我们对计算机底层原理的熟知程度,比如在这个游戏中,就包括了随机数生成和基本的条件判断。同时做到模块化编程,多使用函数来组织和封装游戏的逻辑。模块化设计的目的就是展现我们所写代码的可读性和可维护性。良好的模块化能够将复杂的问题分解为更小的可管理的部分。最后一点就是业务逻辑中的最基本也是最容易忽视的参数校验,用来规范代码的输入。

转载自:https://juejin.cn/post/7385832570183450662
评论
请登录