Html部分(界面):

1.五子棋棋盘由canvas完成;

2.两个按钮,样式由bootstrap完成;

3.菜单按钮对应的模态框,可以选择游戏模式:玩家自由对战,和电脑对战,还可以指定谁先执子和哪个颜色先执子;

4.游戏结束显示的模态框;

模态框由modal.js插件实现

Js部分

模式1玩家对战电脑

模式2玩家自由对战

1游戏初始化,绘制棋盘

1.1创建canvas,将canvas和span(小黄点)添加到html的div中,初始化一个二维数组defaultOptions.chessArray[i][j]使15*15的棋盘上每个点的默认值都是没有棋子。

1.2接下来绘制棋盘,棋盘的三个参数(棋盘的外边距、内边距、每格的宽度)共同决定了棋盘的总宽度和高度,通过getContext('2d')确定2d上下文对象,设定ctx.fillStyle、ctx.font和ctx.textAlign(用于调整A-O及1-15的位置),开始画竖线,总共有15根横线,使用循环,ctx.beginPath(),画竖线通过ctx.moveTo和ctx.lineTo调整每根线的起点和终点(x坐标以间隔作为步进不断递增,y不变),然后利用ctx.stroke()??,然后利用ctx.fillText填充棋盘边缘的字母(A-O),横线的画法基本相同,不同之处是x保持不变,y递增。

利用ctx.rect(起点x,起点y,宽度,高度)画大矩形框包围这些直线。

为了美观,为棋盘添加4个小黑点(它们的位置类似于黄金分割点),同样需要提前为其制定样式(ctx.fillStyle),ctx.arc(圆心x坐标, 圆心y坐标, 半径, 起始角度, 最终角度)。

1.3游戏初始化时就应该监听鼠标事件,chess_canvas.on('mousedown', function(event) {})

1.3.1如果不是玩家下棋阶段,点鼠标没有任何效果;如果游戏已经结束,点鼠标也没有任何效果 ,这时候只有点重新开始才能清空棋盘;所有监听事件时首先判断是否处于这两种情形之一,若是直接返回;

1.3.1.1玩家下棋阶段的判断:两种情况,玩家自由对战模式直接返回true,因为两个都是玩家;玩家对战电脑,只有当前要下的棋子颜色和设置的玩家执子的颜色相同时才返回true;

1.3.1.2游戏是否结束的判断:若游戏结束则隐藏小黄点;

1.3.2 如果不是上两种情况,则获取鼠标点击的位置(event.offsetX减去棋盘外边距、内边距),再将位置转换成左边(除以间隔,注意取整),准备绘制棋子,如果那个点没有棋子,则获取当前玩家或电脑要下棋的颜色getCurrentColor(),结合坐标和颜色下棋playChess(pointX, pointY, chessColor);每下一枚棋子,我们都要记录下来(白棋和黑棋分别是两个参数defaultOptions.blackLastChess = [pointX, pointY]、defaultOptions.whiteLastChess = [pointX, pointY]记录的用途??标记获胜棋子时会用);每下完一枚棋,就应该判断下棋方是否胜利;

获取要下棋的颜色:开始的第一个棋子不是黑色就是白色,分成这两种情况,分别取模交替变换颜色defaultOptions.chessCount % 2 == 0、defaultOptions.chessCount % 2 == 1;

下棋,其实就是绘制棋子(类似于前面的四个小点,不过效果不同),首先将棋子的小黄点显示,纪录棋子的数量和不同位置棋子的颜色(二维数组),棋子的半径为间隔的2/5,根据传入的坐标定位棋子,并ctx.arc画出棋子,为了更加逼真,为棋子添加径向渐变,ctx.createRadialGradient(1, 2, r,1, 2, 0)通过传入的颜色,添加颜色的渐变gradient.addColorStop(0, "#0A0A0A"); gradient.addColorStop(1, "#636766");最后为刚下的棋子添加小黄点作为标识,chessboardOptions.chessboard_container.find('span.indicator').css(..);

