首页 > 其他分享 >人工智能五子棋游戏——(6)完整的项目代码

人工智能五子棋游戏——(6)完整的项目代码

时间:2023-02-19 16:34:12浏览次数:41  
标签:return 游戏 人工智能 Chessboard 五子棋 length var data row

本项目使用的是JavaScript语言,用到了其中的jquery库的jquery-2.2.2.min版本,请自行网上下载,本文就不再给出。

 

(1)前端html文件

index.html

 1 <!DOCTYPE html>
 2 <html>
 3 <head>
 4     <meta charset="utf-8" />
 5     <meta name="viewport" content="initial-scale=1.0,user-scalable=no,maximum-scale=1,width=device-width">
 6     <title>人工智能五子棋</title>
 7     <style type="text/css">
 8     body{
 9         margin: 0;
10         font-family: Microsoft Yahei;
11         text-align: center;
12     }
13     .timer{
14         margin: 0 20px;
15     }
16     .rollback{
17         width: 70px;
18         height: 30px;
19         margin: 20px;
20     }
21     .chessboard{
22         width: 315px;
23         margin: 0 auto;
24         border-left: 1px solid #ccc;
25         border-top: 1px solid #ccc;
26     }
27     .chessboard .row{
28         overflow: hidden;
29     }
30     .chessboard .tile{
31         width: 20px;
32         height: 20px;
33         float: left;
34         border-right: 1px solid #ccc;
35         border-bottom: 1px solid #ccc;
36         text-align: center;
37         line-height: 20px;
38     }
39     .chessboard .tile.current{
40         background-color: #ddd;
41     }
42     .chessboard .chess-max,.chessboard .chess-min{
43         font-size: 20px;
44         cursor: pointer;
45         -webkit-user-select: none;
46     }
47     </style>
48 </head>
49 <body>
50     <div>
51         <span class="timer">游戏开始,请落子</span>
52         <button class="rollback">悔棋</button>
53     </div>
54     <div class="chessboard"></div>
55     <script type="text/javascript" src="jquery-2.2.2.min.js"></script>
56     <script type="text/javascript" src="fivechess.js"></script>
57     <script type="text/javascript" src="main.js"></script>
58 </body>
59 </html>

 

(2)后端五子棋游戏的实现

main.js

 1 //棋盘
 2 var chessboard = new Chessboard(15, 15);
 3 var chessboardDom = $('.chessboard');
 4 //耗时和时钟
 5 var t = 0,
 6     tick;
 7 //初始化棋盘dom
 8 var initData = function() {
 9     for (var i = 0; i < chessboard.row; i++) {
10         var rowDom = $('<div></div>').addClass('row');
11         for (var j = 0; j < chessboard.column; j++) {
12             var tile = $('<div></div>').addClass('tile').data({
13                 row: i,
14                 column: j
15             });
16             rowDom.append(tile);
17         }
18         chessboardDom.append(rowDom);
19     }
20 };
21 var initEvent = function() {
22     $('.tile').on('click', function() {
23         //如果下棋还未完结
24         if (!chessboard.isEnded()) {
25             var self = $(this);
26             //已经有棋子
27             if (self.is('.chess')) {
28                 alert('请选择空余的格子下棋');
29             } else {
30                 var row = self.data('row'),
31                     column = self.data('column');
32                 //人下棋
33                 chessboard.put(row, column, Chessboard.MAX);
34                 self.addClass('chess chess-max current').text('●');
35                 //第一次下棋开始计时
36                 if (!tick) {
37                     tick = setInterval(function() {
38                         t++;
39                         $('.timer').text('对局已经过' + t + '秒');
40                     }, 1000);
41                 }
42                 //人赢了,结束游戏
43                 if (chessboard.isMaxWin()) {
44                     chessboard.end();
45                     clearInterval(tick);
46                     return alert('你用了' + t + '秒赢了人工智能');
47                 }
48                 //没赢,但平手了
49                 if (chessboard.isEnded()) {
50                     clearInterval(tick);
51                     return alert('你用了' + t + '秒和人工智能成为平手');
52                 } else {
53                     setTimeout(function() {
54                         //未分胜负,AI下棋
55                         console.time('min');
56                         var res = min(chessboard, 2);
57                         console.timeEnd('min');
58                         //AI下棋
59                         chessboard.put(res.row, res.column, Chessboard.MIN);
60                         $('.current').removeClass('current');
61                         chessboardDom.find('.row').eq(res.row).find('.tile').eq(res.column).addClass('chess chess-min current').text('○');
62                         //AI赢了,结束游戏
63                         if (chessboard.isMinWin()) {
64                             chessboard.end();
65                             clearInterval(tick);
66                             return alert('你被人工智能打败!');
67                         }
68                         //没赢,但平手了,否则未分胜负,等待人继续下棋
69                         if (chessboard.isEnded()) {
70                             clearInterval(tick);
71                             return alert('你用了' + t + '秒赢了人工智能');
72                         }
73                     }, 200);
74                 }
75             }
76         }
77     });
78     //悔棋
79     $('.rollback').on('click', function() {
80         //倒退两步
81         var steps = chessboard.rollback(2);
82         //清空前两步的dom文本
83         steps.forEach(function(step) {
84             chessboardDom.find('.row').eq(step.row).find('.tile').eq(step.column).removeClass('chess chess-min chess-max current').text('');
85         });
86         //返回当前的下棋位置,并添加current类
87         var step = chessboard.current();
88         if (step) {
89             chessboardDom.find('.row').eq(step.row).find('.tile').eq(step.column).addClass('current');
90         }
91     });
92 };
93 initData();
94 initEvent();

 

