目录
简介
根据自身学习使用前端三件套以及canvas做一个简易版五子棋,该实现了简单的判断五个颜色相同的棋子是否连成一条直线的功能,唯一不足的是未实现人机交互只实现了人人交互,因为不想使用随机算法进行,等后期会继续完善
棋盘介绍
一、棋盘介绍
棋盘采用了15 * 15,共有225个交叉点
棋子采用了黑白两棋
二、下棋过程
绘制棋盘,棋子
执黑子先落子,然后双方轮流落子
判断胜负
三、功能设计
canvas获取画布
<canvas id = 'c1' width = '800' height='800'></canvas>
/** @type {HTMLCanvasElement} */
//1.找到画布
var c1 = document.getElementById('c1')
//位置:x,y,宽度,高度
//获取tip元素
let tip = document.querySelector('.tip')
//2.获取画笔,上下文对象
var ctx = c1.getContext("2d")
画棋盘
//画棋盘
for(let i=1;i<16;i++)
{
//横线
ctx.moveTo(50,50*i)
ctx.lineTo(750,50*i)
ctx.stroke()
//纵线
ctx.moveTo(50*i,50)
ctx.lineTo(50*i,750)
ctx.stroke()
}
设计棋子、并进行美化
//根据当前是那种棋子,给不同的颜色
// ctx.fillStyle = isblack ? '#000' : '#fff'
remb[m][n] = isblack ? 'black' : 'white'
let tx = isblack ? x - 10 : x + 10
let ty = isblack ? y - 10 : y + 10
const g = ctx.createRadialGradient(tx,ty,0,tx,ty,30)
g.addColorStop(0,isblack ? '#ccc' : '#666')
g.addColorStop(1,isblack ? '#000' : '#fff')
ctx.fillStyle = g
//美化棋子 增加其中的立体感
ctx.shadowBlur = 4
ctx.shadowColor = '#000'
ctx.shadowOffsetX = 4
ctx.shadowOffsetY = 4
ctx.fill()
ctx.closePath()
美化主要是给棋子增加立体感
判断棋子是否有五个相同的棋子连成一条直线
//纵向
function check(row,col){
//定义一个变量,记录向上的次数
let up = 0
//定义一个变量,记录向下的次数
let down = 0
let counts = 1 //记录目标棋子出现的次数
let times = 0
while(times < 10000){ //防止出现死循环
let target = isblack ? 'black' : 'white'
times++
up++
//判断纵向
if(remb[row][col-up]&&remb[row][col-up] == target){
counts++
}
down++
if(remb[row][col+down]&&remb[row][col+down] == target){
counts++
}
// 判断棋子是否有五个成一条直线或者有断的不同色
if(counts >= 5 || remb[row][col-up] !== target && remb[row][col+down] !== target)
{
break
}
}
return (counts >= 5)
}
//检查横向是否有五个连成一条直线
function checkH(row,col){
let count = 1
let times1 = 0
let left = 0
let right = 0
while(times1 < 10000){
times1++
let target1 = isblack ? 'black' : 'white'
left++
if(remb[row - left][col]&&remb[row - left][col] == target1){
count++
}
right++
if(remb[row + right][col]&&remb[row + right][col] == target1){
count++
}
if(count >= 5 || remb[row-left][col] !== target1 && remb[row + right][col] !== target1){
break
}
}
return (count >= 5)
}
//检查从左上到右下是否有五个成一条直线
function checkZsYx(row,col){
let count = 1
let times = 0
let zs = 0
let yx = 0
while(times < 10000){
times++
let target = isblack ? 'black' : 'white'
zs++
if(remb[row - zs][col - zs]&& remb[row - zs][col - zs] == target){
count++
}
yx++
if(remb[row + yx][col + yx]&& remb[row + yx][col + yx]){
count++
}
if(count >= 5 || remb[row - zs][col - zs] !== target && remb[row + yx][col + yx] !== target){
break
}
}
return (count >= 5)
}
//检查从右上到左下是否有五个连成一条直线
function checkYsZx(row,col){
let count = 1
let times = 1
let ys = 0
let zx = 0
while(times < 10000){
times ++
let target = isblack ? 'black' : 'white'
ys++
if(remb[row + ys][col - ys]&&remb[row + ys][col - ys] == target){
count++
}
zx++
if(remb[row - zx][col + zx]&&remb[row-zx][row + zx] == target){
count++
}
if(count >= 5 || remb[row + ys][col - ys] !== target && remb[row - zx][col + zx] !== target){
break
}
}
return (count >= 5)
}
运行效果图
完整代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
canvas{
background-color: darkgoldenrod;
display: block;
margin:0 auto;
}
.tip{
text-align: center;
padding:20px;
}
</style>
</head>
<body>
<div class="tip">请黑棋落子</div>
<canvas id = 'c1' width = '800' height='800'></canvas>
<script>
/** @type {HTMLCanvasElement} */
//1.找到画布
var c1 = document.getElementById('c1')
//位置:x,y,宽度,高度
//获取tip元素
let tip = document.querySelector('.tip')
//2.获取画笔,上下文对象
var ctx = c1.getContext("2d")
//画棋盘
for(let i=1;i<16;i++)
{
//横线
ctx.moveTo(50,50*i)
ctx.lineTo(750,50*i)
ctx.stroke()
//纵线
ctx.moveTo(50*i,50)
ctx.lineTo(50*i,750)
ctx.stroke()
}
let isblack = true
let remb = []
for(let i = 1;i < 16; i++){
remb[i] = []
}
let endGame = false
c1.addEventListener('click',e=>{
let {offsetX : x,offsetY : y} = e
if(x < 25 || y < 25|| x > 775||y > 775){
return
}
let m = Math.floor((x + 25) / 50)
let n = Math.floor((y + 25) / 50)
x = m * 50
y = n * 50
if(endGame){
//当有五个相同的棋子连城一条线,则返回,click事件无效
return
}
ctx.beginPath()
ctx.arc(x,y,20,0,2 * Math.PI)
//判断当前位置是否存在棋子
if(remb[m][n]){
tip.innerHTML = `不能重复落子,当前是${isblack ? '黑子' : '白子'}落棋`
return
}
//根据当前是那种棋子,给不同的颜色
// ctx.fillStyle = isblack ? '#000' : '#fff'
remb[m][n] = isblack ? 'black' : 'white'
let tx = isblack ? x - 10 : x + 10
let ty = isblack ? y - 10 : y + 10
const g = ctx.createRadialGradient(tx,ty,0,tx,ty,30)
g.addColorStop(0,isblack ? '#ccc' : '#666')
g.addColorStop(1,isblack ? '#000' : '#fff')
ctx.fillStyle = g
//美化棋子 增加其中的立体感
ctx.shadowBlur = 4
ctx.shadowColor = '#000'
ctx.shadowOffsetX = 4
ctx.shadowOffsetY = 4
ctx.fill()
ctx.closePath()
//判断是否已经有5个棋子连成一条线
endGame = check(m,n) || checkH(m,n) || checkZsYx(m,n) || checkYsZx(m,n)
if(endGame){
tip.innerText = `${isblack ? '黑' : '白'}子已获胜,请刷新重新开始`
return
}
isblack = !isblack
//提醒用户落棋
tip.innerHTML = isblack ? '请黑棋落子' : '请白棋落子'
})
//纵向
function check(row,col){
//定义一个变量,记录向上的次数
let up = 0
//定义一个变量,记录向下的次数
let down = 0
let counts = 1 //记录目标棋子出现的次数
let times = 0
while(times < 10000){ //防止出现死循环
let target = isblack ? 'black' : 'white'
times++
up++
//判断纵向
if(remb[row][col-up]&&remb[row][col-up] == target){
counts++
}
down++
if(remb[row][col+down]&&remb[row][col+down] == target){
counts++
}
// 判断棋子是否有五个成一条直线或者有断的不同色
if(counts >= 5 || remb[row][col-up] !== target && remb[row][col+down] !== target)
{
break
}
}
return (counts >= 5)
}
//检查横向是否有五个连成一条直线
function checkH(row,col){
let count = 1
let times1 = 0
let left = 0
let right = 0
while(times1 < 10000){
times1++
let target1 = isblack ? 'black' : 'white'
left++
if(remb[row - left][col]&&remb[row - left][col] == target1){
count++
}
right++
if(remb[row + right][col]&&remb[row + right][col] == target1){
count++
}
if(count >= 5 || remb[row-left][col] !== target1 && remb[row + right][col] !== target1){
break
}
}
return (count >= 5)
}
//检查从左上到右下是否有五个成一条直线
function checkZsYx(row,col){
let count = 1
let times = 0
let zs = 0
let yx = 0
while(times < 10000){
times++
let target = isblack ? 'black' : 'white'
zs++
if(remb[row - zs][col - zs]&& remb[row - zs][col - zs] == target){
count++
}
yx++
if(remb[row + yx][col + yx]&& remb[row + yx][col + yx]){
count++
}
if(count >= 5 || remb[row - zs][col - zs] !== target && remb[row + yx][col + yx] !== target){
break
}
}
return (count >= 5)
}
//检查从右上到左下是否有五个连成一条直线
function checkYsZx(row,col){
let count = 1
let times = 1
let ys = 0
let zx = 0
while(times < 10000){
times ++
let target = isblack ? 'black' : 'white'
ys++
if(remb[row + ys][col - ys]&&remb[row + ys][col - ys] == target){
count++
}
zx++
if(remb[row - zx][col + zx]&&remb[row-zx][row + zx] == target){
count++
}
if(count >= 5 || remb[row + ys][col - ys] !== target && remb[row - zx][col + zx] !== target){
break
}
}
return (count >= 5)
}
</script>
</body>
</html>
友友们直接可以将代码复制到VScode中直接编译运行
过几天我会将完善之后的代码发出来,希望友友们指正