前段时间很想做一个五子棋,就和我们老大讨论相关的算法与规则,了解过后,才发觉,原来一个五子棋的水也很深,这时我们老大建议我做个黑白棋先试试,然后就有了这么个东西。

 

废话不多说,效果图如下:

1、结构

功能采用html+css+jquery进行编写。

index.html页面用于存储页面布局与样式。

/images文件夹用于存储棋子图片。

/js文件夹用于存放功能js代码(/js/index.js)与jquery(jquery-1.8.3.min.js)

 

2、html页面(index.html)

css代码如下:

<style>
        .main {
            width: 340px;
            height: 340px;
            padding-top: 10px;
            padding-left: 10px;
            background-color: #f6f5f5;
            float:left;
        }

        .lattice {
            display: table-cell;
            vertical-align:middle;
            text-align:center;
            width: 40px;
            height: 40px;
            float: left;
            cursor:pointer;
        }

        .lattice span {
            height:100%;
            display:inline-block;
            vertical-align:middle;
        }

        .lattice img {
            vertical-align:middle;
        }
        .latticeLeft {
            border-left: 1px solid #b1b0b0;
            border-top: 1px solid #b1b0b0;
        }

        .latticeRight {
            border-right: 1px solid #b1b0b0;
        }

        .latticeBottom {
            border-bottom: 1px solid #b1b0b0;
        }
    </style>

 

类样式(main)为棋盘样式,类样式(lattice)为格子样式,span与img的作用是控制图片居中,类样式(latticeLeft)为左边框样式,类样式(latticeRight)为右边框样式,类样式(latticeBottom)为底边框样式。

 

js引用代码如下:

<script src="js/jquery-1.8.3.min.js"></script>
<script src="js/index.js"></script>

 

 

body代码如下:

