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++) { // 将可能赢的情况都加1if (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++) { // 将可能赢的情况都减1if (wins[_nowi][_nowj][k]) {myWin[k]--;computerWin[k] = _compWin[k]; //这个位置对方可能赢}}// 计算机相应的悔棋chressBord[_compi][_compj] = 0; //计算机,已占位置 还原minusStep(_compi, _compj); //销毁棋子 for (var k = 0; k < count; k++) { // 将可能赢的情况都减1if (wins[_compi][_compj][k]) {computerWin[k]--;// 源代码中的BUG **** _myWin[k]中 i 改为 kmyWin[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++) { // 将可能赢的情况都减1if (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/181.html