懂冯诺依曼原理的人才配玩石头剪刀布(bushi)

297 阅读3分钟

前言

腾讯有一道这样的面试题:“请使用冯诺依曼原理,编写石头剪刀布的游戏”。不少友友看到都蒙了,偶买噶408基础不好算是碰上送命题惹。那么接下来,就由小编来带你一探究竟,你就会发现,其实也是不过如此啦~

冯诺依曼原理

经典的冯·诺依曼架构的计算机由五大部件组成:运算器、控制器、存储器、输入设备和输出设备。基于这一结构编写一个简单的石头剪刀布游戏逻辑,可以理解为在计算机程序中实现,而直接应用冯·诺依曼原理来编写游戏逻辑本身并不直观,因为原理更多是指硬件架构层面,但我们可以遵循这些基本原理来构思程序的流程

思路

用户输入石头或剪子或布,程序再随机输出石头或剪子或布,条件判断用户输赢,赢三次则结束。结合冯诺依曼原理,我们要思考:

  1. 如何通过输入设备——键盘 拿到用户的输入?
  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) // [0,3)向下取整
    computerAction = arr[random];
    console.log('电脑出了' + computerAction);
    if (computerAction == action) {
        console.log('平局')
        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 winCount = 0;

process.stdin.on('data', (buffer) => {   // 监听标准输入流
    const action = buffer.toString().trim(); // trim() 去除首尾空格
    const result = game(action)
    if(result == 1){
        winCount++;
        if(winCount == 3){
            console.log('不玩了');
            process.exit(0); // 退出进程
        }
    }
})  

运行结果

image.png

image.png

详细解释

process.stdin.on('data', (buffer) => { ... }):process是后端的进程对象,process.stdin是标准输入流,.on监听事件。每当有数据到达时,回调函数接收一个参数 buffer,它是一个包含接收到的数据的缓冲区对象

buffer.toString().trim():将输入流接收到的数据(二进制流)转换为字符串,并 .trim() 方法去除字符串首尾的空白字符,确保不会因为换行符影响对输入字符串后续的条件判断

Math.floor(Math.random() * 3)Math.random()产生随机数[0,1),Math.floor()对浮点数向下取整。这样才能随机获取0, 1, 2三个数作为数组下标

总结

整个程序被划分成了两个子函数,一个“process.stdin.on('data', (buffer) => { ... })” 用于控制进程的开始和结束,并监听输入流,一个“const game = (action) => {...}” 用于接收用户的输入,直接输出出拳结果。 通过对这个简单小游戏的探索,我们可以知道:

  1. process是后端的进程对象,进程是资源分配的最小单元,运行任何一个程序都要有一个依赖冯诺依曼计算设备的process对象
  2. 良好的编程无法脱离计算机的底层原理,存储和通信的底层是二进制
  3. 良好的代码是模块化的,本例中独立的出拳业务就被封装成了一个函数
  4. 有输入,就要做输入校验,防止用户的错误操作破坏我们的进程

关注我,让我们努力学好408,以后一起玩更高级的游戏嘿嘿~