<div class="main">
        <div class="lattice latticeLeft">
            <span></span><img src=""/>
        </div>
        <div class="lattice latticeLeft">
            <span></span><img src=""/>
        </div>
        <div class="lattice latticeLeft">
            <span></span><img src=""/>
        </div>
        <div class="lattice latticeLeft">
            <span></span><img src=""/>
        </div>
        <div class="lattice latticeLeft">
            <span></span><img src=""/>
        </div>
        <div class="lattice latticeLeft">
            <span></span><img src=""/>
        </div>
        <div class="lattice latticeLeft">
            <span></span><img src=""/>
        </div>
        <div class="lattice latticeLeft latticeRight">
            <span></span><img src=""/>
        </div>

        <div class="lattice latticeLeft">
            <span></span><img src=""/>
        </div>
        <div class="lattice latticeLeft">
            <span></span><img src=""/>
        </div>
        <div class="lattice latticeLeft">
            <span></span><img src=""/>
        </div>
        <div class="lattice latticeLeft">
            <span></span><img src=""/>
        </div>
        <div class="lattice latticeLeft">
            <span></span><img src=""/>
        </div>
        <div class="lattice latticeLeft">
            <span></span><img src=""/>
        </div>
        <div class="lattice latticeLeft">
            <span></span><img src=""/>
        </div>
        <div class="lattice latticeLeft latticeRight">
            <span></span><img src=""/>
        </div>

        <div class="lattice latticeLeft">
            <span></span><img src=""/>
        </div>
        <div class="lattice latticeLeft">
            <span></span><img src=""/>
        </div>
        <div class="lattice latticeLeft">
            <span></span><img src=""/>
        </div>
        <div class="lattice latticeLeft">
            <span></span><img src=""/>
        </div>
        <div class="lattice latticeLeft">
            <span></span><img src=""/>
        </div>
        <div class="lattice latticeLeft">
            <span></span><img src=""/>
        </div>
        <div class="lattice latticeLeft">
            <span></span><img src=""/>
        </div>
        <div class="lattice latticeLeft latticeRight">
            <span></span><img src=""/>
        </div>

        <div class="lattice latticeLeft">
            <span></span><img src=""/>
        </div>
        <div class="lattice latticeLeft">
            <span></span><img src=""/>
        </div>
        <div class="lattice latticeLeft">
            <span></span><img src=""/>
        </div>
        <div class="lattice latticeLeft">
            <span></span><img src="images/black.png"/>
        </div>
        <div class="lattice latticeLeft">
            <span></span><img src="images/white.png" />
        </div>
        <div class="lattice latticeLeft">
            <span></span><img src=""/>
        </div>
        <div class="lattice latticeLeft">
            <span></span><img src=""/>
        </div>
        <div class="lattice latticeLeft latticeRight">
            <span></span><img src=""/>
        </div>

        <div class="lattice latticeLeft">
            <span></span><img src=""/>
        </div>
        <div class="lattice latticeLeft">
            <span></span><img src=""/>
        </div>
        <div class="lattice latticeLeft">
            <span></span><img src=""/>
        </div>
        <div class="lattice latticeLeft">
            <span></span><img src="images/white.png" />
        </div>
        <div class="lattice latticeLeft">
            <span></span><img src="images/black.png"/>
        </div>
        <div class="lattice latticeLeft">
            <span></span><img src=""/>
        </div>
        <div class="lattice latticeLeft">
            <span></span><img src=""/>
        </div>
        <div class="lattice latticeLeft latticeRight">
            <span></span><img src=""/>
        </div>

        <div class="lattice latticeLeft">
            <span></span><img src=""/>
        </div>
        <div class="lattice latticeLeft">
            <span></span><img src=""/>
        </div>
        <div class="lattice latticeLeft">
            <span></span><img src=""/>
        </div>
        <div class="lattice latticeLeft">
            <span></span><img src=""/>
        </div>
        <div class="lattice latticeLeft">
            <span></span><img src=""/>
        </div>
        <div class="lattice latticeLeft">
            <span></span><img src=""/>
        </div>
        <div class="lattice latticeLeft">
            <span></span><img src=""/>
        </div>
        <div class="lattice latticeLeft latticeRight">
            <span></span><img src=""/>
        </div>

        <div class="lattice latticeLeft">
            <span></span><img src=""/>
        </div>
        <div class="lattice latticeLeft">
            <span></span><img src=""/>
        </div>
        <div class="lattice latticeLeft">
            <span></span><img src=""/>
        </div>
        <div class="lattice latticeLeft">
            <span></span><img src=""/>
        </div>
        <div class="lattice latticeLeft">
            <span></span><img src=""/>
        </div>
        <div class="lattice latticeLeft">
            <span></span><img src=""/>
        </div>
        <div class="lattice latticeLeft">
            <span></span><img src=""/>
        </div>
        <div class="lattice latticeLeft latticeRight">
            <span></span><img src=""/>
        </div>

        <div class="lattice latticeLeft latticeBottom">
            <span></span><img src=""/>
        </div>
        <div class="lattice latticeLeft latticeBottom">
            <span></span><img src=""/>
        </div>
        <div class="lattice latticeLeft latticeBottom">
            <span></span><img src=""/>
        </div>
        <div class="lattice latticeLeft latticeBottom">
            <span></span><img src=""/>
        </div>
        <div class="lattice latticeLeft latticeBottom">
            <span></span><img src=""/>
        </div>
        <div class="lattice latticeLeft latticeBottom">
            <span></span><img src=""/>
        </div>
        <div class="lattice latticeLeft latticeBottom">
            <span></span><img src=""/>
        </div>
        <div class="lattice latticeLeft latticeRight latticeBottom">
            <span></span><img src=""/>
        </div>
    </div>
    <div style="position:relative;left:20px;width:200px;height:100%;float:left;border:1px solid #808080;padding-left:10px;">
        <br />
        <br />
        等待落子:<label id="lblText">请点击开始</label>
        <br />
        <br />
        黑子:<label id="lblcurrent1Num">2</label><br />
        <br />
        白子:<label id="lblcurrent2Num">2</label><br />
        <br />
        <button onclick="begin()">开始</button>&nbsp;&nbsp;<button onclick="reset()">重置</button>
        <br /><br /><br />
    </div>

 