CSS中添加top和left值定位该span元素,span是块元素,为了使其显示更美观需要倒圆角;

判断下棋方是否胜利(该判定方法是针对玩家的判定是否胜利的方法)

连续棋子的个数作为是否胜利的评判标准,当连续棋子的个数大于或等于5个时,取得胜利,而连续棋子可能会在以自己为中心的4条线上出现(x方向,y方向,左斜,右斜),这4条线在具体分析时要以自己为中心拆成8个方向(上,下,左,右,左上,左下,右上,右下),依次判断自己相邻的棋子(判断颜色是否相同),要满足连续,所以一旦有别的颜色或者空位出现,立即break,去反向(比如刚刚是上,现在应该接着判断下)在进行判断 ,连续棋子的个数仍然累加;如果个数大于等于5个,调用hasWin(chessColor),首先结束游戏(改变变量defaultOptions.isGameStart = false;defaultOptions.isGameOver = true;隐藏小黄点),再标记获胜的棋子

要标记获胜的棋子,需要最后几个相连的棋子都找到,从最后一个棋子入手,每下一个棋子,都会在defaultOptions.blackLastChess或defaultOptions.whiteLastChess中记录下最后一个棋子的位置,这样下完棋如果游戏结束,取得胜利,我们从它入手就能找到其余几个棋子,同样,以这个棋子为中心,在4条线8个方向上去寻找相邻同色的棋子,并记录它们的位置,每个棋子的横坐标(lineChess[0][nums] = i;)和纵坐标(lineChess[1][nums] = m;)分别由二维数组记录,最后找完以后,通过循环遍历所有连续的棋子,给它们进行标记;

markChess(根据坐标和颜色画圆)

1.4五子棋AI

由于是计算机自动下棋,所以要考虑权重问题,通过算法确定棋下在哪里最好。

双重循环遍历15*15棋盘上的每个点,只要是没有放置棋子的点,都有可能作为下棋点,计算每个空闲点的权重,采用冒泡法,找到最大权重,并记录位置,然后在该位置下棋,下完棋后同样需要记录defaultOptions.blackLastChess,以便最后标识获胜棋子。下棋之后,可能出现两种情形,一是电脑获胜,根据不同的情况设定不同的权重,超过一定的权重值时电脑获胜;二是电脑没有获胜,则轮到下一个玩家;

计算下棋至(i,j)的权重,首先基于该位置给一定的权重,棋盘的中心处,权重最高,向四周扩散的位置,权重逐渐减小。同样,权重的计算也要考虑4条线,每条线上要考虑两种情况(黑棋、白棋),即要把对手下在该点处的权重也作为总权重的一部分,最终将4条线上,每条线两种情况的权重都相加得到总权重,用于冒泡阶段比较;电脑的权重和玩家的权重可以这样理解,电脑的权重可以理解为电脑进攻,计算玩家的权重可以理解为电脑的防守,进攻和防守选一个为主,这里设置进攻为主,在设置权重时进攻的权重比防守多一位数(即大10倍左右);

每个方向上权重的判定,要根据该方向连子的情况及连子两端的情况具体分析,每条线分为两个方向,每个方向判断是否有颜色相同且连续(不连续则判断两端或break)的棋子,如果有则num++,没有则判断该位置是否没有棋子,没有棋子side1 = true;反向写法相同;最后返回num,side1,side2存到一个对象中;

