html五子棋游戏,HTML5-右脑开发项目-小游戏-五子棋gobang.html

五子棋gobang.html

手机-五子棋

canvas{

display: block;

margin: 20px auto;

background-color:burlywood;

box-shadow: -2px -2px 2px #EFEFEF, 5px 5px 5px #B9B9B9;

}

.restart{

text-align: center;

}

.restart>span{

display: inline-block;

padding: 10px 20px;

color: #fff;

background-color: #45c01a;

border-radius: 5px;

}

//页面加载

$(document).ready(function(){

//画棋盘

drawChessboard();

/* canvas绑定点击事件 实现点击落子 */

chess.onclick = function(e) {

/* 如果棋局结束 点击不再产生效果 */

if(over){return;}

/* 如果没有轮到黑方行棋 点击不触发事件 (如需双人对战,则取消该判断与下方AI行棋方法) */

if (!me) {return;}

var x = e.offsetX; //点击位置横坐标

var y = e.offsetY; //点击位置纵坐标

var i = Math.floor(x / 20); //对应x坐标到棋盘所在交叉点

var j = Math.floor(y / 20); //对应y坐标到棋盘所在交叉点

/* 位置为空 可以落子 */

if (chessBoard[i][j] == 0) {

/* 落子 */

oneStep(i, j, me);

if (me) {

chessBoard[i][j] = 1; //黑方落子

} else {

chessBoard[i][j] = 2; //白方落子 -- 人机对战时 该行不会执行

}

/* 轮流落子 */

me = !me;

/* 落子完成之后 遍历所有赢法 */

for (var k = 0; k < count; k++) {

/* 包含落子点的赢法的统计数组 + 1 */

if(wins[i][j][k]){

BlackWin[k]++; //黑棋在第k种赢法中统计数字 + 1

WhiteWin[k] = 6; //同时白棋不可能以第k种赢法胜利

/* 胜利判断 */

if (BlackWin[k] == 5) {

window.alert("恭喜你,获得了胜利!");

over = true; //棋局结束

}

}

}

/* 如果棋局未结束 计算机AI自动执白行棋 */

if (!over) {

computerAI();

}

}

}

//点击‘重新开始’按钮

$("#restart").click(function(){

window.location.reload();

});

});

//画棋盘

function drawChessboard(){

/***** UI设计 -- 棋盘绘制 & 棋子绘制 & 落子动作 *****/

//获取Canvas面板

var chess = document.getElementById("chess");

//2D面板-画笔

var context = chess.getContext("2d");

//绘制棋盘

//线条颜色

context.strokeStyle = "black";

for (var i = 0; i < 15; i++) {

//横线

context.moveTo(15 + i * 20, 15);

context.lineTo(15 + i * 20, 295);

context.stroke();

//纵线

context.moveTo(15, 15 + i * 20);

context.lineTo(295, 15 + i * 20);

context.stroke();

}

//绘制棋盘上的5个标志点

context.beginPath();//开始绘制新路径

//arc(x, y, radius, startAngle, endAngle, counterclockwise):

//以(x,y)为圆心绘制一条弧线,弧线半径为radius,起始和结束角度(用弧度表示)分别为startAngle 和endAngle。最后一个参数表示startAngle 和endAngle 是否按逆时针方向计算,值为false表示按顺时针方向计算。

var number = 4;//圆半径

//中心点

context.arc(155,155,number,0,2*Math.PI);//参数1:左右移动;参数2:上下移动;参数3:大小;参数4:图形显示百分比

//左上点

context.arc(75,75,number,0,2*Math.PI);

//右下点

context.arc(235,235,number,0,2*Math.PI);

context.closePath();

context.fillStyle = 'red';

context.fill();

context.beginPath();//开始绘制新路径

//左下

context.arc(75,235,number,0,2*Math.PI);

//右上

context.arc(235,75,number,0,2*Math.PI);

context.closePath();

context.fillStyle = 'red';

context.fill();

}

/* 走棋 */

// param - i : 棋子落点第几行

// param - j : 棋子落点第几列

// param - me : 是否黑棋

function oneStep(i, j, me) {

/* 画圆(棋子) */

//获取Canvas面板

var chess = document.getElementById("chess");

//2D面板-画笔

var context = chess.getContext("2d");

context.beginPath();

context.arc(15 + i * 20, 15 + j * 20, 9, 0, 2 * Math.PI); //圆心x  圆心y  半径  弧度(起)  弧度(止)

context.closePath();

//context.stroke();//描边

//context.fill();//填充

/* 棋子颜色渐变 */

var gradient = context.createRadialGradient(15 + i * 20 + 2, 15 + j * 20 - 2, 9, 15 + i * 20 + 2, 15 + j * 20 - 2, 0); //外圆圆心坐标 半径, 内圆圆心坐标半径

if (me) {

//黑棋颜色

gradient.addColorStop(0, "#0A0A0A"); //外圆颜色 0代表百分比

gradient.addColorStop(1, "#636766"); //内圆颜色 1代表百分比

} else {

//白棋颜色

gradient.addColorStop(0, "#D1D1D1");

gradient.addColorStop(1, "#F9F9F9");

}

context.fillStyle = gradient;

context.fill();

}

/* 定义全局变量 me 代表黑白棋 */

var me = true; //默认黑棋先行

/* 定义全局变量 over 代表棋局是否结束 */

var over = false;

/* 定义全局二维数组并初始化 存储每个落子点的落子情况 */

var chessBoard = [];

for (var i = 0; i < 15; i++) {

chessBoard[i] = [];

for (var j = 0; j < 15; j++) {

chessBoard[i][j] = 0; // 0 未落子;1 黑子;2 白子

}

}

/* 定义全局变量 count 存储赢法ID */

var count = 0;

