前往我的主页以获得更好的阅读体验人工智能基础-极大极小策略 - DearXuan的主页https://blog.dearxuan.com/2021/11/13/%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD%E5%9F%BA%E7%A1%80-%E6%9E%81%E5%A4%A7%E6%9E%81%E5%B0%8F%E7%AD%96%E7%95%A5/

博弈论

博弈论是现代数学的一个分支,是用于研究竞争现象的数学工具。博弈策略是一套考虑到所有可能的情况而做出的行动。博弈论在人工智能方面有极大的价值。

零和博弈

在零和博弈,双方的总利益为0,其中一方为了自己利益最大化,必须损失另一方的利益。正如棋局中,一方赢了,则另一方必定输了,则利益之和为 1+(-1)=0

这就要求,任意一方都要使自己利益最大化,同时使对方利益最小化。因此在决策时,不能只考虑自己的最大利益,还需要考虑对方做出的对自己最不利的选择

极大极小策略

极大极小方法是分析零和博弈问题时的一种策略,在对局制游戏中,每个参与者都会做出对自己最有利,同时也是对对方最不利的选择。

在下棋时,每一个棋盘布局都可以表示为一个节点,相邻的节点形成多叉树。每种布局都会对一方有利而对另一方不利,称节点的有利程度为价值

假设人类与计算机进行对决,并假设人类绝对聪明,那么在人类的回合,他会选择对计算机最不利的棋局,也就是价值最低的节点。而计算机则会选择对自己价值最高的节点。

假设各节点的价值如下

决策过程如下:

  1. 计算机选择对自己有利的节点:10→17
  2. 人类选择对计算机不利的节点:17→8
  3. 计算机选择对自己有利的节点:8→11
  4. 人类……

称这种在最大和最小值之间不断切换的决策过程为极大极小策略

这是一种保守策略,因为计算机不会尝试冒险,它会假设人类每次都做出对自己最不利的选择,从而保证自己最后得到节点价值不至于太低

井字棋算法

棋局

用TicTac类表示棋局,用数组保存棋子

/// <summary>
/// 棋子
/// </summary>
public static class Player
{public const int Non = 0;public const int Computer = 1;public const int Human = -1;
}
public class TicTac
{public int num { get; set; }= 0;/// <summary>/// 棋盘布局/// </summary>public int[,] chess { get; } = new int[,]{{0, 0, 0},{0, 0, 0},{0, 0, 0}};public TicTac(){}public TicTac(TicTac copyFrom){for (int i = 0; i < 3; i++){for (int j = 0; j < 3; j++){chess[i, j] = copyFrom.chess[i, j];}}num = copyFrom.num;}/// <summary>/// 放下棋子/// </summary>/// <param name="i">位置</param>/// <param name="j">位置</param>/// <param name="player">棋手</param>/// <returns>结果</returns>public bool DropDown(int i, int j, int player){if (chess[i, j] == Player.Non){chess[i, j] = player;num++;return true;}return false;}/// <summary>/// 拿起棋子/// </summary>/// <param name="i">位置</param>/// <param name="j">位置</param>/// <returns>结果</returns>public bool PickUp(int i, int j){if (chess[i, j] != Player.Non){chess[i, j] = Player.Non;num--;return true;}return false;}/// <summary>/// 返回获胜者/// </summary>/// <returns>获胜者</returns>public int GetWinner(){//检查胜者只需要判断三格数字之和是否为 ±3//检查行if (Math.Abs(chess[0, 0] + chess[1, 0] + chess[2, 0]) == 3) return chess[0, 0];if (Math.Abs(chess[0, 1] + chess[1, 1] + chess[2, 1]) == 3) return chess[0, 1];if (Math.Abs(chess[0, 2] + chess[1, 2] + chess[2, 2]) == 3) return chess[0, 2];//检查列if (Math.Abs(chess[0, 0] + chess[0, 1] + chess[0, 2]) == 3) return chess[0, 0];if (Math.Abs(chess[1, 0] + chess[1, 1] + chess[1, 2]) == 3) return chess[1, 0];if (Math.Abs(chess[2, 0] + chess[2, 1] + chess[2, 2]) == 3) return chess[2, 0];//检查对角线if (Math.Abs(chess[0, 0] + chess[1, 1] + chess[2, 2]) == 3) return chess[0, 0];if (Math.Abs(chess[0, 2] + chess[1, 1] + chess[2, 0]) == 3) return chess[0, 2];//没有胜者return Player.Non;}public bool isEnd(){if (GetWinner() != Player.Non || num == 9){return true;}else{return false;}}
}

回合

用节点表示一个回合,节点包括棋局,价值,子节点,棋手,落子位置

其中子节点包含了当前回合后所有可能的情况,棋手是当前回合轮到的棋手,落子位置是上一回合的棋手下的最后一步棋位置