根据棋子的分布具体计算某点的权重,从对象中取出对应方向的num,side1,side2作为函数参数,并增加isAI作为判定电脑和玩家的bool变量。在该函数中使用switch判断num(连子的个数1,2,3,4,5),针对不同的num又有不同的计算权重, 比如num=1和num=4相比,num=4设定的权重应该更高,这里设定权重,num=1为一级(两位数),num=2和num=3为一级(三位数),num=4为一级(4位数),num=5为一级(5位数);连子两端的情况也会影响权重,分为连子两端都没有棋子(side1 && side2)和连子一端有棋子一端没有棋子(side1 || side2),两端都没有棋子的情况权重肯定更高,这种情况设定的权重比第二种的权重高一级,由于考虑了玩家在该点处的权重,还要设置玩家对应的不同情况的权重,weight = isAI ? 15 : 10;由于以进攻为主,所以玩家的权重比电脑的权重稍小,但是都处于同一级。

 

以上部分按照jQuery插件形式编写为闭包的形式

以下部分根据菜单栏选中的不同结果,获取到这些结果并传进插件中,利用defaultOptions = $.extend(defaultOptions, options);可以将这些变化的参数传递进入jQuery插件,可以满足一个插件供两种模式的共用

 

游戏结束时内容的动态显示

通过callback_victory回调函数,在游戏取得胜利后调用,根据chesscolor分为两种显示情况,即白棋赢了和黑棋赢了,每种情况还应该把玩家执子的颜色提示出来,就是判断玩家颜色

$('#showResult').find('.modal-title').text('提示【你执' + (playerColor == 1 ? "白子" : "黑子") + '】');

菜单栏的动态显示

分为几个部分的工作:

1玩家自由对战什么时候禁用,什么时候不禁用;

先行执子:对其设定监听事件$("[name='firstStart']").on("change", function(e) {})

这里默认有两种模式可选:一是玩家自由对战,二是玩家对战电脑,当选择玩家先执子时,才有可能有玩家自由对战模式,此时玩家自由对战模式可选,而先行执子是电脑,则要使玩家自由对战模式处于禁用状态;

2更新文本提示信息

要及时更新显示的文本提示,首先通过start = $("[name='firstStart']").filter(":checked").val();获取到底选中的是哪个;

3通过选中的先行执子和先行颜色,我们就能判断玩家是什么颜色,并最后动态设置传进闭包中

4判断处于哪种模式,直接判读玩家自由对战模式是最方便的,看是否勾选了即可,剩下的就是另一种情况

5监听新的游戏按钮,点击后就要重新设定模式,设定先行执子,先行颜色,将这些传进插件,开始新游戏;

分为两种模式:玩家自由对战模式、玩家对战电脑,不管是哪种模式,都要设定对应的GameMode、playerColor、blackStart值和callback_victory回调函数

6.还应该有默认的GameMode、playerColor、blackStart值和callback_victory回调函数,因为玩家可能进入游戏界面后直接开始游戏,没有通过菜单里设置这些参数,默认设置为玩家对战电脑模式,玩家先行,黑棋先行,对应的回调函数也得设定,以便胜利后显示。

