js实现五子棋人机对战源码

indexhtml

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>五子棋</title>
 6     <meta name="viewport" content="width=device-width"> <!-- 适应移动屏幕 -->
 7     <link rel="stylesheet" type="text/css" href="style.css">
 8 </head>
 9 <body>
10     <h1>五子棋人机对战版</h1>
11     
12     <canvas id="chess" width="450px" height="450px">
13     </canvas>
14     <div id="restart">
15         <span>重新开始</span>
16     </div>
17     <!-- <script type="text/javascript" src="script.js"></script> --> <!-- 未封装版本 -->
18     <script type="text/javascript" src="gobang.js"></script>  <!-- 封装版本 -->
19 </body>
20 </html>
View Code

style.css

 1 h1{
 2     text-align: center;
 3     margin-top: 5%;
 4 }
 5 #restart{
 6     display: block;
 7     margin: 20px auto;
 8     width: 100px;
 9     padding: 10px 10px;
10     background-color: #8f7a66;
11     text-align: center;
12     font-size: 24px;
13     color: white;
14     border-radius: 10px;
15     text-decoration: none;
16 }
17 #restart:hover {
18     background-color: #9f8b77;
19 }
20 canvas {
21   margin: 0 auto;
22   display: block;
23   -moz-box-shadow: -2px -2px 2px #EFEFEF, 5px 5px 5px #b9b9b9;
24   -webkit-box-shadow: -2px -2px 2px #EFEFEF, 5px 5px 5px #b9b9b9;
25   box-shadow: -2px -2px 2px #EFEFEF, 5px 5px 5px #b9b9b9;
26 }
View Code

scrit.js (未封装版本)

  1 //全局变量
  2 var me = true; //黑棋先手 
  3 var over = false; //判断游戏是否结束
  4 //棋盘落子情况初始化为空
  5 var chessBoard = new Array();
  6 
  7 var init = function(){
  8     for (var i=0; i<15; i++) {
  9         chessBoard[i] = [];
 10         for(var j=0; j<15; j++){
 11             chessBoard[i][j] = 0;
 12         }
 13     }
 14 }
 15 
 16 //制作棋盘
 17 var chess = document.getElementById('chess');
 18 var ctx = chess.getContext('2d');
 19 ctx.strokeStyle = "#000000";
 20 
 21 //载入背景图片
 22 var logo = new Image();
 23 logo.src = "logo.jpg";
 24 logo.onload = function(){
 25     ctx.drawImage(logo,0,0,450,450);
 26     drawChessBoard();
 27     init();
 28 }
 29 
 30 var newgame = function(){
 31     location.reload();
 32 }
 33 
 34 //绘制棋盘线
 35 var drawChessBoard = function(){
 36     for(var i=0; i<15; i++){
 37         //画棋盘竖线
 38         ctx.moveTo(15+i*30, 15);
 39         ctx.lineTo(15+i*30, 435);
 40         ctx.stroke(); 
 41         //画棋盘横线
 42         ctx.moveTo(15, 15+i*30);
 43         ctx.lineTo(435, 15+i*30);
 44         ctx.stroke();  
 45     }    
 46 }
 47 
 48 //制作黑白棋子
 49 var oneStep = function(i, j, me){
 50     //画圆
 51     ctx.beginPath();
 52     ctx.arc(15 + i*30, 15 + j*30, 13, 0, 2 * Math.PI);
 53     ctx.closePath();
 54     //渐变
 55     var grd = ctx.createRadialGradient(15 + i*30 + 2, 15 + j*30 - 2, 13, 15 + i*30 + 2, 15 + j*30 - 2, 0); 
 56     if(me){ //黑棋
 57         grd.addColorStop(0, "#0A0A0A");
 58         grd.addColorStop(1, "#636766");
 59     }
 60     else{  //白棋
 61         grd.addColorStop(0, "#D1D1D1");
 62         grd.addColorStop(1, "#F9F9F9");
 63     }   
 64     ctx.fillStyle = grd;
 65     ctx.fill();
 66 }
 67 
 68 //点击棋盘落子
 69 chess.onclick = function(e){
 70     if(over){
 71         return ;
 72     }
 73     if(!me){
 74         return ;
 75     }
 76     var x = e.offsetX;
 77     var y = e.offsetY;
 78     var i = Math.floor(x / 30);
 79     var j = Math.floor(y / 30);
 80     if(chessBoard[i][j] == 0){
 81         oneStep(i, j, me);
 82         chessBoard[i][j] = 1;   //黑棋落子为1
 83      
 84         for(var k=0; k<count; k++){
 85             if(wins[i][j][k]){
 86                 myWin[k]++;
 87                 computerWin[k] = 6; //设置成比5大的数都不会加分
 88                 if(myWin[k] == 5){
 89                     window.alert("You Win !");
 90                     over = true;
 91                 }
 92             }
 93         }
 94         if(!over){
 95             me = !me;
 96             computerAI();
 97         }
 98     }
 99 }