/// <summary>
/// 节点类
/// </summary>
public class Node
{/// <summary>/// 棋局/// </summary>public TicTac ticTac;/// <summary>/// 价值/// </summary>private int? value = null;/// <summary>/// 子节点/// </summary>public List<Node> childNodes = null;/// <summary>/// 棋手/// </summary>public int player = Player.Non;public Point lastDrop = null;private Node(){}public Node(TicTac ticTac, int player){Debug.Assert(player == Player.Computer || player == Player.Human);this.ticTac = new TicTac(ticTac);this.player = player;GetValue();}public Node(Node lastNode, Point drop){this.ticTac = new TicTac(lastNode.ticTac);this.player = -lastNode.player;this.lastDrop = drop;ticTac.DropDown(drop.i, drop.j, lastNode.player);GetValue();}/// <summary>/// 计算当前节点的价值/// 如果棋手是电脑,则返回子节点的最大价值/// 如何棋手是人类,则返回子节点的最小价值/// </summary>public int GetValue(){//已经计算过价值if (value != null) return (int) value;//胜负已分int winner = ticTac.GetWinner();if (winner != Player.Non){value = winner == Player.Computer ? 10 : -10;return (int) value;}//棋盘已满if (ticTac.num == 9){value = 0;return (int) value;}//子节点没有初始化,构造子节点if (childNodes == null){childNodes = new List<Node>();for (int i = 0; i < 3; i++){for (int j = 0; j < 3; j++){if (ticTac.chess[i, j] == Player.Non){Node child = new Node(this, new Point(i, j));childNodes.Add(child);}}}}if (player == Player.Computer){//当前棋手是电脑,返回最大价值int maxValue = Int32.MinValue;//从子节点的最小价值里查找最大值foreach (Node item in childNodes){if (item.GetValue() > maxValue){maxValue = item.GetValue();}}value = maxValue;}else{int minValue = Int32.MaxValue;foreach (Node item in childNodes){if (item.GetValue() < minValue){minValue = item.GetValue();}}value = minValue;}return (int) value;}public Node SearchChildByPoint(int i, int j){foreach (Node item in childNodes){if (item.lastDrop.i == i && item.lastDrop.j == j) return item;}return null;}
}

棋局价值

对于一种棋局,如果游戏已经结束,那么根据获胜者来计算价值。如果获胜者为电脑,则价值为10;如果获胜者为人类,则价值为-10;如果平局,则价值为0

如果游戏尚未结束,则在棋局上所有空位置落子,并得到所有可能的子节点。如果当前棋手是人类,则该节点的价值是子节点的价值的最小值,因为人类会做出对计算机最不利的选择。如果当前棋手是电脑,则该节点的价值是子节点的价值的最大值,因为电脑会做出对自己最有利的选择。

下棋代码