五子棋项目总结 JavaScript+jQuery(插件写法)+bootstrap(模态框)的更多相关文章

  1. [转]jQuery插件写法总结以及面向对象方式写法

    本文转自:http://www.xuanfengge.com/jquery-plug-in-written-summary-and-summary-of-writing-object-oriented ...

  2. Jquery插件写法及extentd函数

    JQuery插件写法 JQuery插件又分为类扩展方法和对象扩展方法两种,类插件是定义在JQuery命令空间的全局函数,直接通过可调用,如可调用,如可调用,如.ajax():对象插件是扩展JQuery ...

  3. Bootstrap 模态框(Modal)插件

    原文链接:http://www.runoob.com/bootstrap/bootstrap-modal-plugin.html Bootstrap 模态框(Modal)插件 模态框(Modal)是覆 ...

  4. Bootstrap入门(二十三)JS插件1:模态框

    Bootstrap入门(二十三)JS插件1:模态框 1.静态实例 2.动态实例 3.模态框的尺寸和效果 4.包含表单的模态框 模态框经过了优化,更加灵活,以弹出对话框的形式出现,具有最小和最实用的功能 ...

  5. 第二百四十三节,Bootstrap模态框插件

    Bootstrap模态框插件 学习要点: 1.基本使用 2.用法说明 本节课我们主要学习一下 Bootstrap 中的模态框插件,这是一款交互式网站非常常见的 弹窗功能插件. 一.基本使用 使用模态框 ...

  6. JavaScript:bootstrap 模态框的简单应用

    最近用上了bootstrap这个强大的前端框架,有空来总结一下.这里记录下模态框的简单应用. 首先,要在页面中引入相应的js.css文件 <link href="css/bootstr ...

  7. js控制Bootstrap 模态框(Modal)插件

    js控制Bootstrap 模态框(Modal)插件 http://www.cnblogs.com/zzjeny/p/5564400.html

  8. 用jQuery写了一个模态框插件

    用jQuery写了一个模态框插件 大家觉得下面的框框好看么, 水印可以去掉(这个任务交给你们了(- o -)~zZ); "info"框 $("div").con ...

  9. 7-20 jquery遍历节点,bootstrap模态框绑定事件和解绑,mock.js,model.urlroot,id,打基础

    7-19 1:$(event.target).parents().filter("tr").find("host-name") 为什么选择不到别的host-na ...

随机推荐

  1. [javaSE] 网络编程(URL)

    获取URL对象,new出来,构造参数:String的路径 调用URL对象的getProtocal()方法,获取协议 调用URL对象的getHost()方法,获取主机 调用URL对象的getPath() ...

  2. 十二、curator recipes之双重屏障DoubleBarrier

    简介 curator实现了单个屏障barrier和双重屏障DoubleBarrier,单个屏障就是在一个进程里面设置了屏障,并等待其它进程去移除这个屏障,否则一直阻塞.双重屏障就是设置了两道屏障,两个 ...

  3. Druid SqlParser理解及使用入门

    以前的项目中很少去思考SQL解析这个事情,即使在saas系统或者分库分表的时候有涉及到也会有专门的处理方案,这些方案也对使用者隐藏了实现细节. 而最近的这个数据项目里面却频繁涉及到了对SQL的处理,原 ...

  4. 撩课-Java每天10道面试题第2天

    11.面向对象的特征有哪些方面 1.抽象: 抽象就是忽略一个主题中与当前目标无关的那些方面, 以便更充分地注意与当前目标有关的方面. 抽象并不打算了解全部问题,而只是选择其中的一部分, 暂时不用部分细 ...

  5. SpringMVC拦截器的实现单方登陆

    过滤器跟拦截器的区别 ①拦截器是基于java的反射机制的,而过滤器是基于函数回调.②拦截器不依赖与servlet容器,过滤器依赖与servlet容器.③拦截器只能对action请求起作用,而过滤器则可 ...

  6. RESTful api 设计规范

    该仓库整理了目前比较流行的 RESTful api 设计规范,为了方便讨论规范带来的问题及争议,现把该文档托管于 Github,欢迎大家补充!! Table of Contents RESTful A ...

  7. 网易游戏js-滚动支持自适应

    nie.config.copyRight.setGray(); var nieCarousel = (function ($) { var defaultOptions = { children: ' ...

  8. Postman-关于设置

    用Postman的时候由于没有中文版,所以想设置的完全符合自己的使用习惯不太容易,于是找了下关于设置的使用并转载记录一下,链接:https://www.jianshu.com/p/518ab60ebe ...

  9. 004bean作用域

    1.Singleton(单例) 2.Prototype(原型)---->每次注入.通过Spring应用上下文获取,都会重新创建    @Scope(ConfigurableBeanFactory ...

  10. 几个 h5页面效果和 自动 app 生成网站 微页

    用MAKA.易企秀.兔展就够了,MAKA和兔展用户体验好些,易企秀广告有点丑,不过模板多一些. 至于交互类工具,iH5.Mugeda.Epub360这三个里面选一个就行. -------------- ...