Node 入门 - (七)使用koa完成小游戏

302 阅读2分钟
  • 首页
<!--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

  • 服务端

首先执行npm i koa koa-mount命令,koa为当前框架, koa-mount作为路由使用

const fs = require('fs'); //文件操作
const game = require('./game.js') //导入游戏逻辑
const express = require('express') //导入express框架
const koa = require('koa') //导入koa框架
const mount = require('koa-mount') //导入koa路由

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

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

const app = new koa(); //实例化koa

app.use(
    mount('/favicon.ico', function(ctx, next) {
        ctx.status = 200;
        return;
    })
)

const gameKoa = new koa();

app.use(
    mount('/game', gameKoa)
)

gameKoa.use(
     //获胜三次退出
    async function(ctx, next) {
        //当用户赢了三次退出
        if (playerWonCount >= 3) {
            ctx.status = 500;
            ctx.body = '我再也不和你玩了!';
            return;
        }

        await next();

        if(ctx.playerWon) {
            playerWonCount++;
        }
    }
)

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

        if (!playerAction) {
            ctx.status = 400;
            return;
        }

        if (sameCount == 9) {
            ctx.status = 500;
            ctx.body = '我再也不和你玩了!';
            return;
        }

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

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

        await next();
    }
)

gameKoa.use(
    //结果返回
    async function(ctx, next) {
        const playerAction = ctx.playerAction;
        const gameResult = game(playerAction);

        await new Promise(resolve => {
            setTimeout(() => {
                ctx.status = 200;
                //根据用户行为返回对应结果
                if (gameResult == 0) {
                    ctx.body = '平局';
                } else if (gameResult == 1) {
                    ctx.body = '你赢了!';
                    ctx.playerWon = true; //判断玩家是否获胜
                } else if (gameResult == -1) {
                    ctx.body = '你输了';
                }

                resolve()
            }, 500)
        })
    }
)

app.use(
    mount('/', function(ctx) {
        ctx.body = fs.readFileSync(__dirname + '/index.html', 'utf-8');
    })
)

app.listen(3000);

koa的使用与express的使用方法基本相同, koactx包含了requestresponse

名称 koa express
状态 ctx.status = 200 res.status(200)
返回结果 ctx.body = 'hello world' res.send('hello world')

如何选择框架

express VS Koa

  • express门槛更低, koa更强大优雅。
  • express封装更多东西,开发更快速,koa可定制型更高。

express适用于小型项目

koa适用于大型项目