Mooc--五子棋(js)小结
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)小结的更多相关文章
- 【微信小程序项目实践总结】30分钟从陌生到熟悉 web app 、native app、hybrid app比较 30分钟ES6从陌生到熟悉 【原创】浅谈内存泄露 HTML5 五子棋 - JS/Canvas 游戏 meta 详解,html5 meta 标签日常设置 C#中回滚TransactionScope的使用方法和原理
[微信小程序项目实践总结]30分钟从陌生到熟悉 前言 我们之前对小程序做了基本学习: 1. 微信小程序开发07-列表页面怎么做 2. 微信小程序开发06-一个业务页面的完成 3. 微信小程序开发05- ...
- CSS&JS小结
回顾:html: 作用:展示 文件标签: <html> <head> <title></title> </head> <body> ...
- 五子棋js
http://www.jb51.net/article/35993.htm <!DOCTYPE html> <html> <head> <meta http- ...
- HTML5 五子棋 - JS/Canvas 游戏
背景介绍 因为之前用c#的winform中的gdi+,java图形包做过五子棋,所以做这个逻辑思路也就驾轻就熟,然而最近想温故html5的canvas绘图功能(公司一般不用这些),所以做了个五子棋,当 ...
- node.js小结 2
下载node安装npm什么的就不说了 入门总结 http://www.cnblogs.com/Darren_code/archive/2011/10/31/nodejs.html 进入node_HOM ...
- 使用Webdriver执行JS小结
首先,我们使用如下方式初始化driver: WebDriver driver = new FirefoxDriver(); JavascriptExecutor jse = (JavascriptEx ...
- js小结
1,浏览器对json支持的方法: JSON.parse(jsonstr);将string转为json的对象. JSON.stringify(jsonobj);将json对象转为string. 2,js ...
- 百度地图js小结
1.获取javascript API 服务方法,首先申请密钥(ak),才可成功载入APIJS文件. 用法例如以下: <script type="text/javascript" ...
- 小程序app.js小结
小程序app.js app.js import { ApiUrl } from 'utils/apiurl.js'; import { httpReq } from 'utils/http.js'; ...
- js 小结
<script type="text/javascript"> var hotalAddJs = { makeSubmitDataHandler: function ( ...
随机推荐
- Synergy 共享键盘和鼠标
直接安装Synergy 不行的话加配置文件 ➜ ~ cat synergy.conf section: screens lab712-PC: ckboss-HP: end section: links ...
- C++如何调用C#编写的 DLL
由于C#编绎出来的DLL不是计算机所能直接识别的二进制指令码,需要CLS进行再解释,说到这,我想有些朋友应该知道C#项目需要引用C++编写的DLL时,可以直接引用DLLMPORT来实现调用,而反向的话 ...
- ajax的cache缓存的使用方法
ajax中cache缓存的使用: 问题描述: 在IE.360浏览器上提交表单后,保存后的内容不回显(依然显示空或者之前的内容). 原因: 回显内容是使用ajax的get方式的请求查询数据,ajax的c ...
- Android 开发环境安装配置手册
本文指导,如何一步步搭建Android开发平台. 1 下载软件 n JDK 1.5+ 到 http://java.sun.com/javase/downloads/index.jsp 下载 n ...
- ActiveMQ学习笔记(9)----ActiveMQ静态网络连接
1. 启动多个Broker 在win10下同一台服务器启动多个Broker, 步骤如下: 1. 复制安装目录下的conf文件夹命名为conf2 2. 修改activemq.xml中的brokerNam ...
- [arc067f]yakiniku restaurants
题意: n家饭店,m张餐票,第i家和第i+1家饭店之间的距离是$A_i$,在第i家饭店用掉第j张餐票会获得$B_{i,j}$的好感度,但是从饭店i走到饭店j会有$dis_{i,j}$的代价,可以从任意 ...
- Tomcat跨域资源共享
1.下载Jar包 cors-filter-1.7.jar java-property-utils-1.9.jar 下载完成后将Jar拷贝到tomcat下lib目录中 2.修改web.xml配置 在29 ...
- Java基础学习总结(7)——Object类
一.Object类介绍 Object类在JAVA里面是一个比较特殊的类,JAVA只支持单继承,子类只能从一个父类来继承,如果父类又是从另外一个父类继承过来,那他也只能有一个父类,父类再有父类,那也只能 ...
- 2015 Multi-University Training Contest 2 hdu 5308 I Wanna Become A 24-Point Master
I Wanna Become A 24-Point Master Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 ...
- 集团公司(嵌入ETL工具)財务报表系统解决方式
集团公司(嵌入ETL工具)財务报表系统解决方式 一.项目背景: 某集团公司是一家拥有100多家子公司的大型集团公司,旗下子公司涉及各行各业,包含:金矿.铜矿.房产.化纤等.因为子公司在业务上的差异.子 ...