html代码采用div进行布局,比较傻,其实可以使用js进行动态加载。

 

3、js部分(index.js)

通用变量部分,代码如下:

// 落子情况
var dataList = [
    [0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 1, 2, 0, 0, 0],
    [0, 0, 0, 2, 1, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0],
];// 1=黑棋 2=白棋
// 当前棋子
var current = 1;
// 当前黑子数
var current1Num = 2;
// 当前白子数
var current2Num = 2;
// 是否开始
var isBengin = false;

 

 

重置按钮事件,代码如下:

// 重置
function reset() {
    dataList = [
    [0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 1, 2, 0, 0, 0],
    [0, 0, 0, 2, 1, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0],
    ];
    var x = 0;
    var y = 0;
    var divList = document.getElementsByClassName("lattice");
    for (var i = 0; i < divList.length; i++) {
        x = $(divList[i]).attr("data-x");
        y = $(divList[i]).attr("data-y");
        if (x !=undefined && y != undefined && parseInt(dataList[y][x]) == 1) {
            $($(divList[i])).find("img").attr("src", "images/black.png");
        } else if (x != undefined && y != undefined && parseInt(dataList[y][x]) == 2) {
            $($(divList[i])).find("img").attr("src", "images/white.png");
        } else {
            $($(divList[i])).find("img").attr("src", "");
        }
    }
    isBengin = false;
}

 

处理流程,初始化棋子落点数组》清空落点棋子,这里还应该重置黑子落子数与白子落子数,并清空settimeout事件,这里未进行处理。

 

开始按钮点击事件,代码如下:

function begin() {
    isBengin = true;
    $("#lblText").text("玩家");
}

 

 

落点初始化点击事件与落点坐标,代码如下:

function init() {
    var x = 0;
    var y = 0;
    var divList = document.getElementsByClassName("lattice");
    for (var i = 0; i < divList.length; i++) {
        // 更新X轴值
        if (x == 8) {
            x = 0;
        }
        // 更新Y轴值
        if (x == 0 && i != 0) {
            y++;
        }

        $(divList[i]).attr("data-x", x);
        $(divList[i]).attr("data-y", y);
        $(divList[i]).attr("id", y + "_" + x);

        $(divList[i]).click(function () {
            if (!isBengin) {
                return;
            }

            // 验证当前位置是否有子
            if ($(this).find("img").attr("src").length > 0) {
                return;
            }
            // 获取当前x和y
            var thisX = parseInt($(this).attr("data-x"));
            var thisY = parseInt($(this).attr("data-y"));

            var arr = checkLegal(thisX, thisY);

            // 验证是否可以落子
            if (!checkIsLegal()) {
                current = current == 1 ? 2 : 1;
                $("#lblText").text("电脑");
                setTimeout(function () { AILegal(); }, 2000);
                return;
            }

            // 验证是否合法
            if (sumArray(arr) == 0) {
                return;
            }

            // 翻转棋子
            var rearr = SumTurn(thisX, thisY, arr);
            Turn(rearr);

            if (current == 1) {// 黑棋
                $(this).find("img").attr("src", "images/black.png");
                dataList[thisY][thisX] = current;
                current = 2;
            } else {// 白棋
                $(this).find("img").attr("src", "images/white.png");
                dataList[thisY][thisX] = current;
                current = 1;
            }
            sumNum();
            
            $("#lblText").text("电脑");
            setTimeout(function () { AILegal(); }, 2000);
        });

        x++;
    }
}

 

 

校验是否可进行落子,代码如下:

// 验证落子是否合法
function checkLegal(x, y) {
    var result = new Array();
    var isLegal = false;
    var isDuiFang = false;
    var i = y - 1;
    // 上
    for (; i >= 0; i--) {
        if (dataList[i][x] == 0) {
            break;
        }
        if (dataList[i][x] != current) {
            isDuiFang = true;
        }

        if (isDuiFang && dataList[i][x] == current) {
            isLegal = true;
            break;
        }
    }
    if (isLegal) {
        result.push(1);
    } else {
        result.push(0);
    }

    // 下
    isLegal = false;
    isDuiFang = false;
    i = y + 1;
    for (; i < 8; i++) {
        if (dataList[i][x] == 0) {
            break;
        }
        if (dataList[i][x] != current) {
            isDuiFang = true;
        }

        if (isDuiFang && dataList[i][x] == current) {
            isLegal = true;
            break;
        }
    }
    if (isLegal) {
        result.push(1);
    } else {
        result.push(0);
    }
    // 左
    isLegal = false;
    isDuiFang = false;
    i = x - 1;
    for (; i >= 0; i--) {
        if (dataList[y][i] == 0) {
            break;
        }
        if (dataList[y][i] != current) {
            isDuiFang = true;
        }

        if (isDuiFang && dataList[y][i] == current) {
            isLegal = true;
            break;
        }
    }
    if (isLegal) {
        result.push(1);
    } else {
        result.push(0);
    }
    // 右
    isLegal = false;
    isDuiFang = false;
    i = x + 1;
    for (; i < 8; i++) {
        if (dataList[y][i] == 0) {
            break;
        }
        if (dataList[y][i] != current) {
            isDuiFang = true;
        }

        if (isDuiFang && dataList[y][i] == current) {
            isLegal = true;
            break;
        }
    }
    if (isLegal) {
        result.push(1);
    } else {
        result.push(0);
    }
    // 左上
    isLegal = false;
    isDuiFang = false;
    i = y - 1;
    var j = x - 1;
    for (; i >= 0 && j >= 0; i--, j--) {
        if (dataList[i][j] == 0) {
            break;
        }
        if (dataList[i][j] != current) {
            isDuiFang = true;
        }

        if (isDuiFang && dataList[i][j] == current) {
            isLegal = true;
            break;
        }
    }
    if (isLegal) {
        result.push(1);
    } else {
        result.push(0);
    }
    // 右上
    isLegal = false;
    isDuiFang = false;
    i = y - 1;
    var j = x + 1;
    for (; i >= 0 && j < 8; i--, j++) {
        if (dataList[i][j] == 0) {
            break;
        }
        if (dataList[i][j] != current) {
            isDuiFang = true;
        }

        if (isDuiFang && dataList[i][j] == current) {
            isLegal = true;
            break;
        }
    }
    if (isLegal) {
        result.push(1);
    } else {
        result.push(0);
    }
    // 左下
    isLegal = false;
    isDuiFang = false;
    i = y + 1;
    var j = x - 1;
    for (; i < 8 && j >= 0; i++, j--) {
        if (dataList[i][j] == 0) {
            break;
        }
        if (dataList[i][j] != current) {
            isDuiFang = true;
        }

        if (isDuiFang && dataList[i][j] == current) {
            isLegal = true;
            break;
        }
    }
    if (isLegal) {
        result.push(1);
    } else {
        result.push(0);
    }
    // 右下
    isLegal = false;
    isDuiFang = false;
    i = y + 1;
    var j = x + 1;
    for (; i < 8 && j < 8; i++, j++) {
        if (dataList[i][j] == 0) {
            break;
        }
        if (dataList[i][j] != current) {
            isDuiFang = true;
        }

        if (isDuiFang && dataList[i][j] == current) {
            isLegal = true;
            break;
        }
    }
    if (isLegal) {
        result.push(1);
    } else {
        result.push(0);
    }
    return result;
}
View Code

 

 

计算翻转位置,代码如下:

