五子棋大战(人机)
<!DOCTYPE html> <html> <head> <title>五子棋</title> <style> #chess{ display:block; margin:50px auto; box-shadow: 2px 2px 2px #EFEFEF,5px 5px 5px #B9B9B9; } </style> </head> <body> <canvas id="chess" width="450px" height="450px"></canvas> <script type="text/javascript" src="js/script.js"></script> </body> </html>
先用html5元素构建一个棋盘。
var chess = document.getElementById('chess'); var context = chess.getContext('2d'); var logo = new Image(); logo.src = 'img/2.png'; //图片加载完成 logo.onload = function(){ //绘制图片 context.drawImage( logo, 0, 0, 450, 450); //绘制棋盘 goBang(); } //设置颜色 context.strokeStyle = '#AAA'; //绘制棋盘的方法 var goBang= function(){ context.strokeStyle = "#BFBFBF"; for (var i = 0; i < 15; i++) { context.moveTo(15 + i*30, 15); context.lineTo(15 + i*30, 435); context.moveTo(15, 15 + i*30); context.lineTo( 435,15 + i*30); context.stroke(); } }(); //棋子绘制 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,'#000'); gradient.addColorStop(1,'#666'); }else{ gradient.addColorStop(0,'#DDD'); gradient.addColorStop(1,'#FFF'); } //填充颜色设置 context.fillStyle = gradient; //执行绘制操作(填充) context.fill(); } //落子设置 默认黑棋 true 黑 false 白 var me = true; //存储棋盘交叉点坐标(二维数组) var chessBoard = []; for(var i=0; i<15; i++){ //第一维 数组 chessBoard[i] = []; for(var j=0; j<15; j++){ //坐标上存默认值 0 chessBoard[i][j] = 0; } } //赢法数组 三维数组 var wins = []; for(var i=0; i<15; i++){ //第一维数组 wins[i] = []; for(var j=0; j<15; j++){ //第二维数组 wins[i][j] = []; } } //赢法种类索引 var count = 0; //15*15 纵向赢法 165 种 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++; } } //15*15 横向赢法 165 种 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++; } } //15*15 斜向赢法 121 种 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++; } } //15*15 反斜向赢法 121 种 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++; } } //人的赢法统计数组 var myWin = []; //计算机的赢法统计数组 var computerWin = []; //表示棋有没有结束 var over = false; for(var i=0; i<count; i++){ myWin[i] = 0; computerWin[i] = 0; } chess.onclick = function(e){ //判断棋是否结束 if(over){ return; } //判断是否黑子下棋 if(!me){ return; } //事件兼容处理 var e = e || event; var x = e.offsetX; var y = e.offsetY; var i = Math.floor(x / 30); var j = Math.floor(y / 30); //如果该坐标没有落子才可以落子 if(chessBoard[i][j]==0){ oneStep(i, j, me); //如果落下的是黑子 在坐标存1 chessBoard[i][j] = 1; //赢法统计 for(var k=0; k<count; k++){ if(wins[i][j][k]){ myWin[k]++; //该赢法计算机不可能再赢了 computerWin[k] = 6; // if(myWin[k] == 5){ window.alert("you win"); over = true; } } } //如果赢法统计完成棋没有结束 if(!over){ computerAI(); me = !me; } } } //计算机下棋 var computerAI = function(){ //记录人下的棋子 var myScore = []; //记录计算机下的棋子 var computerScore = []; //保存最高分数 var max = 0; //最高分数点坐标 var maxX = 0,maxY = 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(chessBoard[i][j] == 0){ //遍历所有赢法 for(var k=0; k<count; k++){ //判断第K种赢法是否有价值 if(wins[i][j][k]){ //判断第K种赢发黑棋是否落子 //拦截价值判断 if(myWin[k] == 1){ //拦截 myScore[i][j] += 200; }else if(myWin[k] == 2){ //拦截 myScore[i][j] += 8000; }else if(myWin[k] == 3){ //拦截 myScore[i][j] += 30000; }else if(myWin[k] == 4){ //拦截 myScore[i][j] += 50000; } //计算机本身落子价值判断 if(computerWin[k] == 1){ //落子价值 computerScore[i][j] += 300; }else if(computerWin[k] == 2){ //落子价值 computerScore[i][j] += 600; }else if(computerWin[k] == 3){ //落子价值 computerScore[i][j] += 40000; }else if(computerWin[k] == 4){ //落子价值 computerScore[i][j] += 100000; } } } //存储最高分数 if(myScore[i][j] > max){ max = myScore[i][j]; maxX = i; maxY = j; }else if(myScore[i][j] == max){ if(computerScore[i][j] > computerScore[maxX][maxY]){ maxX = i; maxY = j; } } //存储最高分数 if(computerScore[i][j] > max){ max = computerScore[i][j]; maxX = i; maxY = j; }else if(computerScore[i][j] == max){ if(myScore[i][j] > myScore[maxX][maxY]){ maxX = i; maxY = j; } } } } } //计算机子 oneStep(maxX, maxY, false); chessBoard[maxX][maxY] = 2; console.dir(chessBoard[maxX][maxY]); //赢法统计 for(var k=0; k<count; k++){ if(wins[maxX][maxY][k]){ //白子赢法更近一步 computerWin[k]++; //该赢法黑棋不可能再赢了 myWin[k] = 6; // if(computerWin[k] == 5){ window.alert("computer win"); over = true; } } } //如果赢法统计完成棋没有结束 if(!over){ me = !me; } }
棋盘的背景图片没有传上来,不需要或是报错删掉此函数重新创建函数即可。
案例是我学习算法计算时在某网站看到的,觉得有趣,无聊时可以自娱自乐打发时间便写下了。
悟已往之不谏,知来者之可追。实迷途其未远,觉今是而昨非。