100 //计算机下棋
101 var computerAI = function(){
102     var myScore = [];
103     var computerScore = [];
104     var max = 0;
105     var u = 0, v = 0;
106     for(var i=0; i<15; i++){
107         myScore[i] = [];
108         computerScore[i] =[];
109         for(var j=0; j<15; j++){
110             myScore[i][j] = 0;
111             computerScore[i][j] = 0;
112         }
113     }
114     for(var i=0; i<15; i++){
115         for(var j=0; j<15; j++){
116             if(chessBoard[i][j] == 0){
117                 for(var k=0; k<count; k++){
118                     if(wins[i][j][k]){
119                         if(myWin[k] == 1){
120                             myScore[i][j] += 200;
121                         }else if(myWin[k] == 2){
122                             myScore[i][j] += 400;
123                         }else if(myWin[k] == 3){
124                             myScore[i][j] += 2000;
125                         }else if(myWin[k] == 4){
126                             myScore[i][j] += 10000;
127                         }
128 
129                         if(computerWin[k] == 1){
130                             computerScore[i][j] += 220;
131                         }
132                         else if(computerWin[k] == 2){
133                             computerScore[i][j] += 420;
134                         }
135                         else if(computerWin[k] == 3){
136                             computerScore[i][j] += 2100;
137                         }
138                         else if(computerWin[k] == 4){
139                             computerScore[i][j] += 20000;
140                         }
141                     }
142                 }
143                 if(myScore[i][j] > max){
144                     max = myScore[i][j];
145                     u = i;
146                     v = j;                  
147                 }
148                 else if(myScore[i][j] == max){
149                     if(computerScore[i][j] > computerScore[u][v]){
150                         u = i;
151                         v = j;                      
152                     }
153                 }
154 
155                 if(computerScore[i][j] > max){
156                     max = computerScore[i][j];
157                     u = i;
158                     v = j;                  
159                 }
160                 else if(computerScore[i][j] == max){
161                     if(myScore[i][j] > myScore[u][v]){
162                         u = i;
163                         v = j;                      
164                     }
165                 }
166             }
167         }
168     }
169     oneStep(u, v, false);
170     chessBoard[u][v] = 2;  
171     
172     for(var k = 0; k < count; k++){
173         if(wins[u][v][k]){
174             computerWin[k]++;
175             myWin[k] = 6;
176             if(computerWin[k] == 5){
177                 window.alert("Computer Win !")
178                 over = true;
179             }
180         }
181     }
182     if(!over){
183         me = !me;
184     }    
185 }
186 
187 
188 //更改鼠标指针样式
189 chess.onmousemove = function(e){
190     chess.style.cursor = "default";
191     var x = e.offsetX;
192     var y = e.offsetY;
193     for(var i=0; i<15; i++){
194         for(var j=0; j<15; j++){
195             var a = x - (15+i*30);
196             var b = y - (15+j*30);
197             var distance = Math.hypot(a, b);
198             var chessRange = Math.sqrt(25, 2);
199             //在交叉处半径为5的范围内,鼠标变成手指样式
200             if(distance < chessRange){
201                 chess.style.cursor = "pointer";
202             }
203         }
204     }
205 }
206 
207 
208 //赢法数组
209 var wins = new Array();
210 
211 //定义赢法的三维数组
212 for(var i=0; i<15; i++){
213     wins[i] = [];
214     for(var j=0; j<15; j++){
215         wins[i][j] = [];
216     }
217 }
218 var count = 0;
219 
220 //横线赢法
221 for(var i=0; i<15; i++){
222     for(var j=0; j<11; j++){
223         for(var k=0; k<5; k++){
224             wins[i][j+k][count] = true;  
225         }
226         count++;
227     }
228 }
229 
230 //竖线赢法
231 for(var i=0; i<15; i++){
232     for(var j=0; j<11; j++){
233         for(var k=0; k<5; k++){
234             wins[j+k][i][count] = true;  
235         }
236         count++;
237     }
238 }
239 
240 //斜线赢法
241 for(var i=0; i<11; i++){
242     for(var j=0; j<11; j++){
243         for(var k=0; k<5; k++){
244             wins[i+k][j+k][count] = true;  
245         }
246         count++;
247     }
248 }
249 
250 //反斜线赢法
251 for(var i = 0; i < 11; i++){
252     for(var j= 14; j > 3; j--){
253         for(var k = 0; k < 5; k++){
254             wins[i+k][j-k][count] = true;
255         }
256         count++;
257     }
258 }
259 console.log(count);
260 
261 
262 //赢法统计数组
263 var myWin = [];
264 var computerWin = [];
265 
266 //赢法统计数组初始化
267 for(var i=0; i<count; i++){
268     myWin[i] = 0;
269     computerWin[i] = 0;
270 }
View Code

