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 ( ...
随机推荐
- Gram矩阵 迁移学习 one-shot 之类
格拉姆矩阵是由内积空间中的向量两两内积而得.格拉姆矩阵在向量为随机的情况下也是协方差矩阵.每个数字都来自于一个特定滤波器在特定位置的卷积,因此每个数字代表一个特征的强度,而Gram计算的实际上是两两特 ...
- hiho 1604 - 股票价格,思维题
题目链接 题目大意 小Hi最近在关注股票,为了计算股票可能的盈利,他获取了一只股票最近N天的价格A1~AN. 在小Hi的策略中,每天可以在下列三种操作中选取一种: 1.什么也不做: 2.按照当天的价格 ...
- opengl问题
1.glCreateShader(GL_VERTEX_SHADER)失败原因: 在调用glewInit()初始化之后才能create shader;
- mybatis批量插入、批量更新和批量删除
转载 https://www.jianshu.com/p/041bec8ae6d3
- Calling convention-调用约定
In computer science, a calling convention is an implementation-level (low-level) scheme for how subr ...
- oracle和mysql的分页
如果我们是通过JDBC的方式访问数据库,那么就有必要根据数据库类型采取不同的SQL分页语句,对于MySql数据库,我们可以采用limit语句进行分页,对于Oracle数据库,我们可以采用rownum的 ...
- 题解 P3200 【[HNOI2009]有趣的数列】
说起来这是今天第三道卡特兰数了... 楼上的几篇题解好像都是直接看出这是卡特兰数,所以我就写一下为什么这道题可以用卡特兰数吧. 考察这样相邻的两项:\(a_{2i-1}\)与\(a_{2i}\),根据 ...
- securefx连接linux后文件夹中文乱码问题解决
首先在选项中设置字符编码为UTF-8 然后在全局选项中找到Securefx的配置文件 进入到该目录中,选择“Sessions”: 在“Sessions”中找到链接地址的ini文件,并用文本编辑器打开: ...
- HTTP Analyzer(实时分析HTTP/HTTPS数据流)
简述 HTTP Analyzer是一款实时分析HTTP/HTTPS数据流的工具.它可以实时捕捉HTTP/HTTPS协议数据,可以显示许多信息(包括:文件头.内容.Cookie.查询字符窜.提交的数据. ...
- 【C语言】递归函数DigitSum(n)
//写一个递归函数DigitSum(n),输入一个非负整数,返回组成它的数字之和, //比如,调用DigitSum(1729),则应该返回1+7+2+9,它的和是19 #include <std ...