突然想利用canvas自己写个简单的五子棋来玩一玩:
首先新建一个html文件,如下:
123
然后创建一个index.js文件,直接放在同一目录下即可。
首先,获取我们在html中创建的canvas:
var canvas = document.querySelector('#qipan');
var ctx = canvas.getContext('2d');
紧接着,第一步就是要绘制棋盘了:
边缘的棋子有一半会在棋盘之外,所以我们要预留空间,因此可以设置一个偏移量,
var pianyiliang = 20;
五子棋的棋盘为15*15
function drawGrid(){
ctx.fillStyle = '#cc9966';
ctx.fillRect(pianyiliang,pianyiliang,560,560);
ctx.fillStyle='#000000';
ctx.beginPath();
//划竖线
for(var i=0;i<15;i++){
ctx.moveTo(i*40+pianyiliang,0+pianyiliang);
ctx.lineTo(i*40+pianyiliang,560+pianyiliang);
ctx.stroke();
}
//横线
for(var i=0;i<15;i++){
ctx.moveTo(0+pianyiliang,i*40+pianyiliang);
ctx.lineTo(560+pianyiliang,i*40+pianyiliang);
ctx.stroke();
}
ctx.closePath();
}
接下来就是绘制棋子:
总所周知,五子棋的棋子形状是圆的,颜色有黑白两种
首先想到的是 用ctx.arc()来绘制,然后用ctx.fill()做颜色填充,每填充一次就改变一下fillstyle,实测时出现了问题,详细问题会另说,这里不纠结它。
直接通过在函数内创建对象,然后函数返回对象来解决,在创建一个qizi数组,用于收集每次点击时所产生的棋子对象,再利用外界判单条件来确定当次点击应该走的是黑子还是白子,传不同的参数就可以实现创建不同特征的对象,这样就可以避免用在fill()填充时把之前走的棋子也填充掉了。
function particle(colora,colorg,colorb,r,x,y,alpha){
var obj = {
ra:colora,
rb:colorb,
rg:colorg,
r:r,
x:x,
y:y,
alpha:alpha,
draw:function(ctx){
//rgba(r,g,b,a)
ctx.fillStyle = 'rgba(' + this.ra + ',' + this.rg + ',' + this.rb + ',' +
this.alpha + ')';
ctx.beginPath();
ctx.arc(this.x,this.y,this.r,0,360,false);
ctx.fill();
ctx.closePath();
},
}
return obj;
}
通过参数rgb就可以对颜色进行控制,引入alpha是为了让白色棋子不透明,这样就可以遮住棋盘的线了。
接下来,便是clickme函数了:
我们在外部定义num = 0 来表示棋盘状态,在外部定义二维数组来模拟棋盘。
每一项,若无子,值为0,若有黑子,值为1,若有白子,值为2;
function clickme(){
var e = event;
var lie = (e.clientY+pianyiliang+10) / 40 | 0 ;
var hang = (e.clientX+pianyiliang+10) / 40 | 0 ;
console.log(e.clientX,e.clientY);
//规定黑子为1,白子为2,无子为0;
if(qipan[hang][lie] === 0){ //无子才落子
if(num % 2 == 0 ){
var p = particle(0,0,0,10,hang*40-pianyiliang,lie*40-pianyiliang,1)
qizi.push(p);
qipan[hang][lie] = 1;
}
else{
var p = particle(240,240,240,10,hang*40-pianyiliang,lie*40-pianyiliang,1)
qizi.push(p);
qipan[hang][lie] = 2;
}
qizi[num].draw(ctx);
num = num + 1; //落子才算新轮。
if(num>=8)
cheak();
}
最后就是cheak函数,就是来判断当前状态下有没有五子连珠的,网上的判断方法有很多。
可参考:https://blog.csdn.net/qiaoruozhuo/article/details/77995410
完整的JS代码:
var canvas = document.querySelector('#qipan');
var ctx = canvas.getContext('2d');
var qipan = [];
var pianyiliang = 20;
var num = 0;
var qizi =[];
for(var i = 0 ; i < 16 ; i ++ ){
qipan[i] = [];
}
for(var i = 1 ; i < 16 ; i ++ ){
for(var j = 1 ; j < 16 ; j++){
qipan[i][j] = 0;
}
}
console.log(qipan);
function drawGrid(){
ctx.fillStyle = '#cc9966';
ctx.fillRect(pianyiliang,pianyiliang,560,560);
ctx.fillStyle='#000000';
ctx.beginPath();
//划竖线
for(var i=0;i<15;i++){
ctx.moveTo(i*40+pianyiliang,0+pianyiliang);
ctx.lineTo(i*40+pianyiliang,560+pianyiliang);
ctx.stroke();
}
//横线
for(var i=0;i<15;i++){
ctx.moveTo(0+pianyiliang,i*40+pianyiliang);
ctx.lineTo(560+pianyiliang,i*40+pianyiliang);
ctx.stroke();
}
ctx.closePath();
}
function clickme(){
var e = event;
var lie = (e.clientY+pianyiliang+10) / 40 | 0 ;
var hang = (e.clientX+pianyiliang+10) / 40 | 0 ;
console.log(e.clientX,e.clientY);
//规定黑子为1,白子为2,无子为0;
if(qipan[hang][lie] === 0){ //无子才落子
if(num % 2 == 0 ){
var p = particle(0,0,0,10,hang*40-pianyiliang,lie*40-pianyiliang,1)
qizi.push(p);
qipan[hang][lie] = 1;
}
else{
var p = particle(240,240,240,10,hang*40-pianyiliang,lie*40-pianyiliang,1)
qizi.push(p);
qipan[hang][lie] = 2;
}
qizi[num].draw(ctx);
num = num + 1; //落子才算新轮。
if(num>=8)
cheak();
}
else{
alert('请不要在已经有子的地方落子哦~')
}
}
function particle(colora,colorg,colorb,r,x,y,alpha){
var obj = {
ra:colora,
rb:colorb,
rg:colorg,
r:r,
x:x,
y:y,
alpha:alpha,
draw:function(ctx){
//rgba(r,g,b,a)
ctx.fillStyle = 'rgba(' + this.ra + ',' + this.rg + ',' + this.rb + ',' +
this.alpha + ')';
ctx.beginPath();
ctx.arc(this.x,this.y,this.r,0,360,false);
ctx.fill();
ctx.closePath();
},
}
return obj;
}
function cheak(){
var A = qipan;
var n = 15;
var win = 0;
for (var i=1; i<=n && win==0; i++)
{
for (var j=1; j<=n && win==0; j++)
{
if (A[i][j] == 0) //跳过空白交叉点
continue;
if (j+4=0 && A[i][j]==A[i+1][j-1] && A[i][j]==A[i+2][j-2] && A[i][j]==A[i+3][j-3] && A[i][j]==A[i+4][j-4])//向左下搜索
win = A[i][j];
}
}
if(win === 1)
alert("黑棋胜!")
else if(win === 2)
alert("白棋胜!")
else
{}
}
drawGrid();
效果图: