unity2018.4.3f1实现五子棋游戏(八)

一、AI原理

当我们人在下棋的时候,我们根据当前棋局的变化,做出防守和攻击的策略。如果不用堵对手的棋子,我们都想下在那个能我方快速连成5子的地方。我们肉眼看见,三子连珠我们肯定会去防,看见两子连珠却无动于衷,那是因为我们脑海里面装了评分表,不同棋型对应不同的分数,取最大的分数。人类有时会失误,因为不是所有人都有比较强的抽象能力,下棋可以看很多步的。

那我们就是要用代码告诉电脑当前的棋型是怎么样的,如果电脑来下,最佳下在那里,然后让电脑去评分表里面找对应的权值,查字典,这就攻击值;然后找站在对手的角度来看,对手最会下的位置在哪,去评分表找出权值,这个叫防守值。比较两值大小,取值最大的点着子

如果只看一步,那就止于当前了。我们肯定是想让AI更聪明,下起来才有意思。那AI就要这样来思考了,像人一样,如果我把棋下在这里,那对手肯定也是想下在对他自己最有利对我最不利的地方,那他下了以后,我再下对自己最有利对他最不利的地方,如此类推,递归下去。

五子棋是15x15,也就是说最多也就是7层,对整个棋盘进行遍历,除了已经落子的地方,假设下下去,并且假设对手做出最佳的策略,然后比较每条路得到的权值,取权值最大的

二、评分表

五子棋棋型参考:https://www.cnblogs.com/songdechiu/p/5768999.html

protected Dictionary<string, float> toScore = new Dictionary<string, float>();

就是一个字符串对应一个值
比如“aa_” 代表两子连珠,左边堵死,右边空
“_aa” 代表两子连珠,右边堵死,左边空
“_aa” 代表两子连珠,左右边空
“aa” 代表两子连珠,左右边非空,这个没有意义,不必计入表中
“a_a” 代表两子中间空

三、AI难度选择

如果一个人知道的棋型越多,水平肯定越高。
如果一个人下棋看到的深度越深,水平也是越高

1、决定因素

那电脑的难度,取决于评分表全面度
那电脑的看棋深度,取决于扫棋方式,

2、简单模式

他继承于之前那个玩家下棋的类

public class AILevelOne : Player {

比如简单模式的扫棋,不考虑棋子中间存在未落子的情况,
只考虑这种:
在这里插入图片描述

评分表:

		toScore.Add("aa_", 50);
        toScore.Add("_aa", 50);
        toScore.Add("_aa_", 100);

        toScore.Add("_aaa_", 1000);
        toScore.Add("aaa_", 500);
        toScore.Add("_aaa", 500);

        toScore.Add("_aaaa_", 10000);
        toScore.Add("aaaa_", 5000);
        toScore.Add("_aaaa", 5000);

        toScore.Add("aaaaa", float.MaxValue);
        toScore.Add("aaaaa_", float.MaxValue);
        toScore.Add("_aaaaa", float.MaxValue);
        toScore.Add("_aaaaa_", float.MaxValue);

扫棋方法

public virtual void CheckOneLine(int[] pos, int[] offset,int chess)
    {
        string str = "a";
        //右边
        for (int i = offset[0], j = offset[1]; (pos[0] + i >= 0 && pos[0] + i < 15) &&
            pos[1] + j >= 0 && pos[1] + j < 15; i += offset[0], j += offset[1])
        {
            if (ChessBoard.Instacne.grid[pos[0] + i, pos[1] + j] ==chess)
            {
                str += "a";

            }
            else if (ChessBoard.Instacne.grid[pos[0] + i, pos[1] + j] == 0)
            {
                str += "_";
                break;
            }
            else
            {
                break;
            }
        }
        //左边
        for (int i = -offset[0], j = -offset[1]; (pos[0] + i >= 0 && pos[0] + i < 15) &&
            pos[1] + j >= 0 && pos[1] + j < 15; i -= offset[0], j -= offset[1])
        {
            if (ChessBoard.Instacne.grid[pos[0] + i, pos[1] + j] == chess)
            {
                str = "a" + str;

            }
            else if (ChessBoard.Instacne.grid[pos[0] + i, pos[1] + j] == 0)
            {
                str = "_" +str;
                break;
            }
            else
            {
                break;
            }
        }


        if (toScore.ContainsKey(str))
        {
            score[pos[0], pos[1]] += toScore[str];
        }

    }

3、困难模式

这个C#文件的类继承于简单模式,然后对评分表和扫棋模式进行重写

public class AILevelTwo : AILevelOne 

在这里插入图片描述

评分表:

