js五子棋游戏
Posted Passer丶
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了js五子棋游戏相关的知识,希望对你有一定的参考价值。
开篇导读:最近面试遇到一个笔试题使用js和dom实现一个五子棋游戏,包含悔棋和撤销悔棋功能,对人机对战不做要求,这里分享一下我个人的实现方案
html部分(未使用原型的封装方式)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <style> .container{ width: 500px; height: 500px; border: 1px solid black; } .container button{ background: transparent; height: 50px; width: 50px; margin: 0; padding: 0; outline: none; border: 1px solid #000000; float: left; font-size: 26px; } #bank,#revokeBank{ position: fixed; width: 80px; height: 30px; top: 200px; left: 700px; } #revokeBank{ top: 240px; } </style> </head> <body> <div class="container"></div> <button id="bank">悔棋</button> <button id="revokeBank">撤销悔棋</button> </body>
//js逻辑部分 <script src="index.js"></script> </html>
JS部分(未使用原型的封装方式)
//创建一个容器 let dom = document.createDocumentFragment(); let container = document.querySelector(".container"); for(let i=1;i<=100;i++){ let btn = document.createElement("button"); btn.className = i; dom.appendChild(btn); } container.appendChild(dom); //红方选手 let redSquare = "O"; // 黑方选手 let blackSquare = "X"; //判断轮到谁下 let flag = true; // 每次落子的位置 let array = []; // 棋子的历史记录 let historys = []; // 悔棋的记录 let unhistorys = []; //选择撤销一步悔或撤销所有悔棋 let revocationType = false; //调用事件委派 delegate(container,\'click\',\'button\',function(e){ //如果此处已下棋子,则不执行方法 if(e.target.innerText) return; flag?isRedOrblack(e,redSquare):isRedOrblack(e,blackSquare); }); //判断哪方下棋 function isRedOrblack(e,square){ // 保存当前事件的对象 let nowDom = e.target; nowDom.innerText = square; // 记录在数组的对应类名序号的下标下 array[nowDom.className] = square; historys.push(nowDom.className); //将悔棋记录清空 unhistorys.length = 0; action(parseInt(nowDom.className),square); flag=!flag; } //判断胜负循环检索的方法 function decide(value,Operator,str,count){ for(i=1;i<5;i++){ if(array[value+Operator*i] === str) count++; else break; } return count; } //判断胜负 function action(value,str){ //垂直方向上的棋子 let Hcount=1; //水平方向上的棋子 let Vcount=1; //左对角方向上的棋子 let LTacr = 1; //右方向上的棋子 let RTacr = 1; //垂直方向 Hcount = decide(value,-10,str,Hcount); Hcount = decide(value,10,str,Hcount); // 水平方向 Vcount = decide(value,-1,str,Vcount); Vcount = decide(value,1,str,Vcount); //上左边对角方向 LTacr = decide(value,-11,str,LTacr); LTacr = decide(value,11,str,LTacr); //上右边对角方向 RTacr = decide(value,-9,str,RTacr); RTacr = decide(value,9,str,RTacr); (Hcount === 5 || Vcount === 5 || LTacr === 5 || RTacr === 5) && alert(str + "胜利"); }; // 悔棋 let BankDom = document.querySelector("#bank"); let containerBtn = document.querySelectorAll("button"); BankDom.onclick = function (){ // 可以悔棋多次 if(historys.length){ let number = setBank(); // 对应的button按钮元素下标需要类名值减一 containerBtn[number].innerText= ""; } } //设置悔棋的相应数据 function setBank(){ //拿到记录中的棋子下标 let number = parseInt(historys.pop()); // 记录需要悔棋棋子的下标 unhistorys.push(number); // 记录棋子值的数组中的下标对应按钮的类名的值 array[number] = ""; // 更改下棋的选手 flag = !flag; // 返回棋子位置的数组在末尾拿掉对应的值减去一就是该btn按钮的下标 return number-1; } //将悔掉的棋重新赋值 function setValue(number,square,isAction){ let target = containerBtn[number-1]; target.innerText= square; array[number] = square; isAction && action(parseInt(target.className),square); // 更改下棋的选手 flag = !flag; } //撤销悔棋 let revokeBank = document.querySelector("#revokeBank"); revokeBank.onclick = function (){ if(!unhistorys.length) return; if(revocationType){ for(let i=unhistorys.length-1;i>=0;i--){ historys.push(unhistorys[i]); flag?setValue(unhistorys[i],redSquare,false):setValue(unhistorys[i],blackSquare,false) } //将悔棋记录清空 unhistorys.length = 0; } else{ let add = unhistorys.pop(); historys.push(add); flag?setValue(add,redSquare,true):setValue(add,blackSquare,true); } }
上述JS部分调用了一个封装好了的delegate事件委派的函数,详细注释js实现事件委派
//事件委派方法 function delegate (element, eventType, selector, fn) { element.addEventListener(eventType, e => { let el = e.target; while (!el.matches(selector)) { if (element === el) { el = null; break; } el = el.parentNode; } el && fn.call(el, e, el) }); return element };
HTML部分(使用原型的封装方式)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <style> .container{ width: 500px; height: 500px; border: 1px solid black; } .container button{ background: transparent; height: 50px; width: 50px; margin: 0; padding: 0; outline: none; border: 1px solid #000000; float: left; font-size: 26px; } #bank,#revokeBank{ position: fixed; width: 80px; height: 30px; top: 200px; left: 700px; } #revokeBank{ top: 240px; } </style> </head> <body> <div class="container"></div> <button id="bank">悔棋</button> <button id="revokeBank">撤销悔棋</button> </body>
//js逻辑部分 <script src="index.js"></script> <script> //创建游戏并初始化 new Game().initGame(); </script> </html>
JS部分(使用原型的封装方式)
// 声明一个游戏函数 function Game(){ //红方选手 this.redSquare = "O"; // 黑方选手 this.blackSquare = "X"; //判断轮到谁下 this.flag = true; // 每次落子的位置 this.array = []; // 棋子的历史记录 this.historys = []; // 悔棋的记录 this.unhistorys = []; //选择撤销一步悔或撤销所有悔棋 this.revocationType = false; //获取到.container元素 this.container = document.querySelector(".container"); //保存所有button元素 let containerBtn = null; } //初始化游戏 Game.prototype.initGame = function(){ this.createBoard(); this.addEventListener(); this.needBank(); this.needRevokeBank(); } //在游戏函数原型上增加方法,创建棋盘 Game.prototype.createBoard = function(){ //创建一个容器 let dom = document.createDocumentFragment(); for(let i=1;i<=100;i++){ let btn = document.createElement("button"); btn.className = i; dom.appendChild(btn); } // 将棋盘渲染 this.container.appendChild(dom); //获到所有button元素 this.containerBtn = document.querySelectorAll("button"); } //为棋盘每个格子绑定点击事件 Game.prototype.addEventListener = function(){ //调用事件委派 this.delegate(this.container,\'click\',\'button\',(e) =>{ //如果此处已下棋子,则不执行方法 if(e.target.innerText) return; this.flag?this.isRedOrblack(e,this.redSquare):this.isRedOrblack(e,this.blackSquare); }); } //判断哪方下棋 Game.prototype.isRedOrblack = function(e,square){ // 保存当前事件的对象 let nowDom = e.target; nowDom.innerText = square; // 记录在数组的对应类名序号的下标下 this.array[nowDom.className] = square; this.historys.push(nowDom.className); //将悔棋记录清空 this.unhistorys.length = 0; this.action(parseInt(nowDom.className),square); this.flag = !this.flag; } //判断胜负循环检索的方法 Game.prototype.decide = function(value,Operator,str,count){ for(i=1;i<5;i++){ if(this.array[value+Operator*i] === str) count++; else break; } return count; } //判断胜负 Game.prototype.action = function(value,str){ //垂直方向上的棋子 let Hcount=1; //水平方向上的棋子 let Vcount=1; //左对角方向上的棋子 let LTacr = 1; //右方向上的棋子 let RTacr = 1; //垂直方向 Hcount = this.decide(value,-10,str,Hcount); Hcount = this.decide(value,10,str,Hcount); // 水平方向 Vcount = this.decide(value,-1,str,Vcount); Vcount = this.decide(value,1,str,Vcount); //上左边对角方向 LTacr = this.decide(value,-11,str,LTacr); LTacr = this.decide(value,11,str,LTacr); //上右边对角方向 RTacr = this.decide(value,-9,str,RTacr); RTacr = this.decide(value,9,str,RTacr); (Hcount === 5 || Vcount === 5 || LTacr === 5 || RTacr === 5) && alert(str + "胜利"); } // 悔棋 Game.prototype.needBank = function(){ let BankDom = document.querySelector("#bank"); //设置悔棋的相应数据 let setBank = () =>{ //拿到记录中的棋子下标 let number = parseInt(this.historys.pop()); // 记录需要悔棋棋子的下标 this.unhistorys.push(number); // 记录棋子值的数组中的下标对应按钮的类名的值 this.array[number] = ""; // 更改下棋的选手 this.flag = !this.flag; // 返回棋子位置的数组在末尾拿掉对应的值减去一就是该btn按钮的下标 return number-1; } BankDom.onclick = () =>{ if(this.historys.length){ let number = setBank(); // 对应的button按钮元素下标需要类名值减一 this.containerBtn[number].innerText= ""; } } } //撤销悔棋 Game.prototype.needRevokeBank = function(){ let revokeBank = document.querySelector("#revokeBank"); //将悔掉的棋重新赋值 function setValue(number,square,isAction){ let target = this.containerBtn[number-1]; target.innerText= square; this.array[number] = square; isAction && this.action(parseInt(target.className),square); // 更改下棋的选手 this.flag = !this.flag; } //绑定事件 revokeBank.onclick = () =>{ if(!this.unhistorys.length) return; if(this.revocationType){ for(let i=this.unhistorys.length-1;i>=0;i--){ this.historys.push(this.unhistorys[i]); this.flag?setValue.call(this,this.unhistorys[i],this.redSquare,false):setValue.call(this,this.unhistorys[i],this.blackSquare,false) } //将悔棋记录清空 this.unhistorys.length = 0; } else{ let add = this.unhistorys.pop(); this.historys.push(add); this.flag?setValue.call(this,add,this.redSquare,true):setValue.call(this,add,this.blackSquare,true); } } } //事件委派方法 Game.prototype.delegate = function(element, eventType, selector, fn) { element.addEventListener(eventType, e => { let el = e.target; while (!el.matches(selector)) { if (element === el) { el = null; break; } el = el.parentNode; } el && fn.call(el, e, el) }); return element };
如果发现这个方案中有问题,请在下方留言,欢迎随时指点
以上是关于js五子棋游戏的主要内容,如果未能解决你的问题,请参考以下文章