// 计算需要翻转位置
function SumTurn(x,y,arr) {
    var isDuiFang = false;
    var xArr = new Array();
    var yArr = new Array();
    var currentArr = new Array();
    // 上
    if (arr[0] == 1) {
        for (var i = y-1; i >= 0; i--) {
            if (dataList[i][x] == 0) {
                break;
            }
            if (dataList[i][x] != current) {
                xArr.push(x);
                yArr.push(i);
                if (current == 1) {
                    currentArr.push(1);
                } else {
                    currentArr.push(2);
                }
                isDuiFang = true;
            }

            if (isDuiFang && dataList[i][x] == current) {
                break;
            }
        }
    }
    // 下
    isDuiFang = false;
    if (arr[1] == 1) {
        for (var i = y+1; i < 8; i++) {
            if (dataList[i][x] == 0) {
                break;
            }
            if (dataList[i][x] != current) {
                xArr.push(x);
                yArr.push(i);
                if (current == 1) {
                    currentArr.push(1);
                } else {
                    currentArr.push(2);
                }
                isDuiFang = true;
            }

            if (isDuiFang && dataList[i][x] == current) {
                break;
            }
        }
    }
    // 左
    isDuiFang = false;
    if (arr[2] == 1) {
        for (var i = x-1; i >= 0; i--) {
            if (dataList[y][i] == 0) {
                break;
            }
            if (dataList[y][i] != current) {
                xArr.push(i);
                yArr.push(y);
                if (current == 1) {
                    currentArr.push(1);
                } else {
                    currentArr.push(2);
                }
                isDuiFang = true;
            }

            if (isDuiFang && dataList[y][i] == current) {
                break;
            }
        }
    }
    // 右
    isDuiFang = false;
    if (arr[3] == 1) {
        for (var i = x+1; i < 8; i++) {
            if (dataList[y][i] == 0) {
                break;
            }
            if (dataList[y][i] != current) {
                xArr.push(i);
                yArr.push(y);
                if (current == 1) {
                    currentArr.push(1);
                } else {
                    currentArr.push(2);
                }
                isDuiFang = true;
            }

            if (isDuiFang && dataList[y][i] == current) {
                break;
            }
        }
    }
    // 左上
    isDuiFang = false;
    if (arr[4] == 1) {
        for (var i = y-1, j = x-1; i >= 0 && j >= 0; i--, j--) {
            if (dataList[i][j] == 0) {
                break;
            }
            if (dataList[i][j] != current) {
                xArr.push(j);
                yArr.push(i);
                if (current == 1) {
                    currentArr.push(1);
                } else {
                    currentArr.push(2);
                }
                isDuiFang = true;
            }

            if (isDuiFang && dataList[i][j] == current) {
                break;
            }
        }
    }
    // 右上
    isDuiFang = false;
    if (arr[5] == 1) {
        for (var i = y-1, j = x+1; i >= 0 && j < 8; i--, j++) {
            if (dataList[i][j] == 0) {
                break;
            }
            if (dataList[i][j] != current) {
                xArr.push(j);
                yArr.push(i);
                if (current == 1) {
                    currentArr.push(1);
                } else {
                    currentArr.push(2);
                }
                isDuiFang = true;
            }

            if (isDuiFang && dataList[i][j] == current) {
                break;
            }
        }
    }
    // 左下
    isDuiFang = false;
    if (arr[6] == 1) {
        for (var i = y+1, j = x-1; i < 8 && j >= 0; i++, j--) {
            if (dataList[i][j] == 0) {
                break;
            }
            if (dataList[i][j] != current) {
                xArr.push(j);
                yArr.push(i);
                if (current == 1) {
                    currentArr.push(1);
                } else {
                    currentArr.push(2);
                }
                isDuiFang = true;
            }

            if (isDuiFang && dataList[i][j] == current) {
                break;
            }
        }
    }
    // 右下
    isDuiFang = false;
    if (arr[7] == 1) {
        for (var i = y+1, j = x+1; i < 8 && j < 8; i++, j++) {
            if (dataList[i][j] == 0) {
                break;
            }
            if (dataList[i][j] != current) {
                xArr.push(j);
                yArr.push(i);
                if (current == 1) {
                    currentArr.push(1);
                } else {
                    currentArr.push(2);
                }
                isDuiFang = true;
            }

            if (isDuiFang && dataList[i][j] == current) {
                break;
            }
        }
    }

    var result = new Array();
    result.push(xArr);
    result.push(yArr);
    result.push(currentArr);
    return result;
}
View Code

 

 

翻转棋子,代码如下:

// 翻转棋子
function Turn(arr) {
    var xArr = arr[0];
    var yArr = arr[1];
    var currentArr = arr[2];
    for (var n = 0; n < xArr.length; n++) {
        if (currentArr[n] == 1) {
            $("#" + yArr[n] + "_" + xArr[n]).find("img").attr("src", "images/black.png");
            dataList[yArr[n]][xArr[n]] = 1;
        } else {
            $("#" + yArr[n] + "_" + xArr[n]).find("img").attr("src", "images/white.png");
            dataList[yArr[n]][xArr[n]] = 2;
        }
    }
}

 

 

计算数组合计,通用方法,代码如下:

// 计算数组合计
function sumArray(arr) {
    var result = 0;
    for (var i = 0; i < arr.length; i++) {
        result += arr[i];
    }
    return result;
}

 

 

校验当前落子人是否可进行落子,代码如下:

// 验证当前需要落子人是否可以落子
function checkIsLegal() {
    for (var i = 0; i < dataList.length; i++) {
        for (var j = 0; j < dataList[i].length; j++) {
            var arr = checkLegal(j, i);
            // 验证是否合法
            if (sumArray(arr) > 0) {
                return true;
            }
        }
    }
    return false;
}

 

 

ai落子,代码如下:

// AI落子
function AILegal() {
    // 获取可以落子点
    var xArr = new Array();
    var yArr = new Array();
    var lArr = new Array();

    var WeightArr = new Array();
    var resultArr = new Array();

    // 初始化可以落子的位置
    for (var i = 0; i < dataList.length; i++) {
        for (var j = 0; j < dataList[i].length; j++) {
            if (dataList[i][j] == 0) {
                var arr = checkLegal(j, i);
                // 验证是否合法
                if (sumArray(arr) > 0) {
                    xArr.push(j);
                    yArr.push(i);
                    lArr.push(arr);

                    var result = SumTurn(j, i, arr);
                    WeightArr.push(result[0].length);
                    resultArr.push(result);
                }
            }
        }
    }

    // 计算权值最大
    var i_t = -1;
    var sumWeight=0;
    for (var i = 0; i < WeightArr.length; i++) {
        if (sumWeight < WeightArr[i]) {
            i_t = i;
            sumWeight = WeightArr[i];
        }
    }

    if (i_t >= 0) {
        Turn(resultArr[i_t]);

        // 验证是否可以落子
        if (!checkIsLegal()) {
            current = current == 1 ? 2 : 1;
            $("#lblText").text("玩家");
        }

        if (current == 1) {// 黑棋
            $("#" + yArr[i_t] + "_" + xArr[i_t]).find("img").attr("src", "images/black.png");
            dataList[yArr[i_t]][xArr[i_t]] = current;
            current = 2;
        } else {// 白棋
            $("#" + yArr[i_t] + "_" + xArr[i_t]).find("img").attr("src", "images/white.png");
            dataList[yArr[i_t]][xArr[i_t]] = current;
            current = 1;
        }
        sumNum();
        $("#lblText").text("玩家");
    }
}
View Code

 

这里,只进行了初级ai,如果有兴趣,其实可以增加权值,比如说普通点权值为1,占边为5,有兴趣可以一起讨论一下。

 

计算并展示落子数:

function sumNum() {
    current1Num = 0;
    current2Num = 0;
    // 计算当前落子
    for (var i = 0; i < dataList.length; i++) {
        for (var j = 0; j < dataList[i].length; j++) {
            if (parseInt(dataList[i][j]) == 1) {
                current1Num++;
            } else if (parseInt(dataList[i][j]) == 2) {
                current2Num++;
            }
        }
    }
    $("#lblcurrent1Num").text(current1Num);
    $("#lblcurrent2Num").text(current2Num);
}

 

 

4、总结

一个练手的东西,无聊的时候研究研究还是挺有意思的,功能上有很多可以完善完善,算法上也有很多不足,有人要是有好的想法,欢迎讨论。

 

下载附件