- 首页
<!--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的使用方法基本相同, koa的ctx包含了request 和 response
| 名称 | 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适用于大型项目