这是用Vue写的五子棋,纯前端手工实现,棋盘是自己画的,data里面的mapFlag的值是确定棋盘每个格子该怎么画,userPieceType 表示当前落子的棋子类型,黑子用1表示,白子用-1表示,0表示该处还没有棋子。drawWhite(cxt),drawBlack(cxt)分别是画白棋和黑棋的。画棋子之前会有一个判断,判断是否能落子。
drawPiecePre():显示当前鼠标预落子区域,在有棋子的区域将不显示预落子。配合cancelDrawPiecePre()使用的。
判断胜负的算法很简单,对当前落子位子进行搜索,先搜索该棋子左上角射线上同类连续棋子个数a(不计算当前落点),在搜索该棋子右下角射线上同类连续棋子个数b(不计算当前落点),若a+b>=4 ,则游戏结束,其他四条直线也是类似的算法。代码请看check()函数。
这是全部代码, 欢迎一起讨论。:
<template>
<div class="view">
<el-row :gutter="24">
<el-col :span="4">
<div class="sideView">
<el-card>左边区域</el-card>
</div>
</el-col>
<el-col :span="16">
<div class="centerView">
<el-menu
:default-active="activeIndex"
class="el-menu-demo"
mode="horizontal"
@select="handleSelect"
background-color="#545c64"
text-color="#fff"
active-text-color="#ffd04b">
<el-menu-item index="1">还没有想好</el-menu-item>
<el-submenu index="2">
<template slot="title">没得东西</template>
<el-menu-item index="2-1">选项1</el-menu-item>
<el-menu-item index="2-2">选项2</el-menu-item>
<el-menu-item index="2-3">选项3</el-menu-item>
<el-submenu index="2-4">
<template slot="title">选项4</template>
<el-menu-item index="2-4-1">选项1</el-menu-item>
<el-menu-item index="2-4-2">选项2</el-menu-item>
<el-menu-item index="2-4-3">选项3</el-menu-item>
</el-submenu>
</el-submenu>
<el-menu-item index="3" disabled>还没开发出来</el-menu-item>
<el-menu-item index="4"><a href="https://www.ele.me" target="_blank">还没开发</a></el-menu-item>
</el-menu>
<el-card>
<el-row :gutter="24">
<el-col :span="16" :offset="1">
<div class="gameArea">
<el-row v-for="(row,rowIndex) in map" :key="rowIndex">
<el-col v-for="(col, colIndex) in map[rowIndex]" :key="colIndex"
:class="col===1?'mycell':'mycell'">
<canvas :id="createId(rowIndex,colIndex)" width="42" height="42"
class="mypiece"
@mouseover="drawPiecePre(createId(rowIndex,colIndex),userPieceType,rowIndex,colIndex)"
@mouseleave="cancelDrawPiecePre(createId(rowIndex,colIndex),userPieceType,rowIndex,colIndex)"
@click="putPiece(createId(rowIndex,colIndex),userPieceType,rowIndex,colIndex)"></canvas>
</el-col>
</el-row>
</div>
</el-col>
<el-col :span="4">
<el-button @click="initGame" type="primary" v-if="gameFlag">开始游戏</el-button>
<el-button @click="initGame" type="danger" v-else>重新开始</el-button>
</el-col>
</el-row>
</el-card>
</div>
</el-col>
<el-col :span="4">
<div class="sideView">
<el-card>右边区域</el-card>
<el-card>当前棋子数量:{{ pieceNum }}</el-card>
</div>
</el-col>
</el-row>
</div>
</template>
<script>
var dc = document
export default {
name: "Wuziqi",
data() {
return {
activeIndex: '1',
map: [],
mapFlag: [
[1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3],
[4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6],
[4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6],
[4, 5, 5, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 5, 5, 6],
[4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6],
[4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6],
[4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6],
[4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6],
[4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6],
[4, 5, 5, 5, 5, 5, 5, 5, 5, 0, 5, 5, 5, 5, 5, 5, 5, 5, 6],
[4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6],
[4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6],
[4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6],
[4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6],
[4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6],
[4, 5, 5, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 5, 5, 6],
[4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6],
[4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6],
[7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9]
],
mapKey: 0,
userPieceType: 1,
pieceNum: 0,
ps: [
[-1, -1],
[1, 1],
[0, -1],
[0, 1],
[1, -1],
[-1, 1],
[-1, 0],
[1, 0]
],
gameFlag: true,
allWidth: 0,
allHeight: 0,
currentId: "",
}
},
methods: {
createId(x, y) {
return x + '-' + y;
},
initGame() {
let xArray = new Array(19);
for (let i = 0; i < 19; i++) {
xArray[i] = new Array(19)
}
for (let i = 0; i < 19; i++) {
for (let j = 0; j < 19; j++) {
xArray[i][j] = 0;
}
}
this.map = xArray;
this.pieceNum = 0
this.gameFlag = true
let that = this
setTimeout(function () {
that.drawMap(xArray);
}, 1000)
},
// 判断输赢
check(current, map) {
// console.log(map)
let ps = this.ps
let res = []
let num = 1;
for (let item = 0; item < ps.length; item++) {
if (item % 2 == 0) {
res.push(num)
num = 1
}
let position = [current[0], current[1]]
position[0] = position[0] + ps[item][0]
position[1] = position[1] + ps[item][1]
let piece = this.inMap(position, map)
while (piece == current[2]) {
position[0] = position[0] + ps[item][0]
position[1] = position[1] + ps[item][1]
num = num + 1
if (num == 5) {
return "win"
console.log("win")
}
piece = this.inMap(position, map)
}
}
console.log("continue")
return "continue"
},
inMap(position, map) {
if (position[0] >= 0 && position[0] < 19 &&
position[1] >= 0 && position[1] < 19)
return map[position[0]][position[1]]
else
return -2
},
putPiece(id, type, x, y) {
if (!this.gameFlag) {
// 游戏已经结束
return
}
console.log("当前棋子:", type == 1 ? "黑棋" : "白棋", type)
let map = this.map;
if (map[x][y]) {
this.$message.error("换个地方落子吧")
return
}
var c = dc.getElementById(id);
var cxt = c.getContext("2d")
if (type == 1) {
this.drawBlack(cxt)
} else if (type == -1) {
this.drawWhite(cxt)
}
this.putNum(id,type,x,y);
this.map[x][y] = type
this.mapKey = this.mapKey + 1
let position = [x, y, type]
let res = this.check(position, map)
this.pieceNum = this.pieceNum + 1
let temnum = this.pieceNum
let str = type == 1 ? "黑棋" : "白棋"
if (res == "win") {
this.$message.success("恭喜" + str + "获胜")
this.gameFlag = false
} else {
this.userPieceType = 0 - type
}
},
drawPiecePre(id, type, x, y) {
if (!this.gameFlag) {
// 游戏已经结束
return
}
let map = this.map
if (map[x][y] != 0)
return
var c = dc.getElementById(id);
var cxt = c.getContext("2d")
if (type == 1) {
this.drawBlack(cxt)
} else if (type == -1) {
this.drawWhite(cxt)
}
},
cancelDrawPiecePre(id, type, x, y) {
// 取消预先画好的棋子
if (this.map[x][y] != 0)
return
let mapImg = this.mapFlag;
var c = dc.getElementById(id)
var cxt = c.getContext("2d");
if (this.map[x][y] == 0) {
cxt.clearRect(0, 0, 42, 42)
} else {
return
}
console.log("离开了")
switch (mapImg[x][y]) {
case 0:
this.draw05(cxt);
this.draw00(cxt);
break;
case 1:
this.draw01(cxt);
break;
case 2:
this.draw02(cxt);
break;
case 3:
this.draw03(cxt);
break;
case 4:
this.draw04(cxt);
break;
case 5:
this.draw05(cxt);
break;
case 6:
this.draw06(cxt);
break;
case 7:
this.draw07(cxt);
break;
case 8:
this.draw08(cxt);
break;
case 9:
this.draw09(cxt);
break;
}
},
putNum(id, type, x, y){
var c = dc.getElementById(id);
var cxt = c.getContext("2d")
let color = ""
if(type == 1){
color = "#FFFFFF"
}else{
color = "#000000"
}
let num = this.pieceNum + 1
this.drawNum(cxt,color,num)
},
drawMap(map) {
let mapImg = this.mapFlag;
for (let i = 0; i < 19; i++) {
for (let j = 0; j < 19; j++) {
var cellId = i + "-" + j;
var c = dc.getElementById(cellId)
var cxt = c.getContext("2d");
cxt.clearRect(0, 0, 42, 42)
switch (mapImg[i][j]) {
case 0:
this.draw05(cxt);
this.draw00(cxt);
// this.drawWhite(cxt)
break;
case 1:
this.draw01(cxt);
break;
case 2:
this.draw02(cxt);
break;
case 3:
this.draw03(cxt);
break;
case 4:
this.draw04(cxt);
break;
case 5:
this.draw05(cxt);
break;
case 6:
this.draw06(cxt);
break;
case 7:
this.draw07(cxt);
break;
case 8:
this.draw08(cxt);
break;
case 9:
this.draw09(cxt);
break;
}
// console.log("画好了")
}
}
},
drawWhite(cxt) {
cxt.fillStyle = '#FFFFFF';
// cxt.fillStyle = "#000000";
cxt.beginPath();
cxt.arc(21, 21, 16, 0, Math.PI * 2, true);
cxt.closePath();
cxt.fill();
cxt.fillStyle = "#000000"
cxt.beginPath();
cxt.arc(21, 21, 17, 0, Math.PI * 2, true);
cxt.stroke();
},
drawBlack(cxt) {
cxt.fillStyle = "#000000";
cxt.beginPath();
cxt.arc(21, 21, 16, 0, Math.PI * 2, true);
cxt.closePath();
cxt.fill();
},
drawNum(cxt, fillStyle, num){
cxt.font = '24px Georgia'
// cxt.fontSize = "16px"
cxt.fillStyle = fillStyle
cxt.fillText(num+"",14,26)
},
draw00(cxt) {
cxt.fillStyle = "#000000";
cxt.beginPath();
cxt.arc(21, 21, 6, 0, Math.PI * 2, true);
cxt.closePath();
cxt.fill();
},
draw01(ctx) {
ctx.fillStyle = "#000000"
ctx.fillRect(19, 19, 4, 23)
ctx.fillRect(19, 19, 23, 4)
},
draw02(ctx) {
ctx.fillStyle = "#000000"
ctx.fillRect(0, 19, 42, 4)
ctx.fillRect(20, 20, 2, 42)
},
draw03(ctx) {
ctx.fillStyle = "#000000"
ctx.fillRect(0, 19, 22, 4)
ctx.fillRect(19, 19, 4, 42)
},
draw04(ctx) {
ctx.fillStyle = "#000000"
ctx.fillRect(19, 0, 4, 42)
ctx.fillRect(20, 20, 22, 2)
},
draw05(ctx) {
ctx.fillStyle = "#000000"
ctx.fillRect(20, 0, 2, 42)
ctx.fillRect(0, 20, 42, 2)
},
draw06(ctx) {
ctx.fillStyle = "#000000"
ctx.fillRect(19, 0, 4, 42)
ctx.fillRect(0, 20, 22, 2)
},
draw07(ctx) {
ctx.fillStyle = "#000000"
ctx.fillRect(19, 0, 4, 22)
ctx.fillRect(19, 19, 25, 4)
},
draw08(ctx) {
ctx.fillStyle = "#000000"
ctx.fillRect(0, 19, 42, 4)
ctx.fillRect(20, 0, 2, 22)
},
draw09(ctx) {
ctx.fillStyle = "#000000"
ctx.fillRect(0, 19, 22, 4)
ctx.fillRect(19, 0, 4, 22)
},
handleSelect(key, keyPath) {
console.log(key, keyPath);
}
},
mounted() {
this.initGame()
// this.test();
this.allWidth = window.innerWidth;
this.allHeith = window.innerHeight;
console.log("运行了", this.allWidth, this.allHeith)
}
}
</script>
<style scoped>
.mypiece {
/*box-shadow:3px 3px 5px;*/
}
.mycell {
width: 42px !important;
height: 42px !important;
inset-inline: auto;
background-color: beige;
}
.mycellstyle {
width: 42px !important;
height: 42px !important;
}
.gameArea {
/*background-color:white;*/
background-color: antiquewhite;
width: 100%;
height: 100%;
min-height: 700px;
min-width: 800px!important;
max-width: 800px
;
}
.el-col-16 {
padding: 2px !important;
}
.el-col-4 {
padding: 2px !important;
}
.centerView {
background-color: aqua;
height: 100%;
width: 100%;
min-height: 900px;
padding: 0 !important;
margin: 0 !important;
}
.sideView {
background-color: aquamarine;
height: 100%;
width: 100%;
min-height: 900px;
padding: 0 !important;
margin: 0 !important;
}
.view {
/*width: 100%;*/
/*height: 100%;*/
max-width: 1900px;
}
</style>
点赞加收藏超过30,将实现联机对战版的。
点赞加收藏超过30,将实现联机对战版的。
点赞加收藏超过30,将实现联机对战版的。
点赞加收藏超过60,你们评论我来改!
点赞加收藏超过60,你们评论我来改!
点赞加收藏超过60,你们评论我来改!
欢迎私信来催!