AI五子棋------------初探

  最近在研究AI贪吃蛇,昨天写了一天代码实在头昏脑涨,想起之前在慕课网上看到一个关于五子棋AI的视频,加起来也就一个钟头,所以今天抽了点时间学习了一下,逻辑还是很简单的,但是如果自己想肯定是一时半会想不出这么好的方法,也对自己的学习以及最近对AI贪吃蛇的思考有所启发,还是很有收获的(为数不多觉得还可以的视频教程)。

  关于具体的思路,视频讲的很清楚,也可以找到观看,就不一一分析了。主要是记录一下代码(因为视频没源码下载),以及自己的感想。

  文件结构(sublime 截图)

  

  index.html代码

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="utf-8">
 5     <title>五子棋</title>
 6     <link rel="stylesheet" type="text/css" href="css/style.css">
 7 </head>
 8 <body>
 9     <canvas id="chess" width="450px" height="450px"></canvas>
10     <script type="text/javascript" src="js/script.js"></script>
11 </body>
12 </html>
13 <!--UI
14 *canvas 绘制直线
15 *设置画笔颜色
16 *canvas画圆
17 *填充渐变色
18 -->
19 <!--AI
20 *赢法数组,三维
21 *每一种赢法的统计数组,一位数组
22 *如何判断胜负
23 -->

index.html

  style.css代码

1 canvas{
2     display: block;
3     margin: 50px auto;
4     box-shadow: -2px -2px 2px 2px #EFEFEF, 5px 5px 5px #B9B9B9;
5 }

style.css

  script.js代码

var chessBoard = [];
var me = true;
var over = false;
//赢法数组
var wins = [];
//赢法的统计数组
var myWin = [];
var computerWin = [];
for (var i = 0; i < 15; i++){
    chessBoard[i] = [];
    for (var j = 0; j < 15; j++){
        chessBoard[i][j] = 0;
    }
}
for (var i = 0; i < 15; i++){
    wins[i] = [];
    for (var j = 0; j < 15; j++){
        wins[i][j] = [];
    }
}
var count = 0;
//统计所有可能的赢法,需要好好理解
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 < 11; i++){
    for (var j = 0; j < 15; j++){
        for (var k = 0; k < 5; k++){
            wins[i+k][j][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++;
    }
}
//共 572 赢法
//初始化
for (var i = 0; i < count; i++){
    myWin[i] = 0;
    computerWin[i] = 0;
}
var chess = document.getElementById(‘chess‘);
var context = chess.getContext(‘2d‘);
context.strokeStyle = "#AFAFAF";
var logo = new Image();
logo.src = "images/logo.png";
logo.onload = function() {
    context.drawImage(logo, 0, 0, 450, 450);
    drawChessBoard();
}
var drawChessBoard = function() {
    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, "#0A0A0A");
        gradient.addColorStop(1, "#636766");
    } else {
        gradient.addColorStop(0, "#D1D1D1");
        gradient.addColorStop(1, "#F9F9F9");
    }
    context.fillStyle = gradient;
    context.fill();
}
chess.onclick = function(e){
    if (over){
        return;
    }
    if (!me){
        return;
    }
    var x = e.offsetX;
    var y = e.offsetY;
    var i = Math.floor(x / 30);
    var j = Math.floor(y / 30);
    if (0 == chessBoard[i][j]){
        oneStep(i, j, me);
        chessBoard[i][j] = 1;
        //更新赢法统计数组
        for (var k = 0; k < count; k++){
            if (wins[i][j][k]){
                myWin[k]++;//接近胜利
                computerWin[k] = 6;//设置为异常值,因为最多加到5
                if (5 == myWin[k]){
                    window.alert("You beat my stupid algorithm");
                    over = true;
                }
            }
        }
        if (!over){
            computerAI();
            me = !me;
        }
    }
}
var computerAI = function() {
    var myScore = [];
    var computerScore = [];
    var max = -1;
    var u = 0, v = 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;
        }
    }
    //evaluate
    for (var i = 0; i < 15; i++){
        for (var j = 0; j < 15; j++){
            if (0 == chessBoard[i][j]){//no chessman
                for (var k = 0; k <count; k++){
                    if (wins[i][j][k]){
                        if (1 == myWin[k]){
                            myScore[i][j] += 200;
                        } else if (2 == myWin[k]){
                            myScore[i][j] += 400;
                        } else if (3 == myWin[k]){
                            myScore[i][j] += 2000;
                        } else if (4 == myWin[k]){
                            myScore[i][j] += 10000;
                        }
                        if (1 == computerWin[k]){
                            computerScore[i][j] += 3 20;
                        } else if (2 == computerWin[k]){
                            computerScore[i][j] += 420;
                        } else if (3 == computerWin[k]){
                            computerScore[i][j] += 4200;
                        } else if (4 == computerWin[k]){
                            computerScore[i][j] += 20000;
                        }
                    }
                }
                if (myScore[i][j] > max){
                    max = myScore[i][j];
                    u = i;
                    v = j;
                } else if (myScore[i][j] == max){
                    if (computerScore[i][j] > computerScore[u][v]){
                        u = i;
                        v = j;
                    }
                }
                if (computerScore [i][j] > max){
                    max = computerScore[i][j];
                    u = i;
                    v = j;
                } else if (computerScore[i][j] == max){
                    if (myScore[i][j] > myScore[u][v]){
                        u = i;
                        v = j;
                    }
                }
            }
        }
    }
    oneStep(u, v, false);
    chessBoard[u][v]  = 2;
    //更新赢法统计数组
    for (var k = 0; k  < count; k++){
        if (wins[u][v][k]){
            computerWin[k]++;//接近胜利
            myWin[k] = 6;//设置为异常值,因为最多加到5
            if (5 == computerWin[k]){
                window.alert("stupid guy");
                over = true;
            }
        }
    }
    if (!over){
        me = !me;
    }
}