public class Point
{public int i { get; set; }public int j { get; set; }public Point(int i, int j){this.i = i;this.j = j;}
}class Program
{private const string space = " ";private static Node node;static void Main(string[] args){Play();}static void Play(){Console.Write("先手方为(1:电脑, 0:人类):");int start = int.Parse(Console.ReadLine());//初始化头节点Console.WriteLine("正在初始化...");node = new Node(new TicTac(), start == 1 ? Player.Computer : Player.Human);Console.WriteLine("初始化结束...");Point drop = null;while (!node.ticTac.isEnd()){if (node.player == Player.Computer){drop = WaitComputerDrop();}else{drop = WaitHumanDrop();}Drop(drop.i, drop.j);}Console.WriteLine("游戏结束,比赛结果");switch (node.ticTac.GetWinner()){case Player.Computer:Console.WriteLine("电脑获胜!");break;case Player.Human:Console.WriteLine("人类获胜!");break;case Player.Non:Console.WriteLine("平局!");break;}}static void PrintTicTac(){for (int i = 0; i < 3; i++){for (int j = 0; j < 3; j++){string s;switch (node.ticTac.chess[i, j]){case Player.Computer:s = "0";break;case Player.Human:s = "1";break;default:s = "x";break;}Console.Write(s + space);}Console.WriteLine();}}static Point WaitHumanDrop(){Console.WriteLine("请输入落子位置[1~3,1~3],例如: 2,3");string line = Console.ReadLine();string[] s = line.Split(",");Point p = new Point(int.Parse(s[0]) - 1, int.Parse(s[1]) - 1);return p;}static Point WaitComputerDrop(){Node maxNode = null;int MaxValue = Int32.MinValue;foreach (Node item in node.childNodes){if (item.GetValue() > MaxValue){maxNode = item;MaxValue = item.GetValue();}}return new Point(maxNode.lastDrop.i, maxNode.lastDrop.j);}static void Drop(int i, int j){Console.WriteLine("------------");Console.Write("棋手:" + (node.player == Player.Computer ? "电脑" : "人类") + ",");node = node.SearchChildByPoint(i, j);Console.WriteLine("落子点:(" + (i+1) + "," + (j+1) + ")");PrintTicTac();Console.WriteLine("------------");}
}

人工智能基础-极大极小策略相关推荐

  1. 理解与理论:人工智能基础问题的悲观与乐观

    来源:筑土为坛 梅剑华,男,1980年生,湖北秭归人,山西大学哲学社会学院教授,博士生导师,先后赴美国罗格斯大学.匹兹堡大学.奥地利萨尔茨堡大学等访学,研究方向是语言哲学与心灵哲学.实验哲学与认知科学 ...

  2. AI 人工智能基础及应用

    一.人工智能概述 1. 简史 2. 应用领域 安防 实时从视频中检测出行人和车辆. 自动找到视频中异常的行为(比如,醉酒的行人或者逆行的车辆),并及时发出带有具体地点方位信息的警报. 自动判断人群的密 ...

  3. Python人工智能基础到实战课程-北方网视频

    ** Python人工智能基础到实战课程 ** 课程主要分为6大模块,带领大家逐步进步人工智能与数据科学领域. 第一阶段:Python语言及其数据领域工具包使用 本阶段旨在帮助大家快速掌握数据领域最常 ...

  4. 首部高中《人工智能基础》教材问世,40家中学引入

     整理 | 阿司匹林 出品 | AI科技大本营(公众号ID:rgznai100) 随着人工智能逐渐上升为国际竞争的新焦点,AI 人才短缺也日益凸显,全球对于人工智能基础教育的呼声不断.国务院印发的 ...

  5. UC伯克利教授Stuart Russell人工智能基础概念与34个误区

    来源:数据简化DataSimp 数据简化DataSimp导读:UC伯克利教授StuartRussell人工智能基础概念与34个误区,Russell是加州大学伯克利分校人工智能系统中心创始人兼计算机科学 ...

  6. 综述 | 联邦学习-新兴的人工智能基础技术

    点上方蓝字计算机视觉联盟获取更多干货 在右上方 ··· 设为星标 ★,与你不见不散 编辑:Sophia 计算机视觉联盟  报道  | 公众号 CVLianMeng 转载于 :arivx, 专知 [人工 ...

  7. 大学计算机与人工智能基础课后答案,好书推荐 | 人工智能基础及应用

    原标题:好书推荐 | 人工智能基础及应用 扫码优惠购书 内容简介 本书主要介绍与人工智能相关的一些基础知识,全书共9 章.第1 章简要介绍人工智能的发展历史及国内外研究现状,第2 章详细给出学习人工智 ...

  8. 你不得不了解的人工智能基础知识

    你不得不了解的人工智能基础知识 1.什么是人工智能? 首先我们利用传统的软件和人工智能进行比较,就容易使大家更容易理解. (1) 传统软件 VS 人工智能 传统软件是[基于规则]的,需要人为的设定条件 ...

  9. UC伯克利教授Stuart Russell人工智能基础概念与34个误区 (公号回复“AI基础概念”可下载PDF资料)

    UC伯克利教授Stuart Russell人工智能基础概念与34个误区 (公号回复"AI基础概念"可下载PDF资料) 秦陇纪 数据简化DataSimp 今天 数据简化DataSim ...

最新文章

  1. python stm32-实现Python与STM32通信方式
  2. 转Python 参数知识(变量前加星号的意义)
  3. 计算机编程英文术语,计算机编程英语词汇
  4. 442. 数组中重复的数据
  5. MarkDown页面添加锚点,跳转到本页指定位置
  6. python3(二)Numpy
  7. linux内存回收机制
  8. 爬虫技巧:在pycharm 下 调试 scrapy项目
  9. 安装 Python 包时解决 Microsoft visual c++ 14.0 is required 问题
  10. activemq发布订阅
  11. 编程让鼠标一直动_华硕、罗技、海盗船无线鼠标选哪个?
  12. 怎样的高管才能得到下属的信任?
  13. 转:什么是Node.js?
  14. 7k7k游戏盒与逗游游戏库,你更喜欢哪个
  15. 华为顶级黑客整理的399本编程电子书,整整16个G,你想学的都有
  16. 双硬盘双系统解决引导在同一个分区的问题
  17. 计算机操作系统-4-设备管理
  18. python怎么弄成黑色背景图片_python 实现将小图片放到另一个较大的白色或黑色背景图片中...
  19. 多元函数泰勒级数展开_二元函数的泰勒展开二元函数的泰勒展开.pdf
  20. 唯品会还“品“的动吗?

热门文章

  1. LINUX服务器的配置
  2. AD18输出BOM表
  3. element-ui trr树形结构点击当前背景再点击其它地方会消失问题解决,以及修改当前背景色。
  4. OpenGL ES2.0 – Iphone开发指引
  5. EKT,又一个以太坊的挑战者?
  6. c# wpf 单选字体_WPF中的字体改善
  7. UJN_DS实验和作业(仅供参考)
  8. 网络访问控制PC 准入机制
  9. MDCC 主题论坛:HTML5Web App
  10. 省消协历数苹果维修十宗罪:更换强制留旧件