编辑

编辑

后续问题上一个问题绘制井字游戏棋盘。

这个问题类似于这个但是由于谢布·格拉夫创建了这样一个易于理解且易于定制的图形,其他人肯定也可以从中受益。

目标是创建一个井字游戏的部分博弈树来解释类似下图的 Minimax 算法。下图来自 Russel 和 Norvig 1995 年的《人工智能 - 现代方法》。

图片来自 Russel Norvig “人工智能

编辑

在 SebGlav 告诉我 tikzpictures 不能嵌套后,我决定使用上面提到的老问题并能创建下面的图形。 我现在的树

仍有以下问题我不知道如何解决:

  1. 我想在右侧添加文本,例如 MAX(X)、TERMINAL 等。
  2. 目前我不知道如何正确显示这些点,所以我写了“子点”作为占位符
  3. “子点”节点的边缘与板节点重叠 - 我认为这是因为文本和板节点是居中对齐的

由于其中两个问题与点有关,因此我尝试创建一种与旧问题中使用的Dots风格类似的风格(?) 。TTT

这是我的代码:

\documentclass{standalone}
\usepackage{tikz}
\usepackage{forest,calc}
\forestset{
  make tab/.style args={#1:#2:#3/#4:#5:#6/#7:#8:#9}{%
    content={%
      \tabcolsep=.6\tabcolsep
      \begin{tabular}{p{\widthof{x}}|p{\widthof{x}}|p{\widthof{x}}}
        #1 & #2 & #3\\\hline#4&#5&#6\\\hline#7&#8&#9
      \end{tabular}}},
  label position r/.initial=right,
  label position b/.initial=below
}
\begin{document}
\begin{forest}
  TTT/.style args={#1:#2}{
    make tab/.expanded=\forestove{content},
     label={\pgfkeysvalueof{/forest/label position #1}:$#2$}
  },
  TTT*/.style={
    make tab=::/::/::,
    content/.expand once=%
    \expandafter\vphantom\expandafter{\romannumeral-`0\forestov{content}},
    draw=none,
    append after command={(\tikzlastnode.north) edge (\tikzlastnode.south)},
    for descendants={before computing xy={l*=1.2}},
  },
  Dots/.style={
  draw=none,
  },
  th/.style=thick,
  for tree={node options=draw, inner sep=+0pt, parent anchor=south, child anchor=north}
%
[::/::/::, TTT=r:
 [x::/::/::, for tree={calign=child, calign child=1},TTT=r:
   [x:o:/::/::,TTT=b:
     [x:o:x/::/::,TTT=b:
       [child dots, Dots
       [x:o:x/:o:x/:o:, TTT=b:-1]
       ]
       [child dots, Dots
       [x:o:x/o:o:x/x:x:o, TTT=b:0]
       ]
       [child dots, Dots
       [x:o:x/:x:/x:o:o, TTT=b:1]
       ]
       [child dots, Dots
       [child dots terminal, Dots]
       ]
     ]
     [x:o:/x::/::, TTT=b:]
     [x:o:/:x:/::, TTT=b:]
     [child dots, Dots]
   ]
   [x::o/::/::, TTT=b:]
   [x::/o::/::, TTT=b:]
   [child dots, Dots]
]
 [:x:/::/::, TTT=r:]
 [::x/::/::, TTT=r:]
 [::/x::/::, TTT=r:]
 [::/:x:/::, TTT=r:]
 [::/::x/::, TTT=r:]
 [::/::/x::, TTT=r:]
 [::/::/:x:, TTT=r:]
 [::/::/::x, TTT=r:]
]
\end{forest}


\end{document}
%   [,TTT* % this is just cheating :( to skip a level and go beneath
%     [o::/:x:/::, TTT=b:1]
%     [:o:/:x:/::, TTT=b:2]
%   ]

答案1

但是,有些基本的东西并不清楚,有些手册很阴暗,每个节点都可以命名,然后用作点来详细说明或使用箭头、文本等关联它们。在“...”的情况下,只需使用,然后您可以使用、和\dots来增加文本框的大小以Dots/style...匹配其他样式的大小。inner sepouter sep

结果:

在此处输入图片描述

梅威瑟:

\documentclass[tikz,border=10pt]{standalone}
\usepackage{forest,calc}
\forestset{
    make tab/.style args={#1:#2:#3/#4:#5:#6/#7:#8:#9}{%
        content={%
            \tabcolsep=.6\tabcolsep
            \begin{tabular}{p{\widthof{x}}|p{\widthof{x}}|p{\widthof{x}}}
                #1 & #2 & #3\\\hline#4&#5&#6\\\hline#7&#8&#9
    \end{tabular}}},
    label position r/.initial=right,
    label position b/.initial=below
}
\begin{document}
    \begin{forest}
        TTT/.style args={#1:#2}{
            make tab/.expanded=\forestove{content},
            label={\pgfkeysvalueof{/forest/label position #1}:$#2$}
        },
        TTT*/.style={
            make tab=::/::/::,
            content/.expand once=%
            \expandafter\vphantom\expandafter{\romannumeral-`0\forestov{content}},
            draw=none,
            append after command={(\tikzlastnode.north) edge (\tikzlastnode.south)},
            for descendants={before computing xy={l*=1.2}},
        },
        Dots/.style={
            draw=none,
            outer sep=20pt %addet this to increase the text node box, that was erased by draw=none
        },
        th/.style=thick,
        for tree={node options=draw, inner sep=+0pt, parent anchor=south, child anchor=north}
        %
        [::/::/::,name=box0, TTT=r:
        [x::/::/::,name=box1, for tree={calign=child, calign child=1},TTT=r:
        [x:o:/::/::,name=box2,TTT=b:
        [x:o:x/::/::,name=box3,TTT=b:
        [\dots, Dots
        [x:o:x/:o:x/:o:,name=box4,TTT=b:-1]
        ]
        [\dots, Dots
        [x:o:x/o:o:x/x:x:o, TTT=b:0]
        ]
        [\dots, Dots
        [x:o:x/:x:/x:o:o, TTT=b:1]
        ]
        [\dots, Dots
        [\dots, Dots]
        ]
        ]
        [x:o:/x::/::, TTT=b:]
        [x:o:/:x:/::, TTT=b:]
        [\dots, Dots]
        ]
        [x::o/::/::, TTT=b:]
        [x::/o::/::, TTT=b:]
        [\dots, Dots]
        ]
        [:x:/::/::, TTT=r:]
        [::x/::/::, TTT=r:]
        [::/x::/::, TTT=r:]
        [::/:x:/::, TTT=r:]
        [::/::x/::, TTT=r:]
        [::/::/x::, TTT=r:]
        [::/::/:x:, TTT=r:]
        [::/::/::x, TTT=r:]
        ]
        \draw(box1.center)++ (-2,0)node(node-name1)[]{MIN (O)};
        \draw(node-name1.center|-box0)node{MAX(X)};
        \draw(box2.center)++ (-2,0)node{MAX (X)};
        \draw(box3.center)++ (-2,0)node{MIN (O)};
        \draw(box4.center)++ (-2,0)node(node-name2){TERMINAL};
        \draw(node-name2.center)++ (0,-1)node{Utility};
    \end{forest}
    
\end{document}

附录:

当然,有些人可能会对从可以作为固定图形导入的图像编写代码感到恼火,但这样做的目的是为了学习并能够定制,但是如果您使用像森林这样的框架来保存代码以获得复杂的地图,您可能会牺牲通过嵌套和自动化代码可以进行的定制,最终这是一个品味问题。

相关内容