Vue实现单机五子棋(附源码)

​ 这是用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,你们评论我来改!

欢迎私信来催!

  • 7
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值