五子棋 源码

15 篇文章 0 订阅
13 篇文章 0 订阅

JS 五子棋 带成绩排名

游戏:http://wx0725.top/index.php/181.html

主程序学习:https://blog.csdn.net/qq_44731019/article/details/109586730

  • 改了几个 BUG
  • 添加了成绩截图功能
  • 去掉了悔棋

在这里插入图片描述

自己看着重新写吧,下面代码只是一个思路,也有bug。。。

1. 源码

HTML

 <div class="row">
     <h3 id="result-wrap" style="color: red;"><img src="http://wx0725.top/image/black_qizi.png" alt=""></h3>
     <canvas id="chess" width="450px" height="450px"></canvas>
     <div class="btn-wrap">
         <div id='restart' class="restart">
             <span>重新开始</span>
         </div>
         <div id='goback' class="goback unable">
             <!-- <span>悔棋</span> -->
         </div>
         <div id='return' class="return unable">
             <!-- <span>撤销悔棋</span> -->
         </div>
     </div>
 </div>

Javascript

代码中有注释啊啊啊

var fail_text = '👏,计算机赢了,继续加油哦!';
var win_text = '恭喜,你赢了!😱';
var back_text = '只能撤销一步哦😂';
var winner = ""; // 假设胜利者是计算机
var over = false;
var me = true; //我
var _nowi = 0,
    _nowj = 0; //记录自己下棋的坐标
var _compi = 0,
    _compj = 0; //记录计算机当前下棋的坐标
var _myWin = [],
    _compWin = []; //记录我,计算机赢的情况
var backAble = false,
    returnAble = false;
var resultTxt = document.getElementById('result-wrap');
var chressBord = []; //棋盘,标记有没有棋子
for (var i = 0; i < 15; i++) {
    chressBord[i] = [];
    for (var j = 0; j < 15; j++) {
        chressBord[i][j] = 0;
    }
}
//每种赢法的统计数组
var myWin = [];
var computerWin = [];
//赢法数组
var wins = [];
for (var i = 0; i < 15; i++) {
    wins[i] = [];
    for (var j = 0; j < 15; j++) {
        wins[i][j] = [];
    }
}
var count = 0; //赢法总数
//横线赢法
for (var i = 0; i < 15; i++) {
    for (var j = 0; j < 11; j++) {
        for (var k = 0; k < 5; k++) {
            wins[i][j + k][count] = true;
        }
        count++;
    }
}
//竖线赢法
for (var i = 0; i < 15; i++) {
    for (var j = 0; j < 11; j++) {
        for (var k = 0; k < 5; k++) {
            wins[j + k][i][count] = true;
        }
        count++;
    }
}
//正斜线赢法
for (var i = 0; i < 11; i++) {
    for (var j = 0; j < 11; j++) {
        for (var k = 0; k < 5; k++) {
            wins[i + k][j + k][count] = true;
        }
        count++;
    }
}
//反斜线赢法
for (var i = 0; i < 11; i++) {
    for (var j = 14; j > 3; j--) {
        for (var k = 0; k < 5; k++) {
            wins[i + k][j - k][count] = true;
        }
        count++;
    }
}
// debugger;
for (var i = 0; i <= count; i++) {
    myWin[i] = 0;
    _myWin[i] = 0;
    computerWin[i] = 0;
    _compWin[i] = 0;
}

var chess = document.getElementById("chess");
var context = chess.getContext('2d');
context.strokeStyle = '#bfbfbf'; //边框颜色
var backbtn = document.getElementById("goback");
var returnbtn = document.getElementById("return");

document.getElementById("restart").onclick = function() {
    window.location.reload();
}

function save_chess() { // 发送棋谱截图
    // 截图发送
    var chessSrc = chess.toDataURL("image/png");
    var data = {
        function: "gobangSave",
        base64: chessSrc,
        city: address, // 地址和IP自己找,不需要可以去掉,记得后台代码做对应的修改,可以使用时间戳命名保存的图片名称
        ip: ip,
    };
    $.ajax({ // 提交截图
        url: "gobangSave.php", // 填写后台php的链接
        type: "post",
        data: data,
        async: true,
        success: function(e) {
        },
        error: function(e) {
        }
    })
}

function win_f() { // 我赢了
    resultTxt.innerHTML = win_text;
    over = true;
    var me_com = [0, 0, 0]; // 地图中 默认、我、计算机 分别占位的个数
    for (var i = 0; i < 15; i++) {
        for (var j = 0; j < 15; j++) {
            me_com[chressBord[i][j]]++;
        }
    }
    if (me_com[1] != me_com[2] + 1) {
        setTimeout(function() {
            alert("下棋成绩异常,如有问题请联系管理员或留言");
        }, 500);
        return;
    }
    winner = "me";
    setTimeout(function() {
        alert(win_text + " 您可以选择【重新开始】继续游戏!");
    }, 1000)
}

function fail_f() { // 计算机赢了
    resultTxt.innerHTML = fail_text;
    over = true;
    winner = "computer";
    setTimeout(function() {
        alert(fail_text + " 您可以选择【重新开始】继续游戏!");
    }, 1000)
}

function able_back() { // 允许悔棋
    backAble = true;
    backbtn.className = backbtn.className.replace(new RegExp("(\\s|^)unable(\\s|$)"), " ");
}

function unable_back() { // 不允许悔棋
    backAble = false;
    var hasClass = new RegExp('unable').test(' ' + backbtn.className + ' ');
    if (!hasClass) {
        backbtn.className += ' ' + 'unable';
    }
}

function able_return() { // 允许撤销悔棋
    returnAble = true;
    returnbtn.className = returnbtn.className.replace(new RegExp("(\\s|^)unable(\\s|$)"), " ");
}

function unable_return() { // 不允许撤销悔棋
    returnAble = false;
    var hasClass = new RegExp('unable').test(' ' + returnbtn.className + ' ');
    if (!hasClass) {
        returnbtn.className += ' ' + 'unable';
    }
}


// 我,下棋
chess.onclick = function(e) {
        if (over) {
            return;
        }
        if (!me) {
            return;
        }
        var x = e.offsetX;
        var y = e.offsetY;
        var i = Math.floor(x / 30);
        var j = Math.floor(y / 30);
        if (chressBord[i][j] == 0) {
            _nowi = i; // 源码中的BUG,这两行更新现在的位置需要放在if中,否则会在撤销的时候出现问题
            _nowj = j;
            oneStep(i, j, me);
            chressBord[i][j] = 1; //我,已占位置   

            for (var k = 0; k < count; k++) { // 将可能赢的情况都加1
                if (wins[i][j][k]) {
                    // debugger;
                    myWin[k]++;
                    _compWin[k] = computerWin[k];
                    computerWin[k] = 6; //这个位置对方不可能赢了
                    if (myWin[k] == 5) {
                        win_f();
                    }
                }
            }
            if (!over) { // 没结束计算机下棋
                me = !me;
                computerAI();
            } else {
                if (winner == "me") {
                    unable_back();
                    save_chess();
                }
            }
        }
    }
    // 悔棋
backbtn.onclick = function(e) {
        if (!backAble) {
            return;
        }
        over = false;
        me = true;
        // 我,悔棋
        chressBord[_nowi][_nowj] = 0; //我,已占位置 还原
        minusStep(_nowi, _nowj); //销毁棋子                                  
        for (var k = 0; k < count; k++) { // 将可能赢的情况都减1
            if (wins[_nowi][_nowj][k]) {
                myWin[k]--;
                computerWin[k] = _compWin[k]; //这个位置对方可能赢
            }
        }
        // 计算机相应的悔棋
        chressBord[_compi][_compj] = 0; //计算机,已占位置 还原
        minusStep(_compi, _compj); //销毁棋子                                  
        for (var k = 0; k < count; k++) { // 将可能赢的情况都减1
            if (wins[_compi][_compj][k]) {
                computerWin[k]--;
                // 源代码中的BUG **** _myWin[k]中 i 改为 k
                myWin[k] = _myWin[k]; //这个位置对方可能赢
            }
        }
        resultTxt.innerHTML = back_text;
        able_return(); // 允许撤销悔棋
        unable_back(); // 不允许悔棋
    }
    // 撤销悔棋
returnbtn.onclick = function(e) {
        if (!returnAble) {
            return;
        }
        // 我,撤销悔棋
        chressBord[_nowi][_nowj] = 1; //我,已占位置 
        oneStep(_nowi, _nowj, me);
        for (var k = 0; k < count; k++) {
            if (wins[_nowi][_nowj][k]) {
                myWin[k]++;
                _compWin[k] = computerWin[k];
                computerWin[k] = 6; //这个位置对方不可能赢
            }
        }
        // 计算机撤销相应的悔棋
        chressBord[_compi][_compj] = 2; //计算机,已占位置   
        oneStep(_compi, _compj, false);
        for (var k = 0; k < count; k++) { // 将可能赢的情况都减1
            if (wins[_compi][_compj][k]) {
                computerWin[k]++;
                _myWin[k] = myWin[k];
                myWin[k] = 6; //这个位置对方不可能赢
            }
        }
        able_back(); // 允许悔棋
        unable_return(); // 不允许撤销悔棋
    }
    // 计算机下棋
var computerAI = function() {
        var myScore = [];
        var computerScore = [];
        var max = 0;
        var u = 0,
            v = 0;
        for (var i = 0; i < 15; i++) {
            myScore[i] = [];
            computerScore[i] = [];
            for (var j = 0; j < 15; j++) {
                myScore[i][j] = 0;
                computerScore[i][j] = 0;
            }
        }
        for (var i = 0; i < 15; i++) {
            for (var j = 0; j < 15; j++) {
                if (chressBord[i][j] == 0) {
                    for (var k = 0; k < count; k++) {
                        if (wins[i][j][k]) {
                            if (myWin[k] == 1) {
                                myScore[i][j] += 200;
                            } else if (myWin[k] == 2) {
                                myScore[i][j] += 400;
                            } else if (myWin[k] == 3) {
                                myScore[i][j] += 2000;
                            } else if (myWin[k] == 4) {
                                myScore[i][j] += 10000;
                            }

                            if (computerWin[k] == 1) {
                                computerScore[i][j] += 220;
                            } else if (computerWin[k] == 2) {
                                computerScore[i][j] += 420;
                            } else if (computerWin[k] == 3) {
                                computerScore[i][j] += 2100;
                            } else if (computerWin[k] == 4) {
                                computerScore[i][j] += 20000;
                            }
                        }
                    }

                    if (myScore[i][j] > max) {
                        max = myScore[i][j];
                        u = i;
                        v = j;
                    } else if (myScore[i][j] == max) {
                        if (computerScore[i][j] > computerScore[u][v]) {
                            u = i;
                            v = j;
                        }
                    }

                    if (computerScore[i][j] > max) {
                        max = computerScore[i][j];
                        u = i;
                        v = j;
                    } else if (computerScore[i][j] == max) {
                        if (myScore[i][j] > myScore[u][v]) {
                            u = i;
                            v = j;
                        }
                    }

                }
            }
        }
        _compi = u;
        _compj = v;
        oneStep(u, v, false);
        chressBord[u][v] = 2; //计算机占据位置
        for (var k = 0; k < count; k++) {
            if (wins[u][v][k]) {
                computerWin[k]++;
                _myWin[k] = myWin[k];
                myWin[k] = 6; //这个位置对方不可能赢了
                if (computerWin[k] == 5) {
                    fail_f();
                }
            }
        }
        able_back(); // 确保我下棋并且计算机也下棋,才能允许悔棋
        unable_return();
        if (!over) { // 如果没有结束,换棋手
            me = !me;
        } else { // 如果结束了
            if (winner == "computer") unable_back();
        }
    }
    //绘画棋盘
var drawChessBoard = function() {
    for (var i = 0; i < 15; i++) {
        context.moveTo(15 + i * 30, 15);
        context.lineTo(15 + i * 30, 435);
        context.stroke();
        context.moveTo(15, 15 + i * 30);
        context.lineTo(435, 15 + i * 30);
        context.stroke();
    }
}
drawChessBoard(); // 画棋盘

//画棋子
var oneStep = function(i, j, me) {
        context.beginPath();
        context.arc(15 + i * 30, 15 + j * 30, 13, 0, 2 * Math.PI); // 画圆
        context.closePath();
        //渐变
        var gradient = context.createRadialGradient(15 + i * 30 + 2, 15 + j * 30 - 2, 13, 15 + i * 30 + 2, 15 + j * 30 - 2,
            0);
        if (me) {
            gradient.addColorStop(0, '#0a0a0a');
            gradient.addColorStop(1, '#636766');
        } else {
            gradient.addColorStop(0, '#d1d1d1');
            gradient.addColorStop(1, '#f9f9f9');
        }
        context.fillStyle = gradient;
        context.fill();
    }
    //销毁棋子
var minusStep = function(i, j) {
    //擦除该圆
    context.clearRect((i) * 30, (j) * 30, 30, 30);
    // 重画该圆周围的格子
    context.beginPath();
    context.moveTo(15 + i * 30, j * 30);
    context.lineTo(15 + i * 30, j * 30 + 30);
    context.moveTo(i * 30, j * 30 + 15);
    context.lineTo((i + 1) * 30, j * 30 + 15);

    context.stroke();
}

php 保存成绩

gobangSave.php

function gobangSave()
{ // 五子棋
    if ($_POST['base64'] != "" && $_POST['city'] != "" && $_POST['ip'] != "") {
        //接收base64数据
        $image = $_POST['base64'];
        if (preg_match('/^(data:\s*image\/(\w+);base64,)/', $image, $result)) {
            $name = $_POST["city"] . "-" . $_POST["ip"] .  "-" . time() . '.png';
            $imageName = "./wuziqi/" . $name;
            is_file($imageName) or fclose(fopen($imageName, 'w'));
            if (file_put_contents($imageName, base64_decode(str_replace($result[1], '', $image)))) {
                echo "成绩有效👍, 您的成绩已经展示在下方,刷新页面查看。";
            } else {
                echo "抱歉,文件写入有误,请联系管理员!";
            }
        } else {
            echo "抱歉,文件格式有误!";
        }
    } else {
        echo "抱歉,成绩无效。如有疑问请联系管理员或留言反馈!";
    }
}
$function = $_POST["function"];
if ($function == "gobangSave") {
    gobangSave();
} 

推荐:公众号能干吗?http://wx0725.top/index.php/archives/224/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

流星蝴蝶没有剑

篮球弹弹弹

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值