1. canvas是块级元素吗??

2. css3 box-shadow属性

语法:box-shadow: h-shadow v-shadow blur spread color inset;

注释:box-shadow 向框添加一个或多个阴影。该属性是由逗号分隔的阴影列表,每个阴影由 2-4 个长度值、可选的颜色值以及可选的 inset 关键词来规定。省略长度的值是 0。

 
描述
h-shadow 必需;水平阴影的位置;允许负值。
v-shadow 必需;垂直阴影的位置;允许负值。
blur 可选;模糊距离。
spread 可选;阴影的尺寸。
color 可选;阴影的颜色。
inset 可选;将外部阴影(outset)改为内部阴影。

3.

代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>五子棋</title>
<link rel="stylesheet" type="text/css" href="css/style.css">
</head>
<body>
<canvas id="chess" width="450px" height="450px"></canvas>
<script type="text/javascript" src="js/sc.js"></script>>
</body>
</html>

CSS

canvas{
display: block;
margin: 50px auto;
box-shadow: -2px -2px 2px #EFEFEF, 5px 5px 5px #B9B9B9;
}

js部分:

1)双人轮流下棋(赢需要人为判断)

//定义二维数组存储棋盘上落子的情况
var chessBoard = [];
var me = true; //代表黑子 for(var i=0; i<15; i++){
chessBoard[i] = [];
for(var j=0; j<15; j++){
chessBoard[i][j] = 0; //代表没有落子,空的
}
} var chess = document.getElementById('chess');
var context = chess.getContext('2d'); context.strokeStyle = "#BFBFBF"; var logo = new Image();
logo.src = "images/deer.png";
//图片加载完成后调用drawImage()
logo.onload = function() {
context.drawImage(logo, 0, 0, 450, 450);
drawChessBoard(); //保证棋盘在水印图片的上层
} /*canvas为450px*450px,棋盘内边距留白15px,每行每列均为15条线,14个方格,每个方格30px*/
var drawChessBoard = function() {
for(var i=0; i<15; i++){
// 画横线
context.moveTo(15 + i*30, 15);
context.lineTo(15 + i*30, 435);
context.stroke(); //用于描边
// 画竖线
context.moveTo(15, 15 + i*30);
context.lineTo(435, 15 + i*30);
context.stroke();
}
} //i,j代表棋子在棋盘的索引,而me(Boolean)表示走的是黑棋还是白棋
var oneStep = function(i, j, me) {
context.beginPath();
//可以画扇型,圆心,半径,扇型的起止弧度和终止弧度
context.arc(15 + i*30, 15 + j*30, 13, 0, 2 * Math.PI);
context.closePath();
//6个参数
var gradient = context.createRadialGradient(15 + i*30 + 2, 15 + j*30 - 2, 13, 15 + i*30 + 2, 15 + j*30 - 2, 0); //圆心偏移右上角
if(me) {
gradient.addColorStop(0, "#0A0A0A"); //0、1代表百分比
gradient.addColorStop(1, "#636766")
} else{
gradient.addColorStop(0, "#D1D1D1");
gradient.addColorStop(1, "#F9F9F9")
}
context.fillStyle = gradient;
context.fill(); //用于填充
} chess.onclick = function(e) {
//相对与canvas左上角计算的坐标
var x = e.offsetX;
var y = e.offsetY;
var i = Math.floor(x / 30);
var j = Math.floor(y / 30);
if(chessBoard[i][j] == 0) {
oneStep(i, j, me)
if(me) {
chessBoard[i][j] = 1;
} else {
chessBoard[i][j] = 2;
}
me = !me;
} }

2)人机模式