		toScore.Add("aa___", 100);                      //眠二
        toScore.Add("a_a__", 100);
        toScore.Add("___aa", 100);
        toScore.Add("__a_a", 100);
        toScore.Add("a__a_", 100);
        toScore.Add("_a__a", 100);
        toScore.Add("a___a", 100);


        toScore.Add("__aa__", 500);                     //活二 "_aa___"
        toScore.Add("_a_a_", 500);
        toScore.Add("_a__a_", 500);

        toScore.Add("_aa__", 500);
        toScore.Add("__aa_", 500);


        toScore.Add("a_a_a", 1000);                     // bool lfirst = true, lstop,rstop = false  int AllNum = 1
        toScore.Add("aa__a", 1000);
        toScore.Add("_aa_a", 1000);
        toScore.Add("a_aa_", 1000);
        toScore.Add("_a_aa", 1000);
        toScore.Add("aa_a_", 1000);
        toScore.Add("aaa__", 1000);                     //眠三

        toScore.Add("_aa_a_", 9000);                    //跳活三
        toScore.Add("_a_aa_", 9000);

        toScore.Add("_aaa_", 10000);                    //活三       


        toScore.Add("a_aaa", 15000);                    //冲四
        toScore.Add("aaa_a", 15000);                    //冲四
        toScore.Add("_aaaa", 15000);                    //冲四
        toScore.Add("aaaa_", 15000);                    //冲四
        toScore.Add("aa_aa", 15000);                    //冲四        


        toScore.Add("_aaaa_", 1000000);                 //活四

        toScore.Add("aaaaa", float.MaxValue);           //连五

扫棋方法

public override void CheckOneLine(int[] pos, int[] offset, int chess)
    {
        bool lfirst = true, lstop= false, rstop = false;
        int AllNum = 1;
        string str = "a";
        int ri = offset[0], rj = offset[1];
        int li = -offset[0], lj = -offset[1];
        while (AllNum<7 && (!lstop||!rstop))
        {
            if (lfirst)
            {
                //左边
                if ((pos[0] + li >= 0 && pos[0] + li < 15) &&
            pos[1] + lj >= 0 && pos[1] + lj < 15 && !lstop)
                {
                    if (ChessBoard.Instacne.grid[pos[0] + li, pos[1] + lj] == chess)
                    {
                        AllNum++;
                        str = "a" + str;

                    }
                    else if(ChessBoard.Instacne.grid[pos[0] + li, pos[1] + lj] == 0)
                    {
                        AllNum++;
                        str = "_" + str;
                        if(!rstop) lfirst = false;
                    }
                    else
                    {
                        lstop = true;
                        if (!rstop) lfirst = false;
                    }
                    li -= offset[0]; lj -= offset[1];
                }
                else
                {
                    lstop = true;
                    if (!rstop) lfirst = false;
                }
            }
            else
            {
                if ((pos[0] + ri >= 0 && pos[0] + ri < 15) &&
          pos[1] + rj >= 0 && pos[1] + rj < 15 && !lfirst && !rstop)
                {
                    if (ChessBoard.Instacne.grid[pos[0] + ri, pos[1] + rj] == chess)
                    {
                        AllNum++;
                        str += "a" ;

                    }
                    else if (ChessBoard.Instacne.grid[pos[0] + ri, pos[1] + rj] == 0)
                    {
                        AllNum++;
                        str += "_" ;
                        if (!lstop) lfirst = true;
                    }
                    else
                    {
                        rstop = true;
                        if (!lstop) lfirst = true;
                    }
                    ri += offset[0]; rj += offset[1];
                }
                else
                {
                    rstop = true;
                    if (!lstop) lfirst = true;
                }
            }
        }

        string cmpStr = "";
        foreach (var keyInfo in toScore)
        {
            if (str.Contains(keyInfo.Key))
            {
                if(cmpStr != "")
                {
                    if(toScore[keyInfo.Key] > toScore[cmpStr])
                    {
                        cmpStr = keyInfo.Key;
                    }
                }
                else
                {
                    cmpStr = keyInfo.Key;
                }
            }
        }

        if(cmpStr!= "")
        {
            score[pos[0], pos[1]] += toScore[cmpStr];
        }
    }

活二可能包含眠二,这些棋型不是完全唯一的,所以我们要搞一个记录值记录一下,

4、炼狱模式

这个比两个都复杂很多,单独写博客说
要涉及到极小值极大值算法,Alpha-Beta算法等
目前就已经实现了双人对战,单机模式下的简单和困难。

接下来先把游戏开始结束动画,模式选择整一下,看起来像一个正常的游戏,后面可以再加入炼狱模式,局域网下棋,联网模式等等

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xiaoduangg

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值