script.js

  logo.png是我用自带的画图软件随便设计的

    

  但是只要认真下,还是很容易就能赢,因为赢法数组(不懂看视频)打分还是自己随意设置的,肯定不是最科学的(这里我想是不是可以设计一套学习算法让程序自己优化打分的方案呢,可惜对这方面不是很了解,以后有机会试试),此外,这是一种很基础的AI,只考虑当前最优局势,相比什么高大上的蒙特卡洛树搜索弱爆了,所以遇到高手输是很正常的。比如

  

  总结,AI看似高大上,但是其实际是对实际问题的高度抽象、模型化以及大量计算(正是计算机的优势)。如果能缜密地设计好编码思路,那么效率就会很高,比如昨天写的贪吃蛇,很多情况没想到,所以总是陷入困境,当代码量增加,逻辑结构变的复杂时,一定要事先规划,或者说,设计模式。自己要突破目前的瓶颈期可能要学习一下这方面的东西了!!!

  此外,还利用Hbuilder生成了APP,首先是自己这么想了,然后还真找到办法实现了,所以创意,眼界,技术,同样重要。

  

  小记。

时间: 2024-08-10 00:04:21

AI五子棋------------初探的相关文章

人机ai五子棋 ——五子棋AI算法之Java实现

人机ai五子棋 下载:chess.jar (可直接运行) 源码:https://github.com/xcr1234/chess 其实机器博弈最重要的就是打分,分数也就是权重,把棋子下到分数大的地方,我获胜的概率就更大. 而在下棋过程中,大部分的点的得分都很小,或者接近,因此无需对每一个点都打分,只需要在我方附近(进攻)或者敌方附近(防守)的几个点进行打分. 具体原理大家可以看源码中的注释,说明的很清楚. 参考 http://blog.csdn.net/pi9nc/article/details

AI五子棋-第三周-需求改进&amp;系统设计

1. 需求&原型改进 根据组内成员的讨论以及老师和同学的建议,本周进行了以下的改进: 1. 改进了游戏UI的界面设计,并且对前端代码进行模块化整理,增强可读性和可维护性. 2. 对后台的游戏引擎进行改进设计,完善了游戏调度机制 3. 对人工智能算法进行了优化和改进,原先的算法因为其所需要的计算资源过大,当前场景难以达到其性能要求,无法发挥出算法的最大实力,所以完全基于AlphaZero模型算法的AI五子棋难以实现,因此我们采取了人工规则的辅助方式实现AI 2. 系统设计 系统设计如图所示 3. 