gobang.js(函数封装版本)

  1 //gobang 封装实现
  2 (function(){
  3     //定义变量
  4     var chess = document.getElementById('chess');  //获取棋盘画布
  5     var ctx = chess.getContext('2d');  //设置画布渲染
  6     var logo = new Image(); //创建棋盘背景图像
  7     var chessBoard = new Array();  //棋盘落子统计,用于存储棋盘格上是否有落子
  8     var wins = [];  //赢法数组
  9     var count = 0;  //赢法统计数组
 10     var myWin = [];  //玩家赢法统计
 11     var computerWin = [];  //计算机赢法统计
 12     var me = true; //棋手标记 true为玩家下棋,false为电脑下棋 
 13     var over = false; //判断对局是否结束标记 true为结束,flase为未结束
 14 
 15     var goBang = {
 16         //入口
 17         init: function(){
 18             var _this = this;  //复制this对象
 19             return (function(){
 20                 //变量初始化
 21                 _this.initializa();
 22                 //图片加载点
 23                 logo.onload = function(){
 24                     //填充背景图片
 25                     ctx.drawImage(logo,0,0,450,450);
 26                     //绘制棋盘线
 27                     _this.drawChessBoard();  
 28                     // _this.oneStep(7,7,false); //测试oneStep函数                                   
 29                 };
 30 
 31                 //落子事件绑定
 32                 //点击棋盘落子
 33                 chess.onclick = function(e){
 34                     //判断对局是否结束或是否轮到玩家下棋,对局结束或者不是玩家下棋就会跳出循环
 35                     if(over || me == false){
 36                         return ;
 37                     }
 38                     //获取鼠标点击位置坐标,并转换为落点坐标
 39                     var x = e.offsetX,
 40                         y = e.offsetY;
 41                     var i = Math.floor(x / 30),
 42                         j = Math.floor(y / 30);
 43                     //判断当前落点是否已有棋子,如果没有则落子成功
 44                     if(chessBoard[i][j] == 0){
 45                         _this.oneStep(i, j, me);  //玩家落子
 46                         chessBoard[i][j] = 1;   //玩家黑棋落子为1
 47                         for(var k=0; k<count; k++){
 48                             if(wins[i][j][k]){
 49                                 myWin[k]++;
 50                                 computerWin[k] = 999; //设置成比5大的数都不会加分
 51                                 if(myWin[k] == 5){
 52                                     window.alert("You Win !");
 53                                     over = true;
 54                                 }
 55                             }
 56                         }
 57                         //判断对局是否未结束,如果未结束将换成计算机下子
 58                         if(over == false){
 59                             me = !me;
 60                             _this.computerAI(); //计算机落子
 61                         }
 62                     }
 63                 };
 64 
 65                 //更改鼠标指针样式
 66                 chess.onmousemove = function(e){
 67                     chess.style.cursor = "default";
 68                     var x = e.offsetX;
 69                     var y = e.offsetY;
 70                     for(var i=0; i<15; i++){
 71                         for(var j=0; j<15; j++){
 72                             var a = x - (15+i*30);
 73                             var b = y - (15+j*30);
 74                             var distance = Math.hypot(a, b);
 75                             var chessRange = Math.sqrt(25, 2);
 76                             //在交叉处半径为5的范围内,鼠标变成手指样式
 77                             if(distance < chessRange){
 78                                 chess.style.cursor = "pointer";
 79                             }
 80                         }
 81                     }
 82                 };
 83 
 84             })();
 85         },
 86 
 87         //变量&初始化&参数设置
 88         initializa: function(){
 89             return (function(){
 90                 //棋盘线条颜色
 91                 ctx.strokeStyle = "#000000"; //黑色
 92                 //载入背景图片
 93                 logo.src = "logo.jpg";
 94                 //棋盘棋盘落子统计初始化(无落子) chessBoard
 95                 for (var i=0; i<15; i++) {
 96                     chessBoard[i] = [];
 97                     for(var j=0; j<15; j++){
 98                         chessBoard[i][j] = 0;
 99                     }
100                 } 
101                 //定义赢法的三维数组 wins
102                 for(var i=0; i<15; i++){
103                     wins[i] = [];
104                     for(var j=0; j<15; j++){
105                         wins[i][j] = [];
106                     }
107                 } 
108                 //赢法总类统计 共计572种
109                 //横线赢法
110                 for(var i=0; i<15; i++){
111                     for(var j=0; j<11; j++){
112                         for(var k=0; k<5; k++){
113                             wins[i][j+k][count] = true;  
114                         }
115                         count++;
116                     }
117                 }
118                 //竖线赢法
119                 for(var i=0; i<15; i++){
120                     for(var j=0; j<11; j++){
121                         for(var k=0; k<5; k++){
122                             wins[j+k][i][count] = true;  
123                         }
124                         count++;
125                     }
126                 }
127                 //斜线赢法
128                 for(var i=0; i<11; i++){
129                     for(var j=0; j<11; j++){
130                         for(var k=0; k<5; k++){
131                             wins[i+k][j+k][count] = true;  
132                         }
133                         count++;
134                     }
135                 }
136                 //反斜线赢法
137                 for(var i = 0; i < 11; i++){
138                     for(var j= 14; j > 3; j--){
139                         for(var k = 0; k < 5; k++){
140                             wins[i+k][j-k][count] = true;
141                         }
142                         count++;
143                     }
144                 }
145                 console.log(count);  //赢法总类输出
146                 //赢法统计数组初始化
147                 for(var i=0; i<count; i++){
148                     myWin[i] = 0;
149                     computerWin[i] = 0;
150                 }
151             })();
152         },
153 
154         //绘制棋盘
155         drawChessBoard: function(){
156             return (function(){
157                 for(var i=0; i<15; i++){
158                     //画棋盘竖线
159                     ctx.moveTo(15+i*30, 15);
160                     ctx.lineTo(15+i*30, 435);
161                     ctx.stroke(); 
162                     //画棋盘横线
163                     ctx.moveTo(15, 15+i*30);
164                     ctx.lineTo(435, 15+i*30);
165                     ctx.stroke();  
166                 }       
167             })();
168         },
169 
170         //绘制黑白棋子
171         oneStep: function(i, j, me){
172             return (function(){
173                 //阴影
174                 ctx.shadowOffsetX = 1.5;
175                 ctx.shadowOffsetY = 2;
176                 ctx.shadowBlur = 3;
177                 ctx.shadowColor = '#333';
178                 //画圆
179                 ctx.beginPath();
180                 ctx.arc(15 + i*30, 15 + j*30, 13, 0, 2 * Math.PI);
181                 ctx.closePath();
182                 //渐变
183                 var grd = ctx.createRadialGradient(15 + i*30 + 2, 15 + j*30 - 2, 13, 15 + i*30 + 2, 15 + j*30 - 2, 0); 
184                 if(me){ //黑棋
185                     grd.addColorStop(0, "#0A0A0A");
186                     grd.addColorStop(1, "#636766");
187                 }
188                 else{  //白棋
189                     grd.addColorStop(0, "#D1D1D1");
190                     grd.addColorStop(1, "#F9F9F9");
191                 }   
192                 ctx.fillStyle = grd;
193                 ctx.fill();                
194             })();
195         },
196 
197         //计算机下棋
198         computerAI: function(){
199             var that = this; //复制this对象
200             return (function(){
201                 //定义变量,分数统计数组和坐标存储变量
202                 var myScore = [],
203                     computerScore = [];
204                 var max = 0,
205                     u = 0, v = 0;
206                 //分数统计初始化
207                 for(var i=0; i<15; i++){
208                     myScore[i] = [];
209                     computerScore[i] = [];
210                     for(var j=0; j<15; j++){
211                         myScore[i][j] = 0;
212                         computerScore[i][j] = 0;
213                     }
214                 }
215                 //分数(权重)统计&计算,获取坐标
216                 for(var i=0; i<15; i++){
217                     for(var j=0; j<15; j++){
218                         //判断当前位置是否没有落子
219                         if(chessBoard[i][j] == 0){
220                             //根据赢法数组计算分数
221                             for(var k=0; k<count; k++){
222                                 //如果存在第K种赢法的可能性
223                                 if(wins[i][j][k]){
224                                     if(myWin[k] == 1){
225                                         myScore[i][j] += 200;
226                                     }else if(myWin[k] == 2){
227                                         myScore[i][j] += 400;
228                                     }else if(myWin[k] == 3){
229                                         myScore[i][j] += 2000;
230                                     }else if(myWin[k] == 4){
231                                         myScore[i][j] += 10000;
232                                     }
233 
234                                     if(computerWin[k] == 1){
235                                         computerScore[i][j] += 220;
236                                     }
237                                     else if(computerWin[k] == 2){
238                                         computerScore[i][j] += 420;
239                                     }
240                                     else if(computerWin[k] == 3){
241                                         computerScore[i][j] += 2100;
242                                     }
243                                     else if(computerWin[k] == 4){
244                                         computerScore[i][j] += 20000;
245                                     }
246                                 }
247                             }
248                             //通过判断获取最优的落子点
249                             if(myScore[i][j] > max){
250                                 max = myScore[i][j];
251                                 u = i;
252                                 v = j;                  
253                             }else if(myScore[i][j] == max){
254                                 if(computerScore[i][j] > computerScore[u][v]){
255                                     u = i;
256                                     v = j;                      
257                                 }
258                             }
259 
260                             if(computerScore[i][j] > max){
261                                 max = computerScore[i][j];
262                                 u = i;
263                                 v = j;                  
264                             }else if(computerScore[i][j] == max){
265                                 if(myScore[i][j] > myScore[u][v]){
266                                     u = i;
267                                     v = j;                      
268                                 }
269                             }
270                         }
271                     }
272                 }
273                 that.oneStep(u, v, false);  //计算机落子
274                 chessBoard[u][v] = 2;  ////玩家白棋落子为2
275                 //判断当前落点是否已有棋子,如果没有则落子成功,如果有则后台提示
276                 for(var k = 0; k < count; k++){
277                     if(wins[u][v][k]){
278                         computerWin[k]++;
279                         myWin[k] = 999;
280                         if(computerWin[k] == 5){
281                             window.alert("Computer Win !")
282                             over = true;
283                         }
284                     }
285                 }
286                 if(over == false){
287                     me = !me;
288                 }    
289             })();
290         },
291     };
292 
293     //重新开始
294     document.getElementById('restart').onclick = function(){
295         window.location.reload();
296     }
297     //执行代码
298     goBang.init(); 
299     
300 })();
View Code

棋盘背景图

 效果预览

 

posted @ 2017-07-16 21:21  gq_orange  阅读(1661)  评论(0编辑  收藏  举报