(2)算法的实现代码

fivechess.js

  1 /**
  2  * [Chessboard 棋盘]
  3  * @param {[type]} row    [description]
  4  * @param {[type]} column [description]
  5  */
  6 var Chessboard = function(row, column) {
  7     this.data = [];
  8     this.row = row;
  9     this.column = column;
 10     //赢法数组
 11     this.wins = [];
 12     //赢法数
 13     this.count = 0;
 14     //记录max每一种赢法的已经达成棋子数
 15     this.maxWin = [];
 16     //记录min每一种赢法的已经达成棋子数
 17     this.minWin = [];
 18     //初始化棋盘,顺便初始化赢法数组
 19     for (var i = 0; i < row; i++) {
 20         this.data[i] = [];
 21         this.wins[i] = [];
 22         for (var j = 0; j < column; j++) {
 23             this.data[i][j] = Chessboard.NONE;
 24             this.wins[i][j] = [];
 25         }
 26     }
 27     //横向赢法
 28     for (var i = 0; i < row; i++) {
 29         for (var j = 0; j <= column - 5; j++) {
 30             for (var k = 0; k < 5; k++) {
 31                 this.wins[i][j + k][this.count] = true;
 32             }
 33             this.count++;
 34         }
 35     }
 36     //纵向赢法
 37     for (var i = 0; i < column; i++) {
 38         for (var j = 0; j <= row - 5; j++) {
 39             for (var k = 0; k < 5; k++) {
 40                 this.wins[j + k][i][this.count] = true;
 41             }
 42             this.count++;
 43         }
 44     }
 45     //右斜线的赢法
 46     for (var i = 0; i <= row - 5; i++) {
 47         for (var j = 0; j <= column - 5; j++) {
 48             for (var k = 0; k < 5; k++) {
 49                 this.wins[i + k][j + k][this.count] = true;
 50             }
 51             this.count++;
 52         }
 53     }
 54     //左斜线的赢法
 55     for (var i = 0; i <= row - 5; i++) {
 56         for (var j = column - 1; j >= 4; j--) {
 57             for (var k = 0; k < 5; k++) {
 58                 this.wins[i + k][j - k][this.count] = true;
 59             }
 60             this.count++;
 61         }
 62     }
 63     //初始化max和min每一种赢法的下子情况
 64     for (var i = 0; i < this.count; i++) {
 65         this.maxWin[i] = {
 66             max: 0,
 67             min: 0
 68         };
 69         this.minWin[i] = {
 70             min: 0,
 71             max: 0
 72         };
 73     }
 74     //下棋记录堆栈
 75     this.stack = [];
 76     //游戏是否结束
 77     this.is_ended = false;
 78 };
 79 /**
 80  * [toString 输出棋盘信息]
 81  * @return {[type]} [description]
 82  */
 83 Chessboard.prototype.toString = function() {
 84     return this.data.map(function(data) {
 85         return data.toString();
 86     }).join('\n');
 87 };
 88 /**
 89  * 返回当前最新一步下的棋子
 90  * @return {[type]}
 91  */
 92 Chessboard.prototype.current = function() {
 93     var l = this.stack.length;
 94     if (l) {
 95         return this.stack[l - 1];
 96     }
 97 };
 98 /**
 99  * [put 下棋]
100  * @param  {[type]} row    [行]
101  * @param  {[type]} column [列]
102  * @param  {[type]} type   [人还是AI下棋]
103  * @return {[type]}        [description]
104  */
105 Chessboard.prototype.put = function(row, column, type) {
106     if (this.data[row][column] == Chessboard.NONE) {
107         this.data[row][column] = type;
108         //放进记录堆栈
109         this.stack.push({
110             row: row,
111             column: column,
112             type: type
113         });
114         //下棋之后对每一种赢法的下棋情况进行更新
115         for (var i = 0; i < this.count; i++) {
116             if (this.wins[row][column][i]) {
117                 if (type == Chessboard.MAX) {
118                     this.maxWin[i].max++;
119                     this.minWin[i].max++;
120                 } else {
121                     this.minWin[i].min++;
122                     this.maxWin[i].min++;
123                 }
124             }
125         }
126         //如果下子满了则结束游戏
127         if (this.stack.length == this.row * this.column) {
128             this.end();
129         }
130     }
131     return this;
132 };
133 /**
134  * [rollback 悔棋]
135  * @param  {[type]} n [后退n步]
136  * @return {[type]}   [description]
137  */
138 Chessboard.prototype.rollback = function(n) {
139     //记录后退的n步走法
140     var steps = [];
141     n = n || 1;
142     for (var i = 0; i < n; i++) {
143         var step = this.stack.pop();
144         if (step) {
145             steps.push(step);
146             var row = step.row,
147                 column = step.column,
148                 type = step.type;
149             //置空格点
150             this.data[row][column] = Chessboard.NONE;
151             //更新每一种赢法的下子情况
152             for (var j = 0; j < this.count; j++) {
153                 if (this.wins[row][column][j]) {
154                     if (type == Chessboard.MAX) {
155                         this.maxWin[j].max--;
156                         this.minWin[j].max--;
157                     } else {
158                         this.minWin[j].min--;
159                         this.maxWin[j].min--;
160                     }
161                 }
162             }
163         }
164     }
165     this.is_ended = false;
166     return steps;
167 };
168 /**
169  * 获取当前点附近考虑的下棋位置
170  * @param  {[p这个点]}
171  * @return {[type]}
172  */
173 Chessboard.prototype.getNearPoints = function(p) {
174     var points = [],
175         row, column;
176     for (var i = -2; i <= 2; i++) {
177         //右下角
178         row = p.row + i;
179         column = p.column + i;
180         if (this.isValid(row, column)) {
181             points.push({
182                 row: row,
183                 column: column
184             });
185         }
186         //左上角
187         row = p.row - i;
188         column = p.column + i;
189         if (this.isValid(row, column)) {
190             points.push({
191                 row: row,
192                 column: column
193             });
194         }
195         //行
196         row = p.row;
197         column = p.column - i;
198         if (this.isValid(row, column)) {
199             points.push({
200                 row: row,
201                 column: column
202             });
203         }
204         //列
205         row = p.row - i;
206         column = p.column;
207         if (this.isValid(row, column)) {
208             points.push({
209                 row: row,
210                 column: column
211             });
212         }
213     }
214     return points;
215 };
216 //该位置是否合法
217 Chessboard.prototype.isValid = function(row, column) {
218     return row >= 0 && row < this.row && column >= 0 && column < this.column && this.data[row][column] == Chessboard.NONE;
219 };
220 /**
221  * [availableSteps 获取可走的位置]
222  * @return {[type]} [description]
223  */
224 Chessboard.prototype.availableSteps = function() {
225     var availableSteps = [],
226         row = this.row,
227         column = this.column,
228         stackLen = this.stack.length,
229         centerRow = Math.floor((row - 1) / 2),
230         centerColumn = Math.floor((column - 1) / 2);
231     if (!stackLen || (stackLen == 1 && this.data[centerRow][centerColumn] == Chessboard.NONE)) {
232         availableSteps.push({
233             row: centerRow,
234             column: centerColumn
235         });
236         return availableSteps;
237     } else {
238         if (stackLen == 1) {
239             var nextRow = centerRow + (Math.random() < 0.5 ? -1 : 1),
240                 nextColumn = centerColumn + (Math.random() < 0.5 ? -1 : 1);
241             availableSteps.push({
242                 row: nextRow,
243                 column: nextColumn
244             });
245             return availableSteps;
246         } else {
247             var hash = {};
248             this.stack.forEach(function(p) {
249                 nearPoints = this.getNearPoints(p);
250                 nearPoints.forEach(function(nearPoint) {
251                     var row = nearPoint.row,
252                         column = nearPoint.column;
253                     if (!hash[row + '#' + column]) {
254                         availableSteps.push(nearPoint);
255                         hash[row + '#' + column] = true;
256                     }
257                 });
258             }.bind(this));
259             return availableSteps;
260         }
261     }
262     return availableSteps;
263 };
264 Chessboard.prototype.analyseMax = function(data, type) {
265     switch (type) {
266         case Chessboard.FIVE_TYPE:
267             return ~data.indexOf('11111') ? 1 : 0;
268         case Chessboard.SFOUR_TYPE:
269             if (~data.indexOf('011110')) {
270                 return 1;
271             }
272             return 0;
273         case Chessboard.FOUR_TYPE:
274             var c = 0;
275             var res1 = data.match(/211110/g);
276             var res2 = data.match(/011112/g);
277             var res3 = data.match(/10111/g);
278             var res4 = data.match(/11011/g);
279             var res5 = data.match(/11101/g);
280             c += (res1 ? res1.length : 0);
281             c += (res2 ? res2.length : 0);
282             c += (res3 ? res3.length : 0);
283             c += (res4 ? res4.length : 0);
284             c += (res5 ? res5.length : 0);
285             return c;
286         case Chessboard.STHREE_TYPE:
287             var c = 0;
288             var res1 = data.match(/01110/g);
289             var res2 = data.match(/011010/g);
290             var res3 = data.match(/010110/g);
291             c += (res1 ? res1.length : 0);
292             c += (res2 ? res2.length : 0);
293             c += (res3 ? res3.length : 0);
294             return c;
295         case Chessboard.THREE_TYPE:
296             var c = 0;
297             var res1 = data.match(/211100/g);
298             var res2 = data.match(/001112/g);
299             var res3 = data.match(/211010/g);
300             var res4 = data.match(/010112/g);
301             var res5 = data.match(/210110/g);
302             var res6 = data.match(/011012/g);
303             var res7 = data.match(/10011/g);
304             var res8 = data.match(/11001/g);
305             var res9 = data.match(/10101/g);
306             var res10 = data.match(/2011102/g);
307             c += (res1 ? res1.length : 0);
308             c += (res2 ? res2.length : 0);
309             c += (res3 ? res3.length : 0);
310             c += (res4 ? res4.length : 0);
311             c += (res5 ? res5.length : 0);
312             c += (res6 ? res6.length : 0);
313             c += (res7 ? res7.length : 0);
314             c += (res8 ? res8.length : 0);
315             c += (res9 ? res9.length : 0);
316             c += (res10 ? res10.length : 0);
317             return c;
318         case Chessboard.STWO_TYPE:
319             var c = 0;
320             var res1 = data.match(/001100/g);
321             var res2 = data.match(/01010/g);
322             var res3 = data.match(/010010/g);
323             c += (res1 ? res1.length : 0);
324             c += (res2 ? res2.length : 0);
325             c += (res3 ? res3.length : 0);
326             return c;
327         case Chessboard.TWO_TYPE:
328             var c = 0;
329             var res1 = data.match(/001100/g);
330             var res2 = data.match(/01010/g);
331             var res3 = data.match(/010010/g);
332             c += (res1 ? res1.length : 0);
333             c += (res2 ? res2.length : 0);
334             c += (res3 ? res3.length : 0);
335             return c;
336         default:
337             return 0;
338     }
339 };
340 Chessboard.prototype.analyseMin = function(data, type) {
341     switch (type) {
342         case Chessboard.FIVE_TYPE:
343             return ~data.indexOf('22222') ? 1 : 0;
344         case Chessboard.SFOUR_TYPE:
345             if (~data.indexOf('022220')) {
346                 return 1;
347             }
348             return 0;
349         case Chessboard.FOUR_TYPE:
350             var c = 0;
351             var res1 = data.match(/122220/g);
352             var res2 = data.match(/022221/g);
353             var res3 = data.match(/20222/g);
354             var res4 = data.match(/22022/g);
355             var res5 = data.match(/22202/g);
356             c += (res1 ? res1.length : 0);
357             c += (res2 ? res2.length : 0);
358             c += (res3 ? res3.length : 0);
359             c += (res4 ? res4.length : 0);
360             c += (res5 ? res5.length : 0);
361             return c;
362         case Chessboard.STHREE_TYPE:
363             var c = 0;
364             var res1 = data.match(/02220/g);
365             var res2 = data.match(/022020/g);
366             var res3 = data.match(/020220/g);
367             c += (res1 ? res1.length : 0);
368             c += (res2 ? res2.length : 0);
369             c += (res3 ? res3.length : 0);
370             return c;
371         case Chessboard.THREE_TYPE:
372             var c = 0;
373             var res1 = data.match(/122200/g);
374             var res2 = data.match(/002221/g);
375             var res3 = data.match(/122020/g);
376             var res4 = data.match(/020221/g);
377             var res5 = data.match(/120220/g);
378             var res6 = data.match(/022021/g);
379             var res7 = data.match(/20022/g);
380             var res8 = data.match(/22002/g);
381             var res9 = data.match(/20202/g);
382             var res10 = data.match(/1022201/g);
383             c += (res1 ? res1.length : 0);
384             c += (res2 ? res2.length : 0);
385             c += (res3 ? res3.length : 0);
386             c += (res4 ? res4.length : 0);
387             c += (res5 ? res5.length : 0);
388             c += (res6 ? res6.length : 0);
389             c += (res7 ? res7.length : 0);
390             c += (res8 ? res8.length : 0);
391             c += (res9 ? res9.length : 0);
392             c += (res10 ? res10.length : 0);
393             return c;
394         case Chessboard.STWO_TYPE:
395             var c = 0;
396             var res1 = data.match(/002200/g);
397             var res2 = data.match(/02020/g);
398             var res3 = data.match(/020020/g);
399             c += (res1 ? res1.length : 0);
400             c += (res2 ? res2.length : 0);
401             c += (res3 ? res3.length : 0);
402             return c;
403         case Chessboard.TWO_TYPE:
404             var c = 0;
405             var res1 = data.match(/001100/g);
406             var res2 = data.match(/01010/g);
407             var res3 = data.match(/010010/g);
408             c += (res1 ? res1.length : 0);
409             c += (res2 ? res2.length : 0);
410             c += (res3 ? res3.length : 0);
411             return c;
412         default:
413             return 0;
414     }
415 };
416 /**
417  * [evaluate 计算当前棋盘的估值]
418  * @return {[type]} [description]
419  */
420 Chessboard.prototype.evaluate = function() {
421     var maxW = minW = 0;
422     var maxGroup = {
423             "5": 0,
424             "4": 0,
425             "3": 0,
426             "2": 0,
427             "1": 0
428         },
429         minGroup = {
430             "5": 0,
431             "4": 0,
432             "3": 0,
433             "2": 0,
434             "1": 0
435         };
436     for (var i = 0; i < this.count; i++) {
437         if (this.maxWin[i].max == 5 && !this.maxWin[i].min) {
438             return Chessboard.MAX_VALUE;
439         }
440         if (this.minWin[i].min == 5 && !this.minWin[i].max) {
441             return Chessboard.MIN_VALUE;
442         }
443         if (this.maxWin[i].max == 4 && !this.maxWin[i].min) {
444             maxGroup[4]++;
445         }
446         if (this.minWin[i].min == 4 && !this.minWin[i].max) {
447             minGroup[4]++;
448         }
449         if (this.maxWin[i].max == 3 && !this.maxWin[i].min) {
450             maxGroup[3]++;
451         }
452         if (this.minWin[i].min == 3 && !this.minWin[i].max) {
453             minGroup[3]++;
454         }
455         if (this.maxWin[i].max == 2 && !this.maxWin[i].min) {
456             maxGroup[2]++;
457         }
458         if (this.minWin[i].min == 2 && !this.minWin[i].max) {
459             minGroup[2]++;
460         }
461         if (this.maxWin[i].max == 1 && !this.maxWin[i].min) {
462             maxGroup[1]++;
463         }
464         if (this.minWin[i].min == 1 && !this.minWin[i].max) {
465             minGroup[1]++;
466         }
467     }
468     maxW = maxGroup[4] * Chessboard.FOUR_W + maxGroup[3] * Chessboard.THREE_W + maxGroup[2] * Chessboard.TWO_W + maxGroup[1] * Chessboard.ONE_W;
469     minW = minGroup[4] * Chessboard.FOUR_W + minGroup[3] * Chessboard.THREE_W + minGroup[2] * Chessboard.TWO_W + minGroup[1] * Chessboard.ONE_W;
470     return maxW - minW;
471 };
472 /**
473  * [isMaxWin 人是否赢了]
474  * @return {Boolean} [description]
475  */
476 Chessboard.prototype.isMaxWin = function() {
477     var w = this.evaluate();
478     return w == Chessboard.MAX_VALUE ? true : false;
479 };
480 /**
481  * [isMinWin AI是否赢了]
482  * @return {Boolean} [description]
483  */
484 Chessboard.prototype.isMinWin = function() {
485     var w = this.evaluate();
486     return w == Chessboard.MIN_VALUE ? true : false;
487 };
488 /**
489  * [end 结束游戏]
490  * @return {[type]} [description]
491  */
492 Chessboard.prototype.end = function() {
493     this.is_ended = true;
494     return this;
495 };
496 /**
497  * [isEnded 游戏是否结束]
498  * @return {Boolean} [description]
499  */
500 Chessboard.prototype.isEnded = function() {
501     return this.is_ended;
502 };
503 /**
504  * [max max下棋]
505  * @param  {[type]} currentChessboard [当前棋盘]
506  * @param  {[type]} depth        [考虑深度]
507  * @return {[type]}              [description]
508  */
509 var max = function(currentChessboard, depth, beta) {
510     //记录优势值,应该下棋的位置
511     var row, column, alpha = -Infinity;
512     //什么都不下,直接返回当前棋盘评估值
513     if (depth == 0) {
514         alpha = currentChessboard.evaluate();
515         return {
516             w: alpha
517         };
518     } else {
519         //获取每一步可以走的方案
520         var steps = currentChessboard.availableSteps();
521         // console.log('搜索MAX' + steps.length + '个棋局');
522         if (steps.length) {
523             //对于每一种走法
524             for (var i = 0, l = steps.length; i < l; i++) {
525                 var step = steps[i];
526                 //下棋
527                 currentChessboard.put(step.row, step.column, Chessboard.MAX);
528                 //如果已经赢了,则直接下棋,不再考虑对方下棋
529                 if (currentChessboard.isMaxWin()) {
530                     alpha = Chessboard.MAX_VALUE;
531                     row = step.row;
532                     column = step.column;
533                     //退回上一步下棋
534                     currentChessboard.rollback();
535                     break;
536                 } else {
537                     //考虑对方depth-1步下棋之后的优势值,如果对方没棋可下了,则返回当前棋盘估值
538                     var res = min(currentChessboard, depth - 1) || {
539                         w: currentChessboard.evaluate()
540                     };
541                     //退回上一步下棋
542                     currentChessboard.rollback();
543                     if (res.w > alpha) {
544                         //选择最大优势的走法
545                         alpha = res.w;
546                         row = step.row;
547                         column = step.column;
548                     }
549                     //如果人可以获得更好的走法,则AI必然不会选择这一步走法,所以不用再考虑人的其他走法
550                     if (alpha >= beta) {
551                         // console.log('MAX节点' + l + '个棋局,剪掉了' + (l - 1 - i) + '个MIN棋局');
552                         break;
553                     }
554                 }
555 
556             }
557             return {
558                 w: alpha,
559                 row: row,
560                 column: column
561             };
562         }
563     }
564 };
565 /**
566  * [min min下棋]
567  * @param  {[type]} currentChessboard [当前棋盘]
568  * @param  {[type]} depth        [考虑深度]
569  * @return {[type]}              [权重和当前推荐下棋的位置]
570  */
571 var min = function(currentChessboard, depth, alpha) {
572     var row, column, beta = Infinity;
573     if (depth == 0) {
574         beta = currentChessboard.evaluate();
575         return {
576             w: beta
577         };
578     } else {
579         //获取每一步可以走的方案
580         var steps = currentChessboard.availableSteps();
581         // console.log('搜索MIN' + steps.length + '个棋局');
582         if (steps.length) {
583             //对于每一种走法
584             for (var i = 0, l = steps.length; i < l; i++) {
585                 var step = steps[i];
586                 //下棋
587                 currentChessboard.put(step.row, step.column, Chessboard.MIN);
588                 //如果已经赢了,则直接下棋,不再考虑对方下棋
589                 if (currentChessboard.isMinWin()) {
590                     beta = Chessboard.MIN_VALUE;
591                     row = step.row;
592                     column = step.column;
593                     //退回上一步下棋
594                     currentChessboard.rollback();
595                     break;
596                 } else {
597                     //考虑对方depth-1步下棋之后的优势值,如果对方没棋可下了,则返回当前棋盘估值
598                     var res = max(currentChessboard, depth - 1, beta) || {
599                         w: currentChessboard.evaluate()
600                     };
601                     //退回上一步下棋
602                     currentChessboard.rollback();
603                     if (res.w < beta) {
604                         //选择最大优势的走法
605                         beta = res.w;
606                         row = step.row;
607                         column = step.column;
608                     }
609                     //如果AI可以获得更好的走法,则人必然不会选择这一步走法,所以不用再考虑AI的其他走法
610                     if (beta <= alpha) {
611                         // console.log('MIN节点' + l + '个棋局,剪掉了' + (l - 1 - i) + '个MAX棋局');
612                         break;
613                     }
614                 }
615             }
616             return {
617                 w: beta,
618                 row: row,
619                 column: column
620             };
621         }
622     }
623 };
624 Chessboard.NONE = 0;
625 Chessboard.MAX = 1;
626 Chessboard.MIN = 2;
627 Chessboard.FIVE_TYPE = 1;
628 Chessboard.SFOUR_TYPE = 2;
629 Chessboard.FOUR_TYPE = 3;
630 Chessboard.STHREE_TYPE = 4;
631 Chessboard.THREE_TYPE = 5;
632 Chessboard.STWO_TYPE = 6;
633 Chessboard.TWO_TYPE = 7;
634 Chessboard.MAX_VALUE = 100000;
635 Chessboard.MIN_VALUE = -100000;
636 Chessboard.FIVE_W = 100000;
637 Chessboard.SFOUR_W = 10000;
638 Chessboard.FOUR_W = 5000;
639 Chessboard.STHREE_W = 2000;
640 Chessboard.THREE_W = 1000;
641 Chessboard.STWO_W = 500;
642 Chessboard.TWO_W = 200;
643 Chessboard.ONE_W = 10;

 

标签:return,游戏,人工智能,Chessboard,五子棋,length,var,data,row
From: https://www.cnblogs.com/yenaibo/p/17134970.html

相关文章