freecodecamp项目---tictactoe
来源:互联网 发布:php取数组中的最大值 编辑:程序博客网 时间:2024/06/05 15:09
一:介绍
这个项目是做一个人机对战的井字棋,一开始,完全不知道如何下手,不知道该怎么完成这个功能,最后再github上找了个项目跟着看,一看js代码,各种函数,作者也没有什么注释,看着还是头疼,但是没有办法,只有硬着头皮一个个函数的看过去,分析这个函数时做什么的,看着看着突然觉得还是挺简单的~但是大多数的时候我们都被自己吓怕了,所以不管多难,都要尝试去做,说不定就做出来了呢。当然这个作者的js代码只有三百多行,所以也不算多,只是一个小项目~
该项目在codepen上的地址:https://codepen.io/lightforme/full/JJLGwq/
二:知识点
- 1.confirm(message):该方法用于显示一个带有指定消息和OK、取消按钮的对话框;
- 2.window.location:对象用于获得当前页面的地址 (URL),window.location.reload可以将页面重新加载;
- 3.z-index:只有当position为非默认值时,该值才有效,只越大越层叠在上面,并且被覆盖的部分不能被点击到;
- 4.e.preventDefault:取消和事件相关联的默认动作;
- 5.原生js中可以直接重新设置事件方法进行覆盖,但是jQuery中不行,jQuery中需要取消事件方法需要使用.unbind()方法,不加参数是移出所有的事件方法,加参数指定移出事件方法;
- 6.在codepen中window.location对象被禁用了,所以重载页面可以使用location = location;来替代;
三:代码
html:
<!DOCTYPE html><html> <head> <meta charset="utf-8" /> <title>tictoctie game</title> <link rel="stylesheet" href="http://cdn.bootcss.com/bootstrap/3.3.5/css/bootstrap.min.css"> <link rel="stylesheet" href="css/tictoctie.css" /> </head> <body> <div class="container"> <div class="gameboard"> <ul class="grid-list"> <li class="grid grid-0"></li> <li class="grid grid-1"></li> <li class="grid grid-2"></li> <li class="grid grid-3"></li> <li class="grid grid-4"></li> <li class="grid grid-5"></li> <li class="grid grid-6"></li> <li class="grid grid-7"></li> <li class="grid grid-8"></li> </ul> </div> </div> <div class="bg"> </div> <div class="choose-panel"> <div class="choose-player"> <p>选择角色:X OR O?</p> <div class="choose-btn"> <button class="btn btn-default xobtn" id="x-btn">X</button><button class="btn btn-default xobtn" id="o-btn">O</button> </div> </div> <div class="choose-first"> <p>设置先手:</p> <div class="choose-btn"> <button class="btn btn-default firstbtn" id="computer">电脑</button><button class="btn btn-default firstbtn" id="user">玩家</button> </div> </div> </div> <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script> <script src="js/tictpctie.js"></script> </body></html>
css:
* { margin: 0px; padding: 0px;}.gameboard { width: 480px; height: 450px; margin-left: auto; margin-right: auto; margin-top: 200px; background-color: #000;}.gameboard ul { list-style: none; height: 480px; padding: 15px;}.grid { width: 32.4%; height: 30.5%; float: left; border: 1px solid #E1F5A9;}.gameboard li { cursor: pointer; color: #F9F9F9; text-align: center; line-height: 138px; font-size: 2em;}.grid-0, .grid-3, .grid-6 { border-left: none;}.grid-0, .grid-1, .grid-2 { border-top: none; }.grid-2, .grid-5, .grid-8 { border-right: none;}.grid-6, .grid-7, .grid-8 { border-bottom: none;}.bg { /*display: none;*/ position: absolute; top: 0%; left: 0%; width: 100%; height: 100%; background-color: black; z-index:1001; -moz-opacity: 0.7; opacity:.70; filter: alpha(opacity=70);}.choose-panel { position: absolute; top: 0; left: 0; bottom: 0; right: 0; width: 560px; height: 200px; margin: auto; background-color: #FFF; margin-top: 200px; z-index: 1002; border-radius: 25px;}.choose-panel p { font-size: 2em; text-align: center; padding-top: 30px;}.choose-btn { text-align: center;}.btn { margin: 5px; padding:5px;}.choose-first { display: none;}
javascript:
/*game逻辑分析 * 新建一个game的构造函数,并给该构造函数的原型对象prototype添加两个属性:init/play * * 1.点击选择角色按钮,选择角色,关闭选择角色面板,打开选择先手面板; * 2.选择先手,若是电脑先手,调用对象的play()函数; * 3.设置点击棋盘位置的点击事件,每次点击玩更新棋盘相应处的棋子,并调用play()函数,让电脑落子; * 4.play()函数逻辑:判断是否下一手即可获胜,若能找到落子位置落子 * 否则,判断下一手player是否将要获胜,若是,找到落子位置落子; * 否则,判断是否是第一手,若是,落子棋盘正中间; * 否则,收集棋盘其余未落子的位置,并随机选择落子位置落子 */$(function(){ var running = false, computerVal = -1, playerVal = 1, computer,player, copEnd = false, winResult = [[0,1,2],[3,4,5],[6,7,8],[0,3,6],[1,4,7],[2,5,8],[0,4,8],[2,4,6]], panel = [0,0,0,0,0,0,0,0,0]; //设置角色 function setPlayer(val){ computer = val === 'O' ? 'X' : 'O'; $(".choose-player").css("display","none"); $(".choose-first").css("display","block"); }; //通过类名获得位置 function getPos(val){ return val.split(" ")[1].split("-")[1]; }; //判断玩家是否胜利 function playerWin(){ for(var i = 0;i <winResult.length;i++){ var winCount = 0; for(var j = 0;j < winResult[i].length;j++){ if(panel[winResult[i][j]] == 1){ winCount++; }; }; if(winCount == 3){ return true; }; }; return false; }; //判断电脑是否胜利 function computerWin(){ for(var i = 0;i <winResult.length;i++){ var winCount = 0; for(var j = 0;j < winResult[i].length;j++){ if(panel[winResult[i][j]] == (-1)){ winCount++; }; }; if(winCount == 3){ return true; }; }; return false; }; //判断棋盘是否下满 function end(){ var count = 0; for(var i = 0;i < panel.length;i++){ if(panel[i] != 0){ count++; }; }; return (count == 9); }; //更新棋盘棋子 function updateRole(pos,val){ var targetClass = '.grid-' + pos; var who = val == 1 ? player : computer; $(targetClass).html(who); $(targetClass).unbind("click"); panel[pos] = val; if(playerWin()){ copEnd = true; if(confirm("玩家胜利,是否重开一局?")){ window.location.reload(); }; }else if(computerWin()){ copEnd = true; if(confirm("电脑胜利 ,是否重开一局?")){ window.location.reload(); }; }else if(end()){ copEnd = true; if(confirm("平局,是否重开一局?")){ window.location.reload(); }; }; }; function compOneEmp(arr){ var empCount = 0; var compCount = 0; for(var i = 0;i < arr.length;i++){ if(panel[arr[i]] == 0){ empCount++; }; if(panel[arr[i]] == (-1)){ compCount++; }; }; if(compCount == 2){ return (empCount == 1); }; }; //电脑是否可以攻击 function canAttack(){ for(var i = 0;i < winResult.length;i++){ if(compOneEmp(winResult[i])){ return true; }; }; return false; }; function findAttackPos(){ for(var i = 0;i<winResult.length;i++){ if(compOneEmp(winResult[i])){ for(var j=0;j<winResult[i].length;j++){ if(panel[winResult[i][j]] == 0){ return winResult[i][j]; }; }; }; }; return false; }; //电脑是否需要防守 function canDefend(){ for(var i = 0;i < winResult.length;i++){ if(playOneEmp(winResult[i])){ return true; }; }; return false; }; function playOneEmp(arr){ var empCount = 0; var playCount = 0; for(var i = 0;i < arr.length;i++){ if(panel[arr[i]] == 0){ empCount++; }; if(panel[arr[i]] == 1){ playCount++; }; }; if(playCount == 2){ return (empCount == 1); }; }; function findDefendPos(){ for(var i = 0;i<winResult.length;i++){ if(playOneEmp(winResult[i])){ for(var j=0;j<winResult[i].length;j++){ if(panel[winResult[i][j]] == 0){ return winResult[i][j]; }; }; }; }; return false; }; function firstStep(){ return !running; }; function specialPos(){ if(panel[4] == 0){ return true; }; return false; }; function collectEmp(){ var arr = []; for(var i = 0;i < panel.length;i++){ if(panel[i] == 0){ arr.push(i); }; }; return arr; }; //建立构造器函数 var ticToctie = function(){}; //给构造函数原型添加方法 ticToctie.prototype = { init: function(){ var self = this; $(".choose-player .btn").click(function(){ player = $(this).html(); setPlayer(player); }); $(".choose-first .btn").click(function(){ $(".bg").css('display', 'none'); $(".choose-panel").css("display","none"); var whoFirst = $(this).attr("id"); //若不是,将running置为true,防止影响后面电脑落子 if(whoFirst == 'computer'){ self.play(); }else{ running = true; }; }); $(".grid").click(function(){ var pos = getPos($(this).attr('class')); updateRole(pos,playerVal); if(!copEnd){ self.play(); }; //并取消此处可点击 }); }, play: function(){ if(canAttack()){ let pos = findAttackPos(); updateRole(pos,computerVal); return; }; if(canDefend()){ let pos = findDefendPos(); updateRole(pos,computerVal); return; }; if(firstStep()){ running = true; updateRole(4,computerVal); return; }; if(specialPos()){ updateRole(4,computerVal); return; }; var arr = collectEmp(); var pos = Math.floor(Math.random() * arr.length); updateRole(arr[pos],computerVal); return; } }; //创建一个构造函数实例 var competition = new ticToctie(); competition.init();});
如果有发现问题或者有好的建议,请在评论中指出
阅读全文
0 0
- freecodecamp项目---tictactoe
- freecodecamp项目---twitch API
- freecodecamp小项目---计时器
- freecodecamp小项目---弹幕发射器
- freecodecamp小项目---个人网站
- FreeCodeCamp日志-基础前端项目完成
- freecodecamp小项目---城市天气预报查询
- TicTacToe(TTT)
- TicTacToe棋盘
- Project: TicTacToe Game
- TicTacToe project submition
- tictactoe的wp
- Mutations|FreeCodeCamp
- freeCodeCamp:jQuery
- freeCodeCamp-jQuery
- 7. tictactoe终于调试完成
- JAVA Playing a TicTacToe game
- FreeCodeCamp(一)学习笔记
- Windows Server上DHCP的配置
- 多态 Java
- 图解HTTPS协议加密解密全过程
- Android 6.0的lowmemorykiller机制
- centos6.5之虚拟机 10连接SecureCRT 7.3
- freecodecamp项目---tictactoe
- 题目1534:数组中第K小的数字
- PAT乙级 1040. 有几个PAT(25)
- Android 自动化测试 Espresso篇:简介&基础使用
- BZOJ 2464 小明的游戏
- 页面中应用CSS的几种方式
- 我的第一个博客,致敬Java Hello Word
- Linux的chattr与lsattr命令详解
- PAT乙级 1041. 考试座位号(15)