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 ( ...
随机推荐
- linux文件上传下载
上传本地文件到服务器:scp 文件名 账号@服务器IP:文件路径eg:scp test.txt root@192.168.0.123:/tmp/服务器文件下载到本地:scp 账号@服务器IP:文件 本 ...
- Redis-1-安装
Redis-1-安装 标签(空格分隔): linux,redis 下载 cd /usr/local/src/ wget http://download.redis.io/releases/redis- ...
- Hadoop编译源码
Hadoop编译源码 克隆一个虚拟机 然后一步一步安装就行 安装所需:链接: https://pan.baidu.com/s/1jIZlQmi 密码: gggv 5.1 前期准备工作 1)CentOS ...
- sql server 更新满足条件的某一条记录
上图数据:SNum为”18004XXXXX000001K2GW 4000 L1C“,OffLineStation为“OP1010”的有两条数据,当where条件中为上述两者时会同时更新这两条数据,并不 ...
- Vue.js Ajax动态参数与列表显示
一.动态参数显示 1.引入js <script type="text/javascript" src="/js/vue.min.js"></s ...
- 【AnjularJS系列2 】— 表单控件功能相关指令
第二篇,表单控件功能相关指令. ng-checked控制radio和checkbox的选中状态 ng-selected控制下拉框的选中状态 ng-disabled控制失效状态 ng-multiple控 ...
- 设置div内的内容不能被选中
通过简单的css设置页面的文字无法被选定. <div class="select">我不能被选中复制</div> .select{ -webkit-user ...
- python编写登录与注册
#编写简单的注册与登陆模块 #使用死循环来检测 while True: #如果条件为真,则一直循环 sum=3 #定义密码输入的次数 username = input("请输入用户名:&qu ...
- linux 空间不够了 修改 /boot
1> 查看空间多少:df -h2> 查看当期内核: uname -r3> 查找内核 rpm -qa | grep kernel4> 删除多余的内核 yum remo ...
- python学习(二):基本数据类型:整型,字符型
整型: type():显示数据类型 # 整型,int # python3里,不管数字有多大,都是int类型 # python2里,有大小区分,长整型:long int a = " print ...