Node 入门 - (六)使用express完成小游戏

212 阅读3分钟
  • 首页
<!--index.html-->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        * {
            padding: 0;
            margin: 0;
        }

        button {
            display: inline-block;
        }
    </style>
</head>
<body>
    <div id="output" style="height: 400px;width:600px;background:#eee;"></div>
    <button id="rock" style="height: 40px; width:180px">石头</button>
    <button id="scissor" style="height: 40px; width:180px">剪刀</button>
    <button id="paper" style="height: 40px; width:180px"></button>

    <script>
        const $button = {
            rock: document.getElementById('rock'),
            scissor: document.getElementById('scissor'),
            paper: document.getElementById('paper'),
        }

        const $output = document.getElementById('output');

        Object.keys($button).forEach(key => {
            $button[key].addEventListener('click', function() {
                fetch(`http://${location.host}/game?action=${key}`)
                    .then((res) => {
                        return res.text()
                    })
                    .then((text) => {
                        $output.innerHTML += text + '<br />'
                    })
            })
        })
    </script>
</body>
</html>
  • 游戏逻辑
//game.js
module.exports = function(playerAction) {
    var random = Math.random() * 3;
    
    if(random < 1) {
        var computerAction = 'rock';
    } else if (random > 2) {
        var computerAction = 'scissor';
    } else {
        var computerAction = 'paper'
    }

    if (computerAction === playerAction) {
        return 0;
    } else if (
        (computerAction === 'rock' && playerAction === 'paper') ||
        (computerAction === 'scissor' && playerAction === 'rock') ||
        (computerAction === 'paper' && playerAction === 'scissor')
    ) {
        return -1;
    } else {
        return 1;
    }
}

首页与游戏逻辑game.js中不需要任何改动,主要改变还是在index.js

  • 服务端
const fs = require('fs'); //文件操作
const game = require('./game.js') //导入游戏逻辑
const express = require('express') //导入express框架

let playerWonCount = 0; //记录用户赢的次数

let playerLastAction = null; //统计用户上次一出拳
let sameCount = 0; //统计连续出拳次数

const app = express();

app.get('/favicon.icon', function(req, res){
    res.status(200);
    return;
})

app.get(
    '/game',

    //获胜三次退出
    function(req, res, next) {
        //当用户赢了三次退出
        if (playerWonCount >= 3 || sameCount == 9) {
            res.status(500);
            res.send('我再也不和你玩了!');
            return;
        }

        next();

        if(res.playerWon) {
            playerWonCount++;
        }
    },

    //操作行为
    function(req, res, next) {
        const query = req.query; //获取请求参数
        const playerAction = query.action; //获取对应参数

        if (!playerAction) {
            res.status(400);
            res.send();
            return;
        }

        //当用户连续出同样券三次 提示用户作弊
        if (playerLastAction == playerAction) {
            sameCount++;
            if (sameCount >= 3) {
                res.status(400);
                res.send('你作弊!');
                sameCount = 9;
                return;
            }
        } else {
            sameCount = 0;
        }

        playerLastAction = playerAction; //记录上一次操作
        res.playerAction = playerAction; //挂在用户操作到res上

        next();
    },

    //结果返回
    function(req, res, next) {
        const playerAction = res.playerAction;
        const gameResult = game(playerAction);
        res.status(200);

        //根据用户行为返回对应结果
        if (gameResult == 0) {
            res.send('平局')
        } else if (gameResult == 1) {
            res.send('你赢了!')
            res.playerWon = true; //判断玩家是否获胜
        } else if (gameResult == -1) {
            res.send('你输了')
        }
    }
)

app.get('/', function(req, res){
    res.send(fs.readFileSync(__dirname + '/index.html', 'utf-8'))
})

app.listen(3000);
  1. 首先需要导入游戏逻辑以及安装express
  2. 创建express服务并监听3000端口
  3. 获取请求路由返回对应信息
  • 用户操作需求
  1. 获取用户操作行为
  2. 返回用户操作结果
  3. 统计用户获胜次数

这里对代码进行了优化,把每个功能都划分出来通过next进行后续操作

注意: 由于express对异步支持不太好所以社区推出koa框架

当在返回结果进行延时加载,由于事件机制会导致统计用户获胜时无法准确获取

//结果返回
function(req, res, next) {
    const playerAction = res.playerAction;
    const gameResult = game(playerAction);
    res.status(200);

    //根据用户行为返回对应结果
    setTimeout(() => {
        if (gameResult == 0) {
            res.send('平局')
        } else if (gameResult == 1) {
            res.send('你赢了!')
            res.playerWon = true; //判断玩家是否获胜
        } else if (gameResult == -1) {
            res.send('你输了')
        }
    }, 500)
},

//获胜三次退出
function(req, res, next) {
    //当用户赢了三次退出
    if (playerWonCount >= 3 || sameCount == 9) {
        res.status(500);
        res.send('我再也不和你玩了!');
        return;
    }

    next();

    if(res.playerWon) {
        playerWonCount++;
    }
},

上面代码中在返回结果时添加一个延时效果,统计获胜次数时无法获取res.playerWon的状态导致功能失效