/* 定义全局三维数组 存储所有的赢法 并初始化 */

var wins = [];

for (var i = 0; i < 15; i++) {

wins[i] = [];

for (var j = 0; j < 15; j++) {

wins[i][j] = [];

}

}

/* 遍历所有赢法 填充赢法数组 */

/* 横向五子连线的情况 */

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++;

}

}

//console.log(count); //572 可知 15 * 15 的棋盘上 五子棋共有 572 种赢法

/* 定义全局一维数组 统计某种赢法下黑白棋子的状态 并初始化 */

var BlackWin = [];

var WhiteWin = [];

for (var i = 0; i < count; i++) {

BlackWin[i] = 0; // 0:未落子  1:落下1子 …… 5:胜利  6:异常 - 对方已经落子(此赢法为不可能)

WhiteWin[i] = 0; // 换句话说,当BlackWin和WhiteWin数组的所有值都为 6 时, 为和棋

}

/***** AI算法基本思路与实现 *****/

/* 1、计算机执白后行 */

/* 2、计算目标:阻止黑棋五子连线 && 试图白棋五子连线 */

/* 3、记录棋盘中可能出现的所有赢法。 三维数组(棋子x, 棋子y, 赢法ID) */

/* 4、赢法统计数组。 对每一种赢法的当前落子情况统计 */

/* 5、胜负判定 */

/* 6、计算机落子优先系数 */

/* 7、计算机执白后行,同情况下白棋优先级需要高于黑棋。 即黑白棋同时4子连线时,需优先连接白棋第5子而非拦截黑棋 */

/* 8、得分累加来判定某一点落子的价值大小*/

/* 9、获取落子价值得分最高的点 */

/* 10、落子的价值分相同时, 优先级顺序的选择:高 --> 低   行白+拦黑  >  行白  >  拦黑+行白  >  拦黑 */

/* AI算法实现 */

var computerAI = function(){

/* 定义变量 保存落子价值得分最高的分数和点坐标 */

var max = 0;

var u = 0;

var v = 0;

/* 定义两个一维数组 存储当前黑棋和白棋的落子评分 并初始化*/

var BlackScore = [];

var WhiteScore = [];

for (var i = 0; i < 15; i++) {

BlackScore[i] = [];

WhiteScore[i] = [];

for (var j = 0; j < 15; j++) {

BlackScore[i][j] = 0;

WhiteScore[i][j] = 0;

}

}

/* 评分方法 */

for (var i = 0; i < 15; i++) {

for (var j = 0; j < 15; j++) {

/* 该点无落子 */

if (chessBoard[i][j] == 0) {

/* 遍历所有赢法 */

for (var k = 0; k < count; k++) {

/* 对包含该点的赢法 所对应的赢法统计数组进行加分 -- 说明在该点落子是有价值的 */

if (wins[i][j][k]) {

/* 如果黑棋在这种赢法中已有1个落子 */

if (BlackWin[k] == 1) {

BlackScore[i][j] += 200;

/* 如果黑棋在这种赢法中已有2个落子 */

}else if (BlackWin[k] == 2) {

BlackScore[i][j] += 400;

/* 如果黑棋在这种赢法中已有3个落子 */

}else if (BlackWin[k] == 3) {

BlackScore[i][j] += 2000;

/* 如果黑棋在这种赢法中已有4个落子 */

}else if (BlackWin[k] == 4) {

BlackScore[i][j] += 10000;

}

/* 如果白棋在这种赢法中已有1个落子 */

if (WhiteWin[k] == 1) {

WhiteScore[i][j] += 220;

/* 如果白棋在这种赢法中已有2个落子 */

}else if (WhiteWin[k] == 2) {

WhiteScore[i][j] += 420;

/* 如果白棋在这种赢法中已有3个落子 */

}else if (WhiteWin[k] == 3) {

WhiteScore[i][j] += 2100;

/* 如果白棋在这种赢法中已有4个落子 */

}else if (WhiteWin[k] == 4) {

WhiteScore[i][j] += 20000;

}

}

}

/* 记录价值最高分和最高价值落子点坐标 */

/* 优先级问题  越靠后,优先级越高*/

/* 1、拦截黑棋 */

if (BlackScore[i][j] > max) {

max = BlackScore[i][j];

u = i;

v = j;

/* 2、当对黑棋的拦截价值分数相同时 优先选择在拦截基础上对白棋价值分更高的点位 */

}else if(BlackScore[i][j] == max){

if (WhiteScore[i][j] > WhiteScore[u][v]) {

u = i;

v = j;

}

}

/* 3、当行白棋和拦截黑棋价值分相同时,优先行走白棋*/

if (WhiteScore[i][j] > max) {

max = WhiteScore[i][j];

u = i;

v = j;

/* 4、当多个行走白棋的方案价值分相同时,优先选择在行走白棋基础上对黑棋拦截价值分更高的点位 */

}else if(WhiteScore[i][j] == max){

if (BlackScore[i][j] > BlackScore[u][v]) {

u = i;

v = j;

}

}

}

}

}

/* 计算机AI计算完毕 落子 */

oneStep(u, v, false);

/* 改变落子点状态 */

chessBoard[u][v] = 2; //白棋落子

/* 胜负判定*/

for (var k = 0; k < count; k++) {

if (wins[u][v][k]) {

/* 白棋在该赢法下胜利系数 + 1 */

WhiteWin[k]++;

/* 黑棋不可能在该赢法下胜利 */

BlackScore[k] = 6;

if (WhiteWin[k] == 5) {

window.alert("机器人获胜!");

over = true;

}

}

}

/* 如果未结束 改变落子方 */

if (!over) {

me = !me;

}

}

五子棋

五子棋游戏

重新开始

你可能感兴趣的:(html五子棋游戏)