目前已经实现的功能: 
V1.0 : 实现棋子的布局,画布及游戏场景的初始化
V2.0 : 实现棋子的颜色改变
V3.0 :实现所有象棋的走棋规则
V4.0 : 实现所有棋子的吃子功能

【原创】使用HTML5+canvas+JavaScript开发的原生中国象棋游戏及源码分享-LMLPHP

GItHub源码下载地址:https://github.com/xiugangzhang/ChineseChess
如果需要直接体验的朋友也可以直接通过这个连接体验哈:
http://htmlpreview.github.io/?https://github.com/xiugangzhang/ChineseChess/blob/master/ChineseChess.html

其他项目推荐:

视频网站项目:https://github.com/xiugangzhang/vip.github.io(在线体验地址:http://vip.52tech.tech)

超级马里奥游戏项目:https://github.com/xiugangzhang/SuperMarioGame

如果觉得不错,也欢迎大家给个star支持一下,你的支持就是我前进的动力!

中国象棋项目源码:

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Title</title>    <style>        * {            margin: 0;            padding: 0;        }    </style></head> <body><canvas id="myCanvas" width="600px" height="660px"></canvas><script>    //V1.0 : 实现棋子的布局,画布及游戏场景的初始化    //V2.0 : 实现棋子的颜色改变    //V3.0 :实现所有象棋的走棋规则    //V4.0 : 实现所有棋子的吃子功能    var canvas = document.getElementById("myCanvas");    var context = canvas.getContext("2d");    /**     * 棋子对象     * @param x     * @param y     * @param color     * @constructor     */    function Chess(x, y, color, type) {        this.x = x;        this.y = y;        this.color = color;        this.type = type;        // 记录颜色        this.chessColor = color;        // 是否死掉        this.isDead = false;    }    // 成员函数    Chess.prototype = {        _getChessText: function () {            switch (this.type) {                case "CHE":                    return "车";                case "MA":                    return "马";                case "PAO":                    return "炮";                case "BING":                    return "兵";                case "JIANG":                    return "将";                case "SHI":                    return "士";                case "XIANG":                    return "相";            }            return "错误";        }    }    /**     * 游戏场景     * @constructor     */    function Game() {        // 存放当前棋盘上所有的棋子        this._chesses = [];        //初始位置        this._initX = 60;        this._initY = 60;        // 判断鼠标是否点击有棋子        this._selectedChess = null;        this._initCount = 0;    }    Game.prototype = {        // 场景的初始化        execute: function () {            this._initChesses();            this._start();        },        _initChesses: function () {            // 绘制棋子(初始位置)            // 总共需要绘制32颗棋子            // 红色棋子            var redChess;            for (var i = 0; i < 4; i++) {                for (var j = 0; j < 9; j++) {                    if ((i == 0 && j == 0) || (j == 8 && i == 0)) {                        // 把棋子的颜色传进去                        redChess = new Chess(j, i, "red", "CHE");                        this._chesses.push(redChess);                    } else if ((j == 1 && i == 0) || (j == 7 && i == 0 )) {                        redChess = new Chess(j, i, "red", "MA");                        this._chesses.push(redChess);                    } else if ((j == 2 && i == 0) || (j == 6 && i == 0)) {                        redChess = new Chess(j, i, "red", "XIANG");                        this._chesses.push(redChess);                    } else if ((j == 3 && i == 0) || (j == 5 && i == 0)) {                        redChess = new Chess(j, i, "red", "SHI");                        this._chesses.push(redChess);                    } else if ((j == 4 && i == 0)) {                        redChess = new Chess(j, i, "red", "JIANG");                        this._chesses.push(redChess);                    } else if ((j == 1 && i == 2) || (j == 7 && i == 2)) {                        redChess = new Chess(j, i, "red", "PAO");                        this._chesses.push(redChess);                    } else if ((j == 0 && i == 3) || (j == 2 && i == 3) || (j == 4 && i == 3) || (j == 6 && i == 3) || (j == 8 && i == 3)) {                        redChess = new Chess(j, i, "red", "BING");                        this._chesses.push(redChess);                    }                }            }            // 绘制黑色棋子            var blackChess;            for (var i = 6; i < 10; i++) {                for (var j = 0; j < 10; j++) {                    if ((j == 0 && i == 9) || (j == 8 && i == 9)) {                        blackChess = new Chess(j, i, "black", "CHE");                        this._chesses.push(blackChess);                    } else if ((j == 1 && i == 9) || (j == 7 && i == 9)) {                        blackChess = new Chess(j, i, "black", "MA");                        this._chesses.push(blackChess);                    } else if ((j == 2 && i == 9) || (j == 6 && i == 9)) {                        blackChess = new Chess(j, i, "black", "XIANG");                        this._chesses.push(blackChess);                    } else if ((j == 3 && i == 9) || (j == 5 && i == 9)) {                        blackChess = new Chess(j, i, "black", "SHI");                        this._chesses.push(blackChess);                    } else if (j == 4 && i == 9) {                        blackChess = new Chess(j, i, "black", "JIANG");                        this._chesses.push(blackChess);                    } else if ((j == 1 && i == 7) || (j == 7 && i == 7)) {                        blackChess = new Chess(j, i, "black", "PAO");                        this._chesses.push(blackChess);                    } else if ((j == 0 && i == 6) || (j == 2 && i == 6) || (j == 4 && i == 6) || (j == 6 && i == 6) || (j == 8 && (i == 6))) {                        blackChess = new Chess(j, i, "black", "BING");                        this._chesses.push(blackChess);                    }                }            }            //console.log(redChess);            //console.log(blackChess);            console.log(this._chesses);        },        /**         * 绘制棋子 车马相士将         * @private         */        _drawChesses: function () {            var isDeadChess = null;            // 根据游戏中棋子的数目来绘制棋子            // 游戏中的棋子始终是32颗, 因此只能根据棋子是否存活来决定是否绘制这个棋子(原来的位置还是有棋子, 这是让他隐藏起来)            for (var i = 0; i < this._chesses.length; i++) {                var chess = this._chesses[i];                // 原来的位置还是有棋子, 这是让他隐藏起来                if (!chess.isDead) {                    // 只有当这个棋子的属性isDead = false; 才绘制这个棋子                    // 根据棋子的属性来绘制                    context.fillStyle = "#C78843";                    context.beginPath();                    // 绘制棋子(注意要把棋子的初始位置复位)                    context.arc(chess.x * 60 + this._initX, chess.y * 60 + this._initY, 25, 0, Math.PI * 2, true);                    context.closePath();                    context.fill();                    // 绘制文本                    if (chess.color == "red") {                        context.fillStyle = 'red';                    }                    if (chess.color == "black") {                        context.fillStyle = 'black';                    }                    if (chess.color == "blue") {                        context.fillStyle = 'blue';                    }                    context.font = '43px 华文新魏';                    context.fillText(chess._getChessText(), chess.x * 60 + this._initX - 22, chess.y * 60 + this._initY + 10);                }                else {                    isDeadChess = chess;                }            }            // 有棋子被吃了,就重新开始            //this._selectedChess = null;            if (this._initCount == 0) {                //console.log(chess.x+","+chess.y+","+chess.type+"已经隐藏");            }        },        _drawChessboard: function () {            context.strokeStyle = "black";            // 绘制棋盘外边界            context.lineWidth = 3;            context.beginPath();            context.moveTo(0, 0);            context.lineTo(600, 0);            context.closePath();            context.stroke();            context.beginPath();            context.moveTo(0, 0);            context.lineTo(0, 660);            context.closePath();            context.stroke();            context.beginPath();            context.moveTo(600, 0);            context.lineTo(600, 660);            context.closePath();            context.stroke();            context.beginPath();            context.moveTo(0, 660);            context.lineTo(660, 660);            context.closePath();            context.stroke();            // 内部的外边界            context.beginPath();            context.moveTo(40, 40);            context.lineTo(40, 620);            context.closePath();            context.stroke();            context.beginPath();            context.moveTo(40, 40);            context.lineTo(560, 40);            context.closePath();            context.stroke();            context.beginPath();            context.moveTo(560, 40);            context.lineTo(560, 620);            context.closePath();            context.stroke();            context.beginPath();            context.moveTo(560, 620);            context.lineTo(40, 620);            context.closePath();            context.stroke();            //棋盘横线            context.lineWidth = 1;            for (var i = 1; i < 11; i++) {                context.beginPath();                context.moveTo(60, 60 * i);                context.lineTo(540, 60 * i);                context.closePath();                context.stroke();            }            // 棋盘纵线            for (var i = 1; i < 10; i++) {                context.beginPath();                context.moveTo(i * 60, 60);                context.lineTo(i * 60, 300);                context.closePath();                context.stroke();            }            for (var i = 1; i < 10; i++) {                context.beginPath();                context.moveTo(i * 60, 360);                context.lineTo(i * 60, 600);                context.closePath();                context.stroke();            }            context.beginPath();            context.moveTo(60, 300);            context.lineTo(60, 360);            context.closePath();            context.stroke();            context.beginPath();            context.moveTo(540, 300);            context.lineTo(540, 360);            context.closePath();            context.stroke();            // 棋盘斜线            context.beginPath();            context.moveTo(240, 60);            context.lineTo(360, 180);            context.closePath();            context.stroke();            context.beginPath();            context.moveTo(360, 60);            context.lineTo(240, 180);            context.closePath();            context.stroke();            context.beginPath();            context.moveTo(240, 480);            context.lineTo(360, 600);            context.closePath();            context.stroke();            context.beginPath();            context.moveTo(360, 480);            context.lineTo(240, 600);            context.closePath();            context.stroke();            // 绘制炮的位置(左上)            context.beginPath();            context.moveTo(115, 160);            context.lineTo(115, 175);            context.closePath();            context.stroke();            context.beginPath();            context.moveTo(115, 175);            context.lineTo(100, 175);            context.closePath();            context.stroke();            context.beginPath();            context.moveTo(125, 160);            context.lineTo(125, 175);            context.closePath();            context.stroke();            context.beginPath();            context.moveTo(125, 175);            context.lineTo(140, 175);            context.closePath();            context.stroke();            context.beginPath();            context.moveTo(115, 185);            context.lineTo(115, 200);            context.closePath();            context.stroke();            context.beginPath();            context.moveTo(115, 185);            context.lineTo(100, 185);            context.closePath();            context.stroke();            context.beginPath();            context.moveTo(125, 185);            context.lineTo(125, 200);            context.closePath();            context.stroke();            context.beginPath();            context.moveTo(125, 185);            context.lineTo(140, 185);            context.closePath();            context.stroke();            // 右上            context.beginPath();            context.moveTo(475, 175);            context.lineTo(460, 175);            context.closePath();            context.stroke();            context.beginPath();            context.moveTo(475, 175);            context.lineTo(475, 160);            context.closePath();            context.stroke();            context.beginPath();            context.moveTo(485, 160);            context.lineTo(485, 175);            context.closePath();            context.stroke();            context.beginPath();            context.moveTo(485, 175);            context.lineTo(500, 175);            context.closePath();            context.stroke();            context.beginPath();            context.moveTo(485, 185);            context.lineTo(485, 200);            context.closePath();            context.stroke();            context.beginPath();            context.moveTo(485, 185);            context.lineTo(500, 185);            context.closePath();            context.stroke();            context.beginPath();            context.moveTo(475, 185);            context.lineTo(475, 200);            context.closePath();            context.stroke();            context.beginPath();            context.moveTo(475, 185);            context.lineTo(460, 185);            context.closePath();            context.stroke();            // 左下            context.beginPath();            context.moveTo(115, 485);            context.lineTo(115, 500);            context.closePath();            context.stroke();            context.beginPath();            context.moveTo(115, 485);            context.lineTo(100, 485);            context.closePath();            context.stroke();            context.beginPath();            context.moveTo(115, 475);            context.lineTo(100, 475);            context.closePath();            context.stroke();            context.beginPath();            context.moveTo(115, 475);            context.lineTo(115, 460);            context.closePath();            context.stroke();            context.beginPath();            context.moveTo(125, 475);            context.lineTo(140, 475);            context.closePath();            context.stroke();            context.beginPath();            context.moveTo(125, 475);            context.lineTo(125, 460);            context.closePath();            context.stroke();            context.beginPath();            context.moveTo(125, 485);            context.lineTo(140, 485);            context.closePath();            context.stroke();            context.beginPath();            context.moveTo(125, 485);            context.lineTo(125, 500);            context.closePath();            context.stroke();            // 右下            context.beginPath();            context.moveTo(475, 485);            context.lineTo(475, 500);            context.closePath();            context.stroke();            context.beginPath();            context.moveTo(475, 485);            context.lineTo(460, 485);            context.closePath();            context.stroke();            context.beginPath();            context.moveTo(475, 475);            context.lineTo(475, 460);            context.closePath();            context.stroke();            context.beginPath();            context.moveTo(475, 475);            context.lineTo(460, 475);            context.closePath();            context.stroke();            context.beginPath();            context.moveTo(485, 475);            context.lineTo(500, 475);            context.closePath();            context.stroke();            context.beginPath();            context.moveTo(485, 475);            context.lineTo(485, 460);            context.closePath();            context.stroke();            context.beginPath();            context.moveTo(485, 485);            context.lineTo(500, 485);            context.closePath();            context.stroke();            context.beginPath();            context.moveTo(485, 485);            context.lineTo(485, 500);            context.closePath();            context.stroke();        },        _drawnTitle: function () {            //context.clearRect(0, 0, canvas.width, canvas.height);            context.fillStyle = 'black';            context.font = '40px 华文新魏';            context.fillText("楚河", 130, 340);            context.fillText("汉界", 380, 340);        },        _start: function () {            // 监听事件, 把触发这个事件的对象也传递过去            document.addEventListener("click", this._mouseClick.bind(this));            var that = this;            // 利用定时器不断重绘canvas            var timer = setInterval(function () {                that._draw();            }, 30);        },        _draw: function () {            context.clearRect(0, 0, canvas.width, canvas.height);            this._drawChessboard();            // 绘制棋子            this._drawChesses();            this._drawnTitle();        },        _mouseClick: function (e) {            // 把棋盘归一化            var px = e.clientX - this._initX + 25;            var py = e.clientY - this._initY + 25;            //console.log(px + " "+py);            // 当前鼠标点击棋盘的位置            var x = parseInt(px / 60);            var y = parseInt(py / 60);            if (x > 8 || x < 0 || y > 9 || y < 0 || px < 0) {                return;            }            console.log(this._selectedChess);            // 之前没有选中棋子(一直点击的是空白位置)            if (this._selectedChess == null) {                //如果当前鼠标点击的位置有棋子,就是选中了棋子                for (var i = 0; i < this._chesses.length; i++) {                    var chess = this._chesses[i];                    // 每次拿出来棋子都要看一下这个棋子是不是还活着, 已经死了的棋子不处理                    if (!chess.isDead) {                        if (x == chess.x && y == chess.y) {                            // 如果有棋子                            this._selectedChess = chess;                            this._selectedChess.color = "blue";                            break;                        } else {                            // 没有棋子                            //alert("没有棋子");                            //break;                        }                    }                }            } else {                var color = this._selectedChess.chessColor;                var srcX = this._selectedChess.x;                var srcY = this._selectedChess.y;                var destX = x;                var destY = y;                this._canKill(srcX, srcY, destX, destY);                // 如果已经有了选择的棋子,就看这一次点击的位置有没有棋子                /*var chess = this._getChess(x, y);                if (chess){                    // 如果这个位置有棋子                    console.log("有棋子");                    if (chess.chessColor == this._selectedChess.chessColor){                        // 如果这两个棋子的颜色相同                        alert("请不要自相残杀!");                        //同一个棋子点击了两下就恢复初始状态                        //this._selectedChess = null;                        this._selectedChess.color = this._selectedChess.chessColor;                        this._selectedChess = null;                        return;                    }                    else {                        // 如果颜色不相同                        // 首先看一下这个棋子能不能移动                        var type = this._selectedChess.type;                        var srcX = this._selectedChess.x;                        var srcY = this._selectedChess.y;                        var destX = x;                        var destY = y;                        var color = this._selectedChess.chessColor;                        // 我们先来判断能不能移动棋子, 然后再来判断能不能吃子                        switch (type) {                            case "CHE":                                if (this._canMoveChe(color, srcX, srcY, destX, destY)) {                                    // 移动棋子                                    this._moveChess(srcX, srcY, destX, destY);                                    return;                                } else {                                    // 点击了颜色相同但是属性不同的其他棋子                                    alert("不能移动棋子!");                                    // 颜色相同的同类棋子就恢复初始状态                                    this._selectedChess.color = this._selectedChess.chessColor;                                    this._selectedChess = null;                                    return;                                }                                break;                            case "MA":                                if (this._canMoveMa(color, srcX, srcY, destX, destY)) {                                    // 移动棋子                                    this._moveChess(srcX, srcY, destX, destY);                                    return;                                } else {                                    // 点击了颜色相同但是属性不同的其他棋子                                    alert("不能移动棋子!");                                    // 颜色相同的同类棋子就恢复初始状态                                    this._selectedChess.color = this._selectedChess.chessColor;                                    this._selectedChess = null;                                    return;                         &n
10-13 19:02