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. 简单封装axios api

    可以在代码逻辑中写axios请求,处理请求结果,但是随着项目越来越大,代码会很繁琐,不容易维护,所以,可以把一些在所有请求中都要处理的逻辑抽取出来,封装成api方法.比如每次请求中都要判断是否有权限, ...

  2. Java基础——String

    前言 从去年八月末开始工作一年了,有了大半年的java开发经验,自认为比在大学时期编码能力强了很多,但是基础方面概念模糊的地方感觉越来越多了 (:´д`)ゞ 所以,我准备把这些问题以及工作中遇到的问题 ...

  3. 简单Json序列化和反序列化

    序列化是什么: 序列化就是将一个对象的状态(各个属性量)保存起来,然后在适当的时候再获得.序列化分为两大部分:序列化和反序列化.序列化是这个过程的第一部分,将数据分解成字节流,以便存储在文件中或在网络 ...

  4. MyBatis 事务源码分析

    先来看看在JAVA事务的相关技术,在JAVA中有两类事务,JDBC事务和JTA事务,如果是JDBC类型的事务,则是由Connection类来控制的.如果创建一个Connection对象时,没有显示调用 ...

  5. laravel开发之-安装汉化语言包

    第一种方法: 1.输入命令:composer require "overtrue/laravel-lang:dev-master" 2.将config/app.php中命令“Ill ...

  6. 用一个div模拟textarea并实现高度自适应

    1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="U ...

  7. Phoenix 映射 HBase + Maven

    声明 本文基于 Centos6.x + CDH5.x 什么是Phoenix Phoenix的团队用了一句话概括Phoenix:"We put the SQL back in NoSQL&qu ...

  8. 下载 github 项目文件到本地方法

    下载 github 项目文件到本地方法 本篇终极,收集 3 种方法 最厉害 666 的方法 直接访问网站: 操作如下: 本地工具版下载方法 首先需要下载 git 客户端 我就不转载了,上面有客户端的使 ...

  9. ListView中Item与Checkable子类控件抢焦点问题

    Android开发中,经常需要为ListView定制Adapter,绑定各种子类控件.如果Item包含Button等Checkable的控件,那么就会发生点击Item无法响应的问题.原因是自己定义的I ...

  10. 用webpack实现前端自动化构建

    什么是自动化的前端构建流? 1. 自动补全css私有前缀,自动转化less\sass为css,自动转化es6\vue\jsx语法为js,自动打包小图片为base64以减少http请求,自动给js,cs ...