canvas学习之五子棋规则法部分实现
前言
想学习下vue中使用canvas,直接学习感觉太无聊,通过实现五子棋增加些乐趣,过程中发现规则算法实现起来还是有一些复杂度的
代码实现
初步代码结构
<template><canvas ref="myCanvas" width="640" height="640" @click="func.next"></canvas><div><button @click="func.start">开始</button><span style="color: red">{{property.message}}</span></div>
</template><script>
import {ref, reactive, onMounted} from 'vue'
export default {name: "GoBang",setup(){const myCanvas = ref(null)const property = reactive({size: 40, //棋盘每格宽高rowNum: 15, //棋盘行数列数message: '',})const ai = reactive({})const func = reactive({start: () => {},next: () => {}})onMounted(() => {})return{myCanvas,property,func}}
}
</script><style scoped></style>
canvas组件context要在所有组件加载完才能调用,所以要放到onMunted中
let ctx = ref(null)
const func = reactive({init: () => {ctx = myCanvas.value.getContext('2d')},drawChessBoard: () => {ctx.beginPath()ctx.rect(0, 0, (property.size * (property.rowNum + 1)), (property.size * (property.rowNum + 1)))ctx.strokeStyle = 'green'ctx.stroke()//棋盘for(let i = 1; i <= property.rowNum; i++){ctx.moveTo(i * property.size, property.size)ctx.lineTo(i * property.size, property.size * property.rowNum)}for(let j = 1; j <= property.rowNum; j++){ctx.moveTo(property.size, property.size * j)ctx.lineTo(property.size * property.rowNum, property.size * j)}ctx.stroke()ctx.closePath()},start: () => {},next: () => {}
})
onMounted(() => {func.init()func.drawChessBoard()
})
效果图
画棋子
const property = reactive({size: 40, //棋盘每格宽高rowNum: 15, //棋盘行数列数message: '',validRange: 0.3 //棋子的半径占每格比
})
//func中
drawChess: (x, y, color) => {ctx.beginPath()ctx.moveTo(x+ property.size * property.validRange, y )ctx.arc(x, y, property.size * property.validRange, 0, 2 * Math.PI)ctx.strokeStyle = colorctx.fillStyle = colorctx.fill()ctx.stroke()ctx.closePath()
}
ai逻辑
const operate = reactive({computer: 1,people: 2
})
const ai = reactive({//检测是否五子checkFive: () => {},//查找单4的位置findBySingleFour: () => {},//查找下一步棋后将会双4的位置findWillBeDoubleFour: () => {},//查找下一步棋后将会单4且双三的位置 暂不实现findWillBeSingleFourAndDoubleThree: () => {},//查找下一步棋后将会两个双三的位置 暂不实现findWillBeTwoDoubleThree: () => {},//查找下两步棋后将会是双4的位置 代替上面两个未实现的方法,但减少了智能findWillBeDoubleFourStep2: () => {},//查找跟随位置,跟随人下棋的位置 落子到旁边findFollowPosition:() => {},//周边找不到位置 随机findRandomPosition: () => {}
})
checkFive
checkFive: (a, rowNum, operator) => {for(let i = 0; i < rowNum; i++){for(let j = 0; j < rowNum ; j++){if(i >= 2 && i < (rowNum - 2) && (a[i][j] & a[i + 1][j] & a[i + 2][j] & a[i - 1][j] & a[i - 2][j]) == operator ||j >= 2 && j < (rowNum - 2) && (a[i][j] & a[i][j + 1] & a[i][j + 2] & a[i][ j - 1] & a[i][j - 2]) == operator ||i >= 2 && j >= 2 && i < (rowNum - 2) && j < (rowNum - 2) && (a[i][j] & a[i + 1][j + 1] & a[i + 2][j + 2] & a[i - 1][j - 1] & a[i - 2][j - 2]) == operator ||i >= 2 && j >= 2 && i < (rowNum - 2) && j < (rowNum - 2) && (a[i][j] & a[i - 1][j + 1] & a[i - 2][j + 2] & a[i + 1][j - 1] & a[i + 2][j - 2]) == operator){return true}}}return false
}
findBySingleFour
//查找单4的位置
findBySingleFour: (a, rowNum, operator) => {let sum = 4 * operatorfor(let i = 0; i < rowNum; i++){for(let j = 0; j < rowNum; j++){//横向判断if(i >= 2 && i < rowNum - 2 && (a[i][j] + a[i + 1][j] + a[i + 2][j] + a[i - 1][j] + a[i - 2][j]) == sum &&(a[i][j] | a[i + 1][j] | a[i + 2][j] | a[i - 1][j] | a[i - 2][j]) == operator){for(let index = 0; index < 5; index++){if(a[i - 2 + index][j] == 0){return {x: i - 2 + index,y: j}}}}//纵向判断if(j >= 2 && j < rowNum - 2 && (a[i][j] + a[i][j + 1] + a[i][j + 2] + a[i][ j - 1] + a[i][j - 2]) == sum &&(a[i][j] | a[i][j + 1] | a[i][j + 2] | a[i][j - 1] | a[i][j - 2]) == operator){for(let index = 0; index < 5; index++){if(a[i][j - 2 + index] == 0){return {x: i,y: j - 2 + index}}}}//正斜向判断if(i >= 2 && i < rowNum - 2 && j >= 2 && j < rowNum - 2 && (a[i][j] + a[i + 1][j + 1] + a[i + 2][j + 2] + a[i - 1][j - 1] + a[i - 2][j - 2]) == sum &&(a[i][j] | a[i + 1][j + 1] | a[i + 2][j + 2] | a[i - 1][j - 1] | a[i - 2][j - 2]) == operator){for(let index = 0; index < 5; index++){if(a[i - 2 + index][j - 2 + index] == 0){return {x: i - 2 + index,y: j - 2 + index}}}}//反斜向判断if(i >= 2 && i < rowNum - 2 && j >= 2 && j < rowNum - 2 && (a[i][j] + a[i - 1][j + 1] + a[i - 2][j + 2] + a[i + 1][j - 1] + a[i + 2][j - 2]) == sum &&(a[i][j] | a[i - 1][j + 1] | a[i - 2][j + 2] | a[i + 1][j - 1] | a[i + 2][j - 2]) == operator){for(let index = 0; index < 5; index++){if(a[i - 2 + index][j + 2 - index] == 0){return {x: i - 2 + index,y: j + 2 - index}}}}}}return null
}
findWillBeDoubleFour
findWillBeDoubleFour: (a, rowNum, operator) => {let sum = 3 * operatorfor(let i = 0; i < rowNum; i++){for(let j = 0; j < rowNum; j++){if(i >= 2 && i < rowNum - 2 && (a[i][j] + a[i + 1][j] + a[i + 2][j] + a[i - 1][j] + a[i - 2][j]) == sum &&(a[i][j] | a[i + 1][j] | a[i + 2][j] | a[i - 1][j] | a[i - 2][j]) == operator && (a[i - 2][j] == 0 || a[i + 2][j] == 0)){//两边界必须为空if(a[i - 2][j] == 0 && i < rowNum - 3 && a[i + 3][j] == 0 ||a[i + 2][j] == 0 && i > 2 && a[i - 3][j] == 0){for(let index = 0; index < 3; index++){if(a[i - 1 + index][j] == 0){return {x: i - 1 + index,y: j}}}//中间三个满了return a[i - 2][j] == 0 && i < rowNum - 3 && a[i + 3][j] == 0 ?{x: i + 2,y: j} :{x: i - 2,y: j}}}//纵向判断if(j >= 2 && j < rowNum - 2 && (a[i][j] + a[i][j + 1] + a[i][j + 2] + a[i][ j - 1] + a[i][j - 2]) == sum &&(a[i][j] | a[i][j + 1] | a[i][j + 2] | a[i][j - 1] | a[i][j - 2]) == operator && (a[i][j - 2] == 0 || a[i][j + 2] == 0)){//两边界必须为空if(a[i][j - 2] == 0 && j < rowNum - 3 && a[i][j + 3] == 0 ||a[i][j + 2] == 0 && j > 2 && a[i][j - 3] == 0){for(let index = 0; index < 3; index++){if(a[i][j - 1 + index] == 0){return {x: i,y: j - 1 + index}}}//中间三个满了return a[i][j - 2] == 0 && j < rowNum - 3 && a[i][j + 3] == 0 ?{x: i,y: j + 2} :{x: i,y: j - 2}}}//正斜向判断if(i >= 2 && i < rowNum - 2 && j >= 2 && j < rowNum - 2 && (a[i][j] + a[i + 1][j + 1] + a[i + 2][j + 2] + a[i - 1][j - 1] + a[i - 2][j - 2]) == sum &&(a[i][j] | a[i + 1][j + 1] | a[i + 2][j + 2] | a[i - 1][j - 1] | a[i - 2][j - 2]) == operator && (a[i - 2][j - 2] == 0 || a[i + 2][j + 2] == 0)){//两边界必须为空if(a[i - 2][j - 2] == 0 && i < rowNum - 3 && j < rowNum - 3 && a[i + 3][j + 3] == 0 ||a[i + 2][j + 2] == 0 && i > 2 && j > 2 && a[i - 3][j - 3] == 0){for(let index = 0; index < 3; index++){if(a[i - 1 + index][j - 1 + index] == 0){return {x: i - 1 + index,y: j - 1 + index}}}//中间三个满了return a[i - 2][j - 2] == 0 && i < rowNum - 3 && j < rowNum - 3 && a[i + 3][j + 3] == 0 ?{x: i + 2,y: j + 2} :{x: i - 2,y: j - 2}}}//反斜向判断if(i >= 2 && i < rowNum - 2 && j >= 2 && j < rowNum - 2 && (a[i][j] + a[i - 1][j + 1] + a[i - 2][j + 2] + a[i + 1][j - 1] + a[i + 2][j - 2]) == sum &&(a[i][j] | a[i - 1][j + 1] | a[i - 2][j + 2] | a[i + 1][j - 1] | a[i + 2][j - 2]) == operator && (a[i + 2][j - 2] == 0 || a[i - 2][j + 2] == 0)){//两边界必须为空if(a[i - 2][j + 2] == 0 && i < rowNum - 3 && j > 2 && a[i + 3][j - 3] == 0 ||a[i + 2][j - 2] == 0 && i > 2 && j < rowNum - 3 && a[i - 3][j + 3] == 0){for(let index = 0; index < 3; index++){if(a[i - 1 + index][j + 1 - index] == 0){return {x: i - 1 + index,y: j + 1 - index}}}//中间三个满了return a[i - 2][j + 2] == 0 && i < rowNum - 3 && j > 2 && a[i + 3][j - 3] == 0 ?{x: i - 2,y: j + 2} :{x: i + 2,y: j - 2}}}}}return null
}
findWillBeDoubleFourStep2
//查找下两步棋后将会是双4的位置 代替上面两个未实现的方法,但减少了智能
findWillBeDoubleFourStep2: (a, rowNum, operator) => {for(let i = 0; i < rowNum; i++){for(let j = 0; j < rowNum; j++){if(a[i][j] == 0){a[i][j] = operatorlet p = ai.findWillBeDoubleFour(a, rowNum, operator)a[i][j] = 0if(p){return {x: i,y: j}}}}}
}
findFollowPosition
//查找跟随位置,跟随人下棋的位置 落子到旁边
findFollowPosition: (a, i, j, rowNum) => {if(i >= 1 && a[i - 1][j] == 0){return {x: i - 1,y: j}}if(j >= 1 && a[i][j - 1] == 0){return {x: i,y: j - 1}}if(i < rowNum - 1 && a[i + 1][j] == 0){return {x: i + 1,y: j}}if(j < rowNum - 1 && a[i][j + 1] == 0){return {x: i,y: j + 1}}if(i >= 1 && j >= 1 && a[i - 1][j - 1] == 0){return {x: i - 1,y: j - 1}}if(i >= 1 && j < rowNum - 1 && a[i - 1][j + 1] == 0){return {x: i - 1,y: j + 1}}if(i < rowNum - 1 && j >= 1 && a[i + 1][j - 1] == 0){return {x: i + 1,y: j - 1}}if(i < rowNum - 1 && j < rowNum - 1 && a[i + 1][j + 1] == 0){return {x: i + 1,y: j + 1}}
}
findRandomPosition
//周边找不到位置 随机
findRandomPosition: (rowNum, dressNum) => {let value = 0let totalNum = rowNum * rowNumwhile(dressNum < totalNum){value = Math.floor(Math.random() * rowNum * rowNum)let i = Math.floor(value / rowNum)let j = value % property.rowNumif(property.data[x][y] == 0){return {x : i,y : j}}}return null
}
人落子相关
const property = reactive({size: 40, //棋盘每格宽高rowNum: 15, //棋盘行数列数message: '',validRange: 0.3, //棋子的半径占每格比canMove: false,data: [],dressNum: 0
})//人最后落子的位置
const lastPosition = {i: 0,j: 0
}start: () => {property.canMove = true
},
next: (p) => {if(!property.canMove){return}property.canMove = falselet x = p.offsetXlet y = p.offsetYx = func.calcPosition(x, property.validRange, property.size)y = func.calcPosition(y, property.validRange, property.size)if(x == -1 || y == -1){return}func.drawChess(x, y, 'red')//记忆落子位置let i = x / property.size - 1let j = y / property.size - 1lastPosition.i = ilastPosition.j = jproperty.data[i][j] = operate.peopleif(ai.checkFive(property.data, property.rowNum, operate.people)){func.win(operate.people)return}func.aiNext()
},
calcPosition: (x, validRange, size) => {let xRemainder = x % sizereturn xRemainder < validRange * size ? (x - xRemainder) :(xRemainder < (1 - validRange) * size ? - 1 : (x + size - xRemainder))
},
ai落子
aiNext: () => {//检查自己单4let p = ai.findBySingleFour(property.data, property.rowNum, operate.computer)if(p){func.drawChess((p.x + 1) * property.size, (p.y + 1) * property.size, 'black')func.win(operate.computer)return}//查找对方单4p = ai.findBySingleFour(property.data, property.rowNum, operate.people)if(p){func.drawBlackChess(p)return}//查找自己将要双4的位置p = ai.findWillBeDoubleFour(property.data, property.rowNum, operate.computer)if(p){func.drawBlackChess(p)return}//查找对方将要双4的位置p = ai.findWillBeDoubleFour(property.data, property.rowNum, operate.people)if(p){func.drawBlackChess(p)return}//查找对方两步将要双4的位置p = ai.findWillBeDoubleFourStep2(property.data, property.rowNum, operate.people)if(p){func.drawBlackChess(p)return}//查找自己两步将要双4的位置p = ai.findWillBeDoubleFourStep2(property.data, property.rowNum, operate.computer)if(p){func.drawBlackChess(p)return}//跟随位置p = ai.findFollowPosition(property.data, lastPosition.i, lastPosition.j, property.rowNum)if(p){func.drawBlackChess(p)return}p = ai.findRandomPosition(property.rowNum, property.dressNum)func.drawBlackChess(p)},
win: (operator) => {property.message = operator == 1 ? "黑方胜" : "红方胜"property.canMove = false
},
drawBlackChess: (p) => {func.drawChess((p.x + 1) * property.size, (p.y + 1) * property.size, 'black')property.data[p.x][p.y] = 1property.canMove = true
},
checkDressNum: () => {if(property.dressNum == property.rowNum * property.rowNum){property.message = "和棋了"}
},
drawChess: (x, y, color) => {ctx.beginPath()ctx.moveTo(x+ property.size * property.validRange, y )ctx.arc(x, y, property.size * property.validRange, 0, 2 * Math.PI)ctx.strokeStyle = colorctx.fillStyle = colorctx.fill()ctx.stroke()ctx.closePath()property.dressNum++func.checkDressNum()
}
最终效果
canvas学习之五子棋规则法部分实现相关推荐
- canvas学习笔记
canvas学习笔记 canvas API中文网 - Canvas API中文文档首页地图 使用canvas来绘制图形 - Web API 接口参考 | MDN 什么是Canvas? Canvas是H ...
- java五子棋项目创新点_五子棋规则的改革创新方法
五子棋规则最近几年来,关于五子棋规则改革的讨论掀起了一阵阵高潮,形态各异的新规则层出无穷,可谓是对各种规则改革方案的大胆设想.下面小编给你介绍五子棋规则的改革创新,欢迎阅读. 五子棋大多数新规则跟流星 ...
- HTML5 Canvas 学习日志(三)
2019独角兽企业重金招聘Python工程师标准>>> HTML5 Canvas 学习日志(三) Canvas的11种合成 蓝色为destination,粉色为source 1 ...
- Canvas 学习笔记1
#Canvas 学习笔记1 @[Canvas,Nunn,HTML5,javascript] ##前言 相信大家多多少少都有了解过`Canvas`,这里我就不多做解释了,网上也充斥了这方面的知识,很多人 ...
- canvas学习和滤镜实现
最近学习了 HTML5 中的重头戏-- canvas .利用 canvas,前端人员可以很轻松地.进行图像处理.其 API 繁多,这次主要学习常用的 API,并且完成以下两个代码: 实现去色滤镜 实现 ...
- Canvas学习:封装Canvas绘制基本图形API
Canvas学习:封装Canvas绘制基本图形API Canvas Canvas学习 从前面的文章中我们了解到,通过Canvas中的CanvasRenderingContext2D对象中的属性和方法, ...
- canvas学习绘制渐变色
1.createLinearGradient() 创建线性渐变 //Linear adj. 直线的 线性的 //Gradient n. 梯度 变化率 createLinearGradient(x1,y ...
- 第六节 电子学习 二极管档测量法 细讲
二极管档测量法非常重要,维修过程中,作者是用的最多的方法, 第四节讲了一些,但是图示仍不明确,可能很多实践少的朋友不理解. 这里绘图更详细的讲解. 见上图, 现代集成电路工艺,每个引脚内部都有一个保护 ...
- Canvas学习笔记之画线
Canvas学习笔记之画线 步骤 1.使用getElementById()获取canvas元素. 2.获取canvas的绘制环境getContext(). 3.进行绘制画笔的粗细和颜色定义,分别是li ...
最新文章
- OpenCV中与matlab中相对应的函数
- mysql 相关命令
- 【Codeforces】401C Team (01010110...)
- 彻底取代Redis+数据库架构,京东618稳了!
- 推荐算法炼丹笔记:序列化推荐算法Bert4Rec
- CPU方案简介 RK3308 - 智能音响
- LiveVideoStack线上分享第三季(九):《街舞》《长安十二时辰》背后的文娱大脑...
- dos输入java Hello,出现错误: 找不到或无法加载主类 Hello
- SAP License:你是怎么理解ERP的?
- 【报告分享】2020年抖音美妆直播报告.pdf(附下载链接)
- linux识别设备插槽,你如何确定linux计算机的CPU插槽类型?
- 西数linux驱动程序,下载:西数移动硬盘WD SES Driver驱动更新
- Flutter修改App名称(Android+IOS)
- 当网页无法正常显示时更换浏览器
- 鱼眼和全向视图的图像深度学习方法
- BioBERT: a pre-trained biomedical language representation model for biomedical text mining
- 华为大数据研发第3轮面试
- 什么是地理信息系统(GIS)?
- python读取word内容复制粘贴_如何复制word文档的内容?
- ubuntu展示点云使用boost::this_thread报错
热门文章
- 计算机辅助测试技术最近的发展,CAT_计算机辅助测试_技术_第六讲_CAT的发展_郑叔芳...
- 技法の穴をふさぐ:規模編--技法のルールは分かりにくい数え方の“迷い”をなくす
- Lagrangian乘子法与对偶上升法(Dual Ascent)
- matlab绘制线性回归_如何在Excel中绘制线性校准曲线
- 简单几个设置教会你更好的保护Mac!不让你的Mac中毒小妙招!
- 【Educoder】密码学理论与实战 30+完整过题代码
- Python 数据分析学习笔记(一):Pandas 入门
- CRM系统需具有的九大功能
- 怎么让Java系统的手机连WiFi_Java-Jain Sip如何在Android中连接WiFi
- Cryp.1.大整数相乘---分治法