简单AI五子棋,js,canvas

新年第一篇博客,最近几天走亲访友的没有学习.今天开始进入学习模式. <!DOCTYPE html> <html> <head> <title>五子棋</title> <link rel="stylesheet" type="text/css" href="./css/style.css"> </head> <body> <canvas id=&q

机器博弈中的数据结构与基本方法(一)-----总结

一.基本概念 博弈分类:单人博弈(华容道).双人博弈(象棋.围棋).多人博弈(麻将.桥牌):完全信息博弈(象棋.围棋).不完全信息博弈(麻将.桥牌.三国杀等). 注:大一曾选修过一门课:博弈论,也在数模班做过一些博弈方面的研究,有一些基础,所以对机器博弈中博弈概念很容易就理解了.但博弈论(Game Theory)是经济学的一个重要分支(虽然我发现我们学校图书馆有关博弈论的书籍主要放在数学类书架,这也是有其原因的),主要研究的是社会两难问题(如经典的囚徒困境问题),通常是非零和博弈(即致力于出现双

一维数组建模表示二维的棋盘状态

当我们想写一个棋类游戏的时候,不难发现,很多棋类游戏的棋盘都可以用一个二维数组表示,比如: 井字棋(3*3的二维数组).黑白棋(8*8的二维数组).五子棋(15*15的二维数组)等等 使用二维数组表示棋盘,数组的下标就是棋子的坐标,数组中的值就是棋子的状态. 好处就是数据访问比较直观,可直接根据下标快速找到某个位置的棋子的状态. 但缺点也是很明显的 比如: 首先是遍历棋盘需要用双重循环处理横坐标跟纵坐标: 其次是判断棋子状态,比如以上所说的三种棋子,需要判断行.列以及斜线8个方向上的棋子状态,因

egret游戏入门之学习资源篇

最近因需要,入手H5游戏. 写游戏当然需要有引擎. H5游戏开发:游戏引擎入门推荐 如何选择 H5 游戏引擎 白鹭引擎和layabox哪个好用,哪个技术更成熟 ? LayaBox 与 Egret 选择哪个呢? Egret 4.1.6 和 LayaBox(LayaAir 2.0) 的 易用性 对比 经过初步分析和咨询,基本确认Egret和LayaAir, 个人讲真从官网和社区逛过后.真心喜欢LayaAir一些.但是最后还是选择了这一只白鹭. 要学习当然要有学习资源. Egret官网 其首页的新闻动

五子棋AI的思路

隔了一年才把AI思路给写了... 需求分析与设计方案:http://www.cnblogs.com/songdechiu/p/4951634.html 如需整个工程,移步http://download.csdn.net/detail/sdzuiaidanpianji/9452789 注:全文,都默认以黑方为己方. 一.五子棋基本棋型 参考资料:http://game.onegreen.net/wzq/HTML/142336.html 最常见的基本棋型大体有以下几种:连五,活四,冲四,活三,眠三,

C语言 AI智能,五子棋 人机对战,人人对战

C语言五子棋,人机对战,人人对战 [email protected]:~$ cat main.c  # include<stdio.h> # include<string.h> # include<stdlib.h> # define SPA 0 # define MAN 1 # define COM 2    /* 空位置设为0 ,玩家下的位置设为1 ,电脑下的位置设为2 */ int qipan[15][15];    /* 15*15的棋盘 */ int a,b,

五子棋AI算法-算杀

关于剪枝问题 前面讲到的通过Alpha-Beta剪枝和启发式搜索可以将4层搜索的平均时间降低到1秒以下.只有这两个优化方式其实目前最多可以做到6层搜索,就是把AI和玩家各向后推算三步. 6层搜索的棋力其实相当弱,碰到经常玩五子棋的人基本都会输,更不要说对五子棋有研究的玩家.以目前的平均一个节点有50个子节点的搜索方式,把搜索效率提高50倍则可以增加一层搜索深度.而除了前面讲到的AlphaBeta剪枝和启发式搜索,其他的剪枝算法基本都是非安全剪枝.也就是说后序我们会使用一些非安全的剪枝算法来提升搜