github仓库地址:https://github.com/feddiyao/Frontend-05-Template/tree/master/Week%2001
tictactoe
需求
就是一个三子棋的游戏,双方交替落子,率先先连成三子则获胜。
实现
用一个list来进行棋盘格子的布局,编写对应的show方法
<style>
.cell {
width: 100px;
height: 100px;
background-color: green;
display: inline-block;
border: solid 1px white;
vertical-align: middle;
line-height: 100px;
font-size: 50px;
text-align: center;
}
</style>
<div id = "board"></div>
<script>
let pattern = [
0, 0, 0,
0, 0, 0,
0, 0, 0
]
let color = 1;
function show() {
let board = document.getElementById("board");
board.innerHTML = "";
for (let i = 0; i < 3; i ++) {
for(let j = 0; j < 3; j ++) {
let cell = document.createElement("div");
cell.classList.add("cell");
cell.innerText =
pattern[i * 3 + j] == 2 ? "×" :
pattern[i * 3 + j] == 1 ? "o" : "";
cell.addEventListener("click", () => userMove(j, i));
board.appendChild(cell);
}
board.appendChild(document.createElement("br"))
}
}
function userMove(x, y) {
pattern[y * 3 + x] = color;
if(check(pattern,color)) {
alert(color == 2 ? "× is winner!" : "o is winner!");
}
color = 3 -color;
show();
computerMove()
}
//人机对抗
function computerMove(x, y) {
let choice = bestChoice(pattern, color);
if (choice.point)
pattern[choice.point[1] * 3 + choice.point[0]] = color;
if(check(pattern, color)) {
alert(color == 2 ? "× is winner!" : "o is winner!");
}
color = 3 - color;
show();
}
// 检查哪方赢
function check(pattern, color){
// 横向
for (let i = 0; i < 3; i ++) {
let win = true;
for(let j = 0; j < 3; j ++) {
if (pattern[i * 3 + j] != color) {
win = false;
}
}
if (win)
return true;
}
// 纵向
for (let i = 0; i < 3; i ++) {
let win = true;
for(let j = 0; j < 3; j++) {
if (pattern[j * 3 + i] != color) {
win = false;
}
}
if (win)
return true;
}
// 斜对角两条
{
let win = true;
for (let j = 0; j < 3; j ++) {
if (pattern[j * 3 + 2 -j] != color) {
win = false;
}
}
if (win)
return true;
}
// 斜对角一条
{
let win = true;
for (let j = 0; j < 3; j ++) {
if (pattern[j * 3 + j] != color) {
win = false;
}
}
if (win)
return true;
}
return false;
}
// willwin中避免破坏当前棋盘进行克隆
function clone(pattern) {
return JSON.parse(JSON.stringify(pattern));
}
function willWin(pattern, color) {
for (let i = 0; i < 3; i ++) {
for (let j = 0; j < 3; j ++) {
if (pattern[i * 3 + j])
continue;
let tmp = clone(pattern);
tmp[i * 3 + j] = color;
if (check(tmp, color)) {
return [j, i];
}
}
}
return null;
}
//当前最好策略
function bestChoice(pattern, color) {
let p;
if (p = willWin(pattern, color)) {
return {
point: p,
result: 1
}
}
let result = -2;
let point = null;
outer: for (let i = 0; i < 3; i ++) {
for (let j = 0; j < 3; j ++) {
if (pattern[i * 3 + j])
continue;
let tmp = clone(pattern);
tmp[i * 3 + j] = color;
let r = bestChoice(tmp, 3 - color).result;
if (- r > result) {
result = - r;
point = [j, i];
}
if(result == 1)
break outer;
}
}
return {
point: point,
result: point ? result : 0
}
}
show(pattern);
console.log(bestChoice(pattern, color))
</script>
红绿灯
需求
红绿灯问题主要是是一个异步的问题,需要实现绿灯亮10秒,黄灯2秒,红灯5秒的顺序无限循环。
ui设计
<style>
div {
background-color: grey;
display: inline-block;
margin: 30px;
width: 100px;
height: 100px;
border-radius: 50px;
}
.green.light {
background-color: green;
}
.yellow.light {
background-color: yellow;
}
.red.light {
background-color: red;
}
</style>
<div class="green"></div>
<div class="yellow"></div>
<div class="red"></div>
<button id="next">next</button>
<script>
function green() {
var lights = document.getElementsByTagName("div");
for (var i = 0; i < 3; i ++) {
lights[i].classList.remove("light")
document.getElementsByClassName("green")[0].classList.add("light")
}
}
function red() {
var lights = document.getElementsByTagName("div");
for (var i = 0; i < 3; i ++) {
lights[i].classList.remove("light")
document.getElementsByClassName("red")[0].classList.add("light")
}
}
function yellow() {
var lights = document.getElementsByTagName("div");
for (var i = 0; i < 3; i ++) {
lights[i].classList.remove("light")
document.getElementsByClassName("yellow")[0].classList.add("light")
}
}
</script>
功能实现
我们的实现方式有三种:
- callback
- Promise
- async/await
首先最基础的链式执行代码:
//链式执行
function go(){
green()
setTimeout(function(){
yellow()
setTimeout(function(){
red()
setTimeout(function(){
go()
}, 5000)
}, 2000)
}, 10000)
}
然后是promise执行:
// promise执行
function sleep(t) {
return new Promise((resolve, reject) => {
setTimeout(resolve, t)
})
}
function go() {
green()
sleep(1000).then(() => {
yellow()
return sleep(200);
}).then(() => {
red()
return sleep(500)
}).then(() => {
go()
})
}
async 自动执行
//async 自动执行
function sleep(t) {
return new Promise((resolve, reject) => {
setTimeout(resolve, t)
})
}
async function go(){
while(true) {
green()
await sleep(1000)
yellow()
await sleep(200)
red()
await sleep(500)
}
}
async 手动执行
// async执行 手动
function happen(element, eventName) {
return new Promise((resolve, reject) => {
element.addEventListener(eventName, resolve, {once: true})
})
}
async function go(){
while(true) {
green()
await happen(document.getElementById("next"), "click");
yellow()
await happen(document.getElementById("next"), "click");
red()
await happen(document.getElementById("next"), "click");
}
}
generator执行
// generator执行
function* go(){
while(true) {
green();
yield sleep(1000);
yellow();
yield sleep(200);
red();
yield sleep(500);
}
}
function run(iterator) {
let {value, done} = iterator.next();
if (done) {
return;
}
if (value instanceof Promise)
value.then(() => {
run(iterator)
})
}
function co(generator) {
return function() {
return run(generator());
}
}
go = co(go);