window.onload=function(){
var me=true;
var over=false;//表示棋局有没有结束 //定义二维数组存储棋盘上落子的情况
var chessBord=[];
//初始化chessBord数组
for(var i=0; i<15;i++){
chessBord[i]=[];
for(var j=0;j<15;j++){
chessBord[i][j]=0; //代表没有落子,空的
}
} //赢法数组(三维数组)
var wins=[];
//赢法的统计数组(一维数组)
var myWin=[];
var computerWin=[];
//初始化3维赢法数组
for(var i=0; i<15; i++){
wins[i]=[];
for(var j=0; j<15; j++){
wins[i][j]=[];
}
} var count=0;//定义赢法种类的索引
//所有横线的赢法
for(var i=0;i<15;i++){
for(var j=0;j<11;j++){
//wins[0][0][0] = true;
//wins[0][1][0] = true;
//wins[0][2][0] = true;
//wins[0][3][0] = true;
//wins[0][4][0] = true; //wins[0][1][1] = true;
//wins[0][2][1] = true;
//wins[0][3][1] = true;
//wins[0][4][1] = true;
//wins[0][5][1] = true;
for(var k=0;k<5;k++){
wins[i][j+k][count]=true;
}
count++;
}
}
//所有竖线的赢法
for(var i=0;i<15;i++){
for(var j=0;j<11;j++){
for(var k=0;k<5;k++){
wins[j+k][i][count]=true;
}
count++;
}
}
//所有斜线的赢法
for(var i=0;i<11;i++){
for(var j=0;j<11;j++){
for(var k=0;k<5;k++){
wins[i+k][j+k][count]=true;
}
count++;
}
}
//所有反斜线的赢法
for(var i=0;i<11;i++){
for(var j=14;j>3;j--){
for(var k=0;k<5;k++){
wins[i+k][j-k][count]=true;
}
count++;
}
} console.log(count);
//初始化赢法的统计数组
for(var i=0; i<count; i++){
myWin[i]=0;
computerWin[i]=0;
} /**/
var chess=document.getElementById('chess');
var context=chess.getContext('2d'); context.strokeStyle="#BFBFBF";
var logo=new Image();
logo.src="data:images/deer.png";
/**/
logo.onload=function(){
context.drawImage(logo,0,0,450,450);
drawChessBoard();
/**/ }
/**/
function drawChessBoard (){
for(var i=0; i<15; i++){
context.moveTo(15+i*30,15);
context.lineTo(15+i*30,430);
context.stroke();
context.moveTo(15,15+i*30);
context.lineTo(435,15+i*30);
context.stroke();
}
} /**//*定义onesStep函数来绘制棋子*/
var oneStep=function(i,j,me){
context.beginPath();
//可以画扇型,圆心,半径,扇型的起止弧度和终止弧度
context.arc(15+i*30,15+j*30,13,0,2*Math.PI);
context.closePath(); var gradient=context.createRadialGradient(15+i*30+2,15+j*30-2,13,15+i*30+2,15+j*30-2,0);
if(me){
gradient.addColorStop(0,"#0A0A0A");
gradient.addColorStop(1,"#636766");
}
else{
gradient.addColorStop(0,"#D1D1D1");
gradient.addColorStop(1,"#F9F9F9");
}
context.fillStyle=gradient;
context.fill();//填充
} /**/
chess.onclick=function(e){
//棋局结束
if(over){
return;
}
if(!me){
return;
}
var x=e.offsetX;
var y=e.offsetY;
var i=Math.floor(x/30);
var j=Math.floor(y/30);
if(chessBord[i][j]==0){
oneStep(i,j,me);
chessBord[i][j]=1;
for(var k=0;k<count;k++){
if(wins[i][j][k]){
myWin[k]++; //向着胜利前进一步
computerWin[k]=6; //黑棋落子,白棋在k种赢法下不成立,异常数据,不可能大于5
if(myWin[k]==5){
window.alert("你赢了");
over=true;
}
}
}
if(!over){
me=!me;
computerAI();
}
}
} //定义computerAI函数
var computerAI=function(){
var myScore=[]; //计算我方得分(二维数组)
var computerScore=[]; //计算计算机得分(二维数组)
var max=0; //保存最高分数
var u=0, v=0; //保存最高分数的点的坐标 for(var i=0;i<15;i++){
myScore[i]=[];
computerScore[i]=[];
for(var j=0;j<15;j++){
myScore[i][j]=0;
computerScore[i][j]=0;
}
} for(var i=0;i<15;i++){
for(var j=0; j<15;j++){
if(chessBord[i][j]==0){
//如果i,j出现在多种赢法上,会进行累加
for(var k=0; k<count;k++){
if(wins[i][j][k]){
if(myWin[k]==1){
myScore[i][j]+=200;
} else if(myWin[k]==2){
myScore[i][j]+=400;
} else if(myWin[k]==3){
myScore[i][j]+=2000;
} else if(myWin[k]==4){
myScore[i][j]+=10000;
}
if(computerWin[k]==1){
computerScore[i][j]+=200;
} else if(computerWin[k]==2){
computerScore[i][j]+=400;
} else if(computerWin[k]==3){
computerScore[i][j]+=2000;
} else if(computerWin[k]==4){
computerScore[i][j]+=10000;
}
}
}
if(myScore[i][j]>max){
max=myScore[i][j];
u=i;
v=j;
} else if(myScore[i][j]==max){
if(computerScore[i][j]>computerScore[u][v]){
u=i;
v=j;
}
}
if(computerScore[i][j]>max){
max=computerScore[i][j];
u=i;
v=j;
} else if(computerScore[i][j]==max){
if(myScore[i][j]>myScore[u][v]){
u=i;
v=j;
}
}
}
}
}
oneStep(u,v,false);
chessBord[u][v]=2;
//
for(var k=0;k<count;k++){
if(wins[u][v][k]){
computerWin[k]++;
myWin[k]=6;
if(computerWin[k]==5){
setTimeout(function(){
window.alert("计算机赢了");},0.5);
over=true;
}
}
}
if(!over){
me=!me; }
}
}

注:此AI算法侧重于防守;

几个小问题:

1)Chrome浏览器中,在落下第五个棋子(赢),会先弹出‘赢了’的对话框,用setTimeout改进;

后续改进:

1)添加悔棋功能 

如果是要悔棋的功能的话可以用一个变量存储上次落子坐标,重新绘制背景以及坐标位置的十字;

2)添加重置功能

3)落子得分的计算

4)重复部分的封装 

  

 

  

Mooc--五子棋(js)小结的更多相关文章

  1. 【微信小程序项目实践总结】30分钟从陌生到熟悉 web app 、native app、hybrid app比较 30分钟ES6从陌生到熟悉 【原创】浅谈内存泄露 HTML5 五子棋 - JS/Canvas 游戏 meta 详解,html5 meta 标签日常设置 C#中回滚TransactionScope的使用方法和原理

    [微信小程序项目实践总结]30分钟从陌生到熟悉 前言 我们之前对小程序做了基本学习: 1. 微信小程序开发07-列表页面怎么做 2. 微信小程序开发06-一个业务页面的完成 3. 微信小程序开发05- ...

  2. CSS&JS小结

    回顾:html: 作用:展示 文件标签: <html> <head> <title></title> </head> <body> ...

  3. 五子棋js

    http://www.jb51.net/article/35993.htm <!DOCTYPE html> <html> <head> <meta http- ...

  4. HTML5 五子棋 - JS/Canvas 游戏

    背景介绍 因为之前用c#的winform中的gdi+,java图形包做过五子棋,所以做这个逻辑思路也就驾轻就熟,然而最近想温故html5的canvas绘图功能(公司一般不用这些),所以做了个五子棋,当 ...

  5. node.js小结 2

    下载node安装npm什么的就不说了 入门总结 http://www.cnblogs.com/Darren_code/archive/2011/10/31/nodejs.html 进入node_HOM ...

  6. 使用Webdriver执行JS小结

    首先,我们使用如下方式初始化driver: WebDriver driver = new FirefoxDriver(); JavascriptExecutor jse = (JavascriptEx ...

  7. js小结

    1,浏览器对json支持的方法: JSON.parse(jsonstr);将string转为json的对象. JSON.stringify(jsonobj);将json对象转为string. 2,js ...

  8. 百度地图js小结

    1.获取javascript API 服务方法,首先申请密钥(ak),才可成功载入APIJS文件. 用法例如以下: <script type="text/javascript" ...

  9. 小程序app.js小结

    小程序app.js app.js import { ApiUrl } from 'utils/apiurl.js'; import { httpReq } from 'utils/http.js'; ...

  10. js 小结

    <script type="text/javascript"> var hotalAddJs = { makeSubmitDataHandler: function ( ...

随机推荐

  1. html5+css3+javascript 自定义提示窗口

    效果图: 源码: 1.demo.jsp <%@ page contentType="text/html;charset=UTF-8" language="java& ...

  2. dialog.setCancelable与setCanceledOnTouchOutside的区别

    dialog.setCancelable(false); dialog弹出后会点击屏幕或物理返回键,dialog不消失 dialog.setCanceledOnTouchOutside(false); ...

  3. JSP学习(一)

    1.jsp脚本和注释 jsp脚本: 1)<%java代码%> ----- 内部的java代码翻译到service方法的内部 2)<%=java变量或表达式> ----- 会被翻 ...

  4. C#多播委托和事件的区别与关系

    事件是对委托的封装. 如果一个类里,你把一个委托声明为 public 了,那么外部就可以随意改变委托变量的值,包括清空委托变量等,这样的话就违背了面向对象思想的封装特性:但如果声明为 private ...

  5. 1028C:Rectangles

    You are given n rectangles on a plane with coordinates of their bottom left and upper right points. ...

  6. ZBrush笔刷属性栏简介

    在笔刷的属性栏当中,最先要了解和掌握的就是Zadd和Zsub两个按钮,当激活Zadd按钮时,我们雕刻的形态向屏幕外突出:当激活Zsub时,我们雕刻的形体就会向屏幕内凹陷.如果在激活Zadd按钮时,雕刻 ...

  7. 创建私有CA, 加密解密基础, PKI, SSL

    发现了一篇图文并茂的超棒的  加密解密, CA, PKI, SSL 的基础文章, 链接如下:https://blog.csdn.net/lifetragedy/article/details/5223 ...

  8. Base64编码字符串时数据量明显变大

    那就是当把byte[]通过Convert.ToBase64String转换成Base64编码字符串时数据量明显变大 Base64编码的思想是是采用64个基本的ASCII码字符对数据进行重新编码.它将需 ...

  9. java zyUpload 实现多文件上传

    1.html部分 <form enctype="multipart/form-data"> <label>请选择文件</label> <i ...

  10. 【CS-4476-project 6】Deep Learning

    AlexNet / VGG-F network visualized by mNeuron. Project 6: Deep LearningIntroduction to Computer Visi ...