如何利用canvas自己从头写一个五子棋

突然想利用canvas自己写个简单的五子棋来玩一玩:

首先新建一个html文件,如下:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>123</title>
		<!-- <link rel="stylesheet" type="text/css" href="main.css"/> -->
	</head>
	<body>
		<div id="canvas">
			<canvas id="qipan" width="640" height="640" onclick="clickme()"></canvas>
		</div>
	</body>
	<script type="text/javascript" src="index.js"></script>
</html>

然后创建一个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<n && A[i][j]==A[i][j+1] && A[i][j]==A[i][j+2] && A[i][j]==A[i][j+3] && A[i][j]==A[i][j+4])//向右搜索 
				win = A[i][j];
			if (i+4<n && A[i][j]==A[i+1][j] && A[i][j]==A[i+2][j] && A[i][j]==A[i+3][j] && A[i][j]==A[i+4][j])//向下搜索 
				win = A[i][j];
			if (i+4<n && j+4<n && 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 (i+4<n && 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();

效果图:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值