代码拉取完成,页面将自动刷新
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>五子棋</title>
</head>
<body>
<!--棋盘层-->
<canvas id="gobangBase" width="1200px" height="800px" style="position: absolute;"></canvas>
<!--棋子层-->
<canvas id="gobangPice" width="1200px" height="800px" style="position: absolute;"></canvas>
<!--交互层-->
<canvas id="gobangActi" width="1200px" height="800px" style="position: absolute;"></canvas>
</body>
<script>
//游戏基本架构
var gbb = gobangBase.getContext("2d");
var gbp = gobangPice.getContext("2d");
var gba = gobangActi.getContext("2d");
var gbm = [];
var isEnd = 0;
var pices = [2, [], [] ];
//玩家使用的棋子
var player = 2;
function isEmpty(x, y) {
//判断该位置是否有棋子
return isEnd == 0 && gbm[x] && gbm[x][y] == 0;
}
function trans(X) {
//坐标转换为像素坐标
return 25 + 50 * X;
}
function toX(P) {
//像素坐标转换为坐标
return Math.round((P - 25) / 50);
}
function drawBase() {
//绘制棋盘
//画线
for (let i = 0; i < 16; i++) {
gbb.moveTo(25, trans(i));
gbb.lineTo(775, trans(i));
gbb.moveTo(trans(i), 25);
gbb.lineTo(trans(i), 775);
//小黑点
if (i == 7 || i == 3 || i == 12) {
gbb.fillRect(trans(i) - 5, trans(i) - 5, 10, 10);
if (i != 7) {
gbb.fillRect(trans(i) - 5, trans(15 - i) - 5, 10, 10);
}
}
}
gbb.stroke();
//初始化棋盘数组
var row = [];
for (let i = 0; i < 16; i++) {
row.push(0);
}
for (let i = 0; i < 16; i++) {
gbm.push([].concat(row));
}
}
drawBase();
var old = [0, 0];
gobangActi.onmousemove = (e) => {
//棋盘内移动时,绘制定位光标
let x = toX(e.clientX);
let y = toX(e.clientY);
if (isEnd == 0) {
gba.clearRect(trans(old[0]) - 15, trans(old[1]) - 15, 30, 30);
}
if (isEmpty(x, y)) {
gba.strokeRect(trans(x) - 10, trans(y) - 10, 20, 20);
old = [x, y];
}
}
gobangActi.onclick = (e) => {
if (pices[0] == player) {
let x = toX(e.clientX);
let y = toX(e.clientY);
if(isEmpty(x,y)){
drawPice(x, y, pices[0]);
setTimeout(() => {
gbAi(gbm, pices, player == 1 ? 2 : 1, drawPice);
}, 10);
}
}
}
function drawArea(x,y){
gbp.strokeStyle = "#F00";
gbp.strokeRect(trans(x) - 15, trans(y) - 15,30,30);
gbp.strokeStyle = "#000";
}
function drawPice(x, y, pice) {
//绘制棋子
if (isEmpty(x, y)) {
gba.clearRect(trans(old[0]) - 15, trans(old[1]) - 15, 30, 30);
let p = pice == 1 ? 2 : 1;
let len = pices[p].length - 1;
if (len > -1) {
gba.clearRect(trans(pices[p][len][0]) - 30, trans(pices[p][len][1]) - 30, 60, 60);
}
gbp.fillStyle = "#000";
gbp.beginPath();
gbp.arc(trans(x), trans(y), 20, 0, 2 * Math.PI);
gbp.fill();
//白棋
if (pice == 1) {
gbp.fillStyle = "#FFF";
gbp.beginPath();
gbp.arc(trans(x), trans(y), 18, 0, 2 * Math.PI);
gbp.fill();
}
gbm[x][y] = pice;
pices[pice].push([x, y]);
gba.strokeRect(trans(x) - 25, trans(y) - 25, 50, 50);
pices[0] = pice == 1 ? 2 : 1;
checkWin(x, y);
}
}
function drawWin(x1, y1, x2, y2) {
//游戏结束
let s = 1;
let e = 2;
if (x1 == x2) {
if (y1 > y2) {
s = 0;
e = 1;
}
} else if (y1 == y2) {
if (x1 > x2) {
s = 1.5;
e = 0.5;
} else {
s = 0.5;
e = 1.5;
}
} else if (x1 > x2) {
if (y1 > y2) {
s = 1.75;
e = 0.75;
} else {
s = 1.25;
e = 0.25;
}
} else {
if (y1 > y2) {
s = 0.25;
e = 1.25;
} else {
s = 0.75;
e = 1.75;
}
}
let p = pices[0] == 1 ? 2 : 1;
let len = pices[p].length - 1;
if (len > -1) {
gba.clearRect(trans(pices[p][len][0]) - 30, trans(pices[p][len][1]) - 30, 60, 60);
}
gba.lineWidth = 3;
gba.strokeStyle = "#F00";
gba.beginPath();
gba.arc(trans(x1), trans(y1), 22, s * Math.PI, e * Math.PI);
gba.arc(trans(x2), trans(y2), 22, e * Math.PI, s * Math.PI);
gba.arc(trans(x1), trans(y1), 22, s * Math.PI, s * Math.PI);
gba.stroke();
gba.strokeStyle = "#000";
isEnd = 1;
gba.lineWidth = 1;
playWin();
}
function playWin() {
//播放结果动画
let start = 0;
let w = 60;
let h = 10;
gba.clearRect(trans(old[0]) - 15, trans(old[1]) - 15, 30, 30);
let loop = () => {
start += 1;
let x = 1000 - (w / 2 + start);
let y = 125 - (h + start) / 2;
gba.fillStyle = "#000";
gba.fillRect(x, y, w + start * 2, h + start);
gba.fillStyle = "#FFF";
gba.fillRect(x + 3, y + 3, (w - 6) + start * 2, (h - 6) + start);
if (start < 100) {
setTimeout(function() {
loop();
}, 2);
} else {
gba.font = "45px Arial";
if (pices[0] == 2) {
gba.strokeText("白棋获胜", x + 36, y + 70);
} else {
gba.strokeText("黑棋获胜", x + 36, y + 70);
}
}
}
loop();
}
function checkWin(x, y) {
//游戏结束检测
let p = gbm[x][y];
let count = 0;
let e = [x, y];
let ways = [
[[1,0],[-1,0]],
[[0,1],[0,-1]],
[[1,1],[-1,-1]],
[[1,-1],[-1,1]]
];
for(let i = 0; i < 4; i++) {
let way = ways[i];
let res = counter(gbm,p,x,y,way[0][0],way[0][1],0,4);
if(res[0] == 4){
drawWin(x,y,res[1],res[2]);
return;
}
e = [res[1],res[2]];
res = counter(gbm,p,x,y,way[1][0],way[1][1],0,4);
if((res[0] + count) >= 4){
drawWin(e[0],e[1],res[1] - (res[0] + count - 4) * way[1][0],res[2] - (res[0] + count - 4) * way[1][1]);
return;
}
}
}
function counter(m,t,x,y,xw,yw,z,c){
//方向计数器 m 地图数组 t 目标值 x,y 起点坐标 xw,yw 坐标前进方向 z 允许空格数 c 检测格数
let count = 0;
let ex = -1;
let ey = -1;
let end = -1;
for(let i = 1; i <= c; i++ ){
ex = x+xw*i;
ey = y+yw*i;
if(m[x+xw*i]){
let n = m[x+xw*i][y+yw*i];
end = n;
if(n == t){
count++;
}else if( n == 0 && z > 0){
z--;
}else{
ex = x+xw*(i-1);
ey = y+yw*(i-1);
break;
}
}else{
ex = x+xw*(i-1);
ey = y+yw*(i-1);
break;
}
}
return [count,ex,ey,end];
}
</script>
<script>
//五子棋AI
function gbAi(map, pices, t, drawPice){
let coor = GbGen.desition(map,t,pices[t],pices[t == 1 ? 2 : 1]);
drawPice(coor[0],coor[1],t);
}
var GbGen = {
gen:[[5,10],[100,1000],[1000,10000],[500000,0]],
desition:function(map, t, p1, p2) {
let coor = [7,7];
let ways = [ [1,0],[-1,0], [0,1],[0,-1], [1,1],[-1,-1], [1,-1],[-1,1] ];
let m = {};
let set = {};
for(let pi in p1) {
let p = p1[pi];
for(let i = 1; i < 3; i++) {
for(let wi in ways) {
let w = ways[wi];
let x = p[0] + i * w[0];
let y = p[1] + i * w[1];
if(x < 0 || x > 15 || y < 0 || y > 15) {
continue;
}
let n = [x,y].join(",");
if( map[x][y] == 0 && !m[n]) {
let s = this.denfen(map,t,x,y);
m[n] = s + 1;
}
}
}
}
for(let pi in p2) {
let p = p2[pi];
for(let i = 1; i < 3; i++) {
for(let wi in ways) {
let w = ways[wi];
let x = p[0] + i * w[0];
let y = p[1] + i * w[1];
if(x < 0 || x > 15 || y < 0 || y > 15) {
continue;
}
let n = [x,y].join(",");
if( map[x][y] == 0 && !set[n] ) {
set[n]=true;
let s = this.denfen(map,t == 1 ? 2 : 1,x,y);
if(m[n]) {
m[n] += s;
}else {
m[n] = s;
}
}
}
}
}
set = [];
let max = 0;
for(let k in m) {
if(m[k] > max) {
set = [k];
max = m[k];
}else if(m[k] == max){
set.push(k);
}
}
if(set.length > 0) {
let ps = set[parseInt(Math.random()*set.length)];
ps = ps.split(",");
coor = [parseInt(ps[0]),parseInt(ps[1])];
}
return coor;
},denfen:function(map, t, x, y) {
let polet = 0;
let ways = [
[[1,0],[-1,0]],
[[0,1],[0,-1]],
[[1,1],[-1,-1]],
[[1,-1],[-1,1]]
];
for(let i = 0; i < 4; i++) {
let count = 0;
let way = ways[i];
let res1 = counter(map,t,x,y,way[0][0],way[0][1],0,4);
let res2 = counter(map,t,x,y,way[1][0],way[1][1],0,4);
count = res1[0] + res2[0];
if(count >= 4) {
polet+= this.gen[3][0];
}else {
let zp = 0;
if(res1[3] == 0) {
zp++;
}
if(res2[3] == 0) {
zp++;
}
if(zp > 0 && count > 0) {
polet+= this.gen[count-1][zp - 1];
}
}
}
return polet;
}
}
</script>
</html>
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。