废话开篇:简单用 canvas 绘制跟触点跟踪来实现一个 js版单机五子棋 demo,这里没有什么特别高级的东西,内容纯属娱乐。
步骤一、先画一个棋盘
这里直接上一段简单 html 代码,内容就是一个 canvas 标签。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<script src="wz.js" type="text/javascript" charset="utf-8"></script>
<style type="text/css">
#canvas{
background-color: aliceblue;
margin-top: 50px;
margin-left: 50px;
}
</style>
<body>
<canvas id="canvas" width="606" height="606"></canvas>
</body>
<script>
window.$wzObj.initMap()
</script>
</html>
步骤二、在 canvas 标签内画好棋盘
在 js 文件里声明了一个 wzObj 对象,把所有的任务执行都绑定在这个 wzObj 对象上面。
为 wzObj 对象添加一个 initMap 的方法,这里就进行了 3 步:
1、获取 canvas 画布。
2、计算网格线定位参数。
3、绘制网格横线、竖线。
wzObj.initMap = function(){
//步骤一 拿到画板
var canvas = document.getElementById('canvas')
//添加画板鼠标点击 point
canvas.addEventListener('click', function(e) {
var x = event.pageX - 50
var y = event.pageY - 50
//绘制棋子
wzObj.draw(x,y);
})
//步骤二
var mapWidth = canvas.width - 1;
var lineNums = 11;
var lineWidth = 1;
var sap = mapWidth / lineNums;
this.sap = sap;
// 拿到上下文
var context = canvas.getContext('2d');
// 设置线条的颜色
context.strokeStyle = '#000';
// 设置线条的宽度
context.lineWidth = lineWidth;
//步骤三
for(var i = 1;i < lineNums;i++){
//绘制竖线
//开始绘制路径
context.beginPath();
// 起点
context.moveTo(i * sap + 0.5, sap);
// 终点
context.lineTo(i * sap + 0.5, mapWidth - sap);
//填充颜色
context.strokeStyle="#000";
//进行填充
context.stroke();
//关闭绘制路径
context.closePath();
//绘制横线
context.beginPath();
// 起点
context.moveTo(sap,i * sap + 0.5);
// 终点
context.lineTo(mapWidth - sap,i * sap + 0.5);
context.strokeStyle="#000";
context.stroke();
context.closePath();
}
}
步骤三、判断画布鼠标触点位置,进行绘制黑白棋子
初始化棋盘记录数据:
recordArr:记录当前棋盘所有位置落子情况 0:无落子,1:黑子,2:白子。初始化全部重置为 0.
black:记录下一手落子颜色。true:黑子,false:白子。
var wzObj = {}
wzObj.recordArr = [];
wzObj.black = true;
//初始化全部统计为 0
for(var i = 0;i < 10;i++){
var arr = [];
for(var j = 0;j < 10;j++){
arr.push(0);
}
wzObj.recordArr.push(arr);
}
进行触点计算及绘制
wzObj.draw = function(x,y){
//不在棋盘内,不进行绘制,x、y参数值为当前鼠标 point 的 x值及y值
if(x < 55 || y < 55 || x > 552 || y > 552){
return;
}
//棋盘x轴的偏移量
var i = x / this.sap;
//Math.round 把一个数字舍入为最接近的整数,这里并没有四舍五入,只招附近的整数点
i = Math.round(i);
//棋盘y轴偏移量
var j = y / this.sap;
j = Math.round(j);
//如果当前计算的棋盘位置已落子,不进行绘制
if(this.haveRecordAtPoint(i-1,j-1)){
return;
}
//进行绘制
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
//判断当前绘制的棋子的颜色
context.fillStyle = this.black ? "#000" : "#FFF";
context.beginPath();
//绘制圆形。
context.arc(this.sap * i, this.sap * j, 15, 0, 2*Math.PI, true);
context.closePath();
context.stroke();
//进行内部填充
context.fill();
console.log('x='+x + 'y='+y);
console.log('i='+i + 'j='+j);
//记录当前落子点
this.record(i-1,j-1);
//判断是否有5子链接,进行胜负判断。
if(this.judgeIsComplete(i-1,j-1)){
var that = this;
setTimeout(function(){
var name = that.black ? "黑子" : "白子";
alert(name + "赢了");
},500);
} else {
//没有判断出输赢,棋子落子颜色变更
this.black = !this.black;
}
}
判断是否已落子
//判断是否已落子
wzObj.haveRecordAtPoint = function(i,j){
var arrX = this.recordArr[i];
var y = arrX[j];
return (y != 0);
}
记录落子
//记录落子
wzObj.record = function(i,j){
var arrX = this.recordArr[i];
var y = arrX[j];
arrX[j] = (this.black == true) ? 1 : 2;
}
步骤四、根据当前结束的落子位置进行棋盘上同颜色棋子整体输赢判断
通过当前落子的位置,从横向、纵向、左上到右下、右上到左下的顺序进行判断周围是否有 5 子链接
//计算是否有链接5子部分
wzObj.judgeIsComplete = function(i,j){
var bj = this.black ? 1 : 2;
var sameCount = 0;
//计算横向
//向左
var arrX = this.recordArr[i];
for(var x = j;x >= 0;x--){
var val = arrX[x];
if(val == bj){
sameCount++;
} else {
break;
}
}
//向右
for(var x = j+1;x <= arrX.length;x++){
var val = arrX[x];
if(val == bj){
sameCount++;
} else {
break;
}
}
//从左到右,检测,数量 >= 5 输赢判断成立
if(sameCount >= 5){
return true;
}
//计算纵向
//向上
sameCount = 0;
for(var y = i;y >= 0;y--){
var val = this.recordArr[y][j];
if(val == bj){
sameCount++;
} else {
break;
}
}
//向下
for(var y = i + 1;y < this.recordArr.length;y++){
var val = this.recordArr[y][j];
if(val == bj){
sameCount++;
} else {
break;
}
}
//从上到下,检测,数量 >= 5 输赢判断成立
if(sameCount >= 5){
return true;
}
//左上-右下
sameCount = 0;
var y = i;
for(var x = j;x >= 0;x--){
if(y >= 0){
var val = this.recordArr[y][x];
if(val == bj){
sameCount++;
} else {
break;
}
}
y-=1;
}
y = i + 1;
for(var x = j + 1;x < this.recordArr.length;x++){
if(y <= this.recordArr.length){
var val = this.recordArr[y][x];
if(val == bj){
sameCount++;
} else {
break;
}
}
y+=1;
}
//从左上到右下,检测,数量 >= 5 输赢判断成立
if(sameCount >= 5){
return true;
}
//右上-左下
sameCount = 0;
y = i;
for(var x = j;x < this.recordArr.length;x++){
if(y >= 0){
var val = this.recordArr[y][x];
if(val == bj){
sameCount++;
} else {
break;
}
}
y-=1;
}
y = i + 1;
for(var x = j - 1;x >= 0;x--){
if(y <= this.recordArr.length){
var val = this.recordArr[y][x];
if(val == bj){
sameCount++;
} else {
break;
}
}
y+=1;
}
//从右上到左下,检测,数量 >= 5 输赢判断成立
if(sameCount >= 5){
return true;
}
return false;
}
好了,极其简单的五子棋 demo 就写好了,里面没啥技术高的内容,纯属娱乐,代码拙劣,大神勿笑。