![有任何用于排版多边形/俄罗斯方块形状的软件包吗?](https://linux22.com/image/267006/%E6%9C%89%E4%BB%BB%E4%BD%95%E7%94%A8%E4%BA%8E%E6%8E%92%E7%89%88%E5%A4%9A%E8%BE%B9%E5%BD%A2%2F%E4%BF%84%E7%BD%97%E6%96%AF%E6%96%B9%E5%9D%97%E5%BD%A2%E7%8A%B6%E7%9A%84%E8%BD%AF%E4%BB%B6%E5%8C%85%E5%90%97%EF%BC%9F.png)
我想排版一些简单的多格拼图,因此需要一个合适的 LaTeX 包。我找不到易于使用的包(当然,除了使用 TikZ)。除了使用 TikZ/PSTricks 之外,还有其他方法吗?
对于那些不知道多格骨牌是什么的人来说: http://en.wikipedia.org/wiki/Polyomino
编辑:对于多格骨牌拼图,我的意思是这样的: http://www.virtualimage.co.uk/html/polyomino.html
所以我的目的是将一组多格骨牌放入给定的形状。
答案1
代码 1
\documentclass[tikz,border=2pt]{standalone}
\usetikzlibrary{matrix}
\makeatletter
\newcounter{qrr@tikz@omino}
\newcounter{qrr@tikz@omino@up}
\newcounter{qrr@tikz@omino@right}
\tikzset{
omino/.style={/tikz/omino/.cd,#1},
omino/distance/.initial=1,
omino/radius/.initial=.5,
omino/at/.style={/tikz/shift={(#1)}},
omino/rotate/.style={/tikz/rotate=#1},
omino/s/.code=
\setcounter{qrr@tikz@omino}{0}%
\setcounter{qrr@tikz@omino@up}{0}%
\setcounter{qrr@tikz@omino@right}{0}%
\pgfkeysalso{/tikz/insert path={(0,0) node[/tikz/omino/nodes/.try,/tikz/omino/node normal/.try,/tikz/omino/node start/.try] {\qrr@tikz@omino@text@start}}},
omino/u/.code=%
\stepcounter{qrr@tikz@omino}%
\stepcounter{qrr@tikz@omino@up}%
\pgfkeysalso{/tikz/insert path={
to[/tikz/omino/how] ++(up:#1)
node[/tikz/omino/nodes/.try,/tikz/omino/node normal/.try,/tikz/omino/node up/.try]{\qrr@tikz@omino@text@up}}},
omino/d/.code=%
\stepcounter{qrr@tikz@omino}%
\addtocounter{qrr@tikz@omino@up}{-1}%
\pgfkeysalso{/tikz/insert path={
to[/tikz/omino/how] ++(down:#1)
node[/tikz/omino/nodes/.try,/tikz/omino/node normal/.try,/tikz/omino/node down/.try]{\qrr@tikz@omino@text@down}}},
omino/l/.code=%
\stepcounter{qrr@tikz@omino}%
\addtocounter{qrr@tikz@omino@right}{-1}%
\pgfkeysalso{/tikz/insert path={
to[/tikz/omino/how] ++(left:#1)
node[/tikz/omino/nodes/.try,/tikz/omino/node normal/.try,/tikz/omino/node left/.try]{\qrr@tikz@omino@text@left}}},
omino/r/.code=%
\stepcounter{qrr@tikz@omino}%
\stepcounter{qrr@tikz@omino@right}%
\pgfkeysalso{/tikz/insert path={
to[/tikz/omino/how] ++(right:#1)
node[/tikz/omino/nodes/.try,/tikz/omino/node normal/.try,/tikz/omino/node right/.try] {\qrr@tikz@omino@text@right}}},
omino/u/.default=\pgfkeysvalueof{/tikz/omino/distance},
omino/d/.default=\pgfkeysvalueof{/tikz/omino/distance},
omino/l/.default=\pgfkeysvalueof{/tikz/omino/distance},
omino/r/.default=\pgfkeysvalueof{/tikz/omino/distance},
omino/how/.style=,
omino/reset/.code=
\pgfutil@in@_{#1}%
\ifpgfutil@in@
\qrr@tikz@omino@split#1\relax
\else
\edef\pgf@tempa{\csname qrr@tikz@omino@coords@#1\endcsname}%
\expandafter\qrr@tikz@omino@split\pgf@tempa\relax
\fi
\pgfkeysalso{/tikz/insert path={(omino-n-#1.center) node[/tikz/omino/nodes/.try, /tikz/omino/node reset/.try] {\qrr@tikz@omino@text@reset}}},
omino/do/.code={\@tfor\@next:=#1\do{\pgfkeysalso{/tikz/omino/\@next}}},
omino/node reset/.style={draw=none,fill=none},
omino/node normal/.style={
name=omino-n-\number\c@qrr@tikz@omino,
alias=omino-n-\number\c@qrr@tikz@omino@right_\number\c@qrr@tikz@omino@up,
omino/@store coords
},
omino/@store coords/.code=
\expandafter\xdef\csname qrr@tikz@omino@coords@\arabic{qrr@tikz@omino}\endcsname
{\number\c@qrr@tikz@omino@right_\number\c@qrr@tikz@omino@up},
omino/Text/.code 2 args=\expandafter\edef\csname qrr@tikz@omino@text@#1\endcsname{#2},
omino/Text={up}{},omino/Text={down}{},omino/Text={left}{},omino/Text={right}{},omino/Text={start}{},omino/Text={reset}{}
}
\def\qrr@tikz@omino@split#1_#2\relax{\setcounter{qrr@tikz@omino@right}{#1}\setcounter{qrr@tikz@omino@up}{#2}}
\tikzset{
omino/x mirror/.style={/tikz/cm={-1,0,0,1,(0,0)}},
omino/y mirror/.style={/tikz/cm={1,0,0,-1,(0,0)}}
}
\tikzset{fun/.code={\pgfmathtruncatemacro\@fun{\number\c@qrr@tikz@omino/4*100}\pgfkeysalso{fill=blue!\@fun!red}}}
\makeatother
\tikzset{
tetris/.style={/tikz/tetris/.cd,#1},
tetris/1/.style={/tikz/omino={do=suuu}},
tetris/2/.style={/tikz/omino={do=suur}},
tetris/2'/.style={/tikz/omino/x mirror, 2},
tetris/3/.style={/tikz/omino={do=suru}},
tetris/3'/.style={/tikz/omino/x mirror, 3},
tetris/4/.style={/tikz/omino={do=surd}},
tetris/5/.style={/tikz/omino={s,u,u,reset=1,r}}
}
\makeatletter
\makeatother
\newcommand*{\thesamepictureeverywhere}{\matrix[column sep=.5cm, row sep=.5cm, ampersand replacement=\&] {
\path [tetris=1]; \&
\path [tetris=2']; \& \path [tetris=2]; \\
\path [tetris=3]; \& \path [tetris=3']; \&
\path [tetris=4]; \&
\path [tetris=5];\\};}
\begin{document}
\begin{tikzpicture}[
every path/.style=draw,
omino/how/.style={bend left},
omino/nodes/.style={circle, inner sep=+0pt, minimum size=+4pt, fill=black, outer sep=+0pt}]
\thesamepictureeverywhere
\end{tikzpicture}
\begin{tikzpicture}[omino/nodes/.style={rectangle, inner sep=+0pt, minimum size=+1cm, draw}]
\thesamepictureeverywhere
\end{tikzpicture}
\begin{tikzpicture}[omino={
nodes/.style={circle, inner sep=+0pt, minimum size=+1cm, draw},
Text={left}l,Text={right}r,Text={up}u,Text={down}d,Text={start}s
}]
\thesamepictureeverywhere
\end{tikzpicture}
\begin{tikzpicture}[omino/nodes/.style={shape=circle, inner sep=+0pt, minimum size=+1cm, fun}]
\thesamepictureeverywhere
\end{tikzpicture}
\tikzset{
tetris/1/.prefix style={/tikz/omino/nodes/.append style={fill=black,text=white}},
tetris/2/.prefix style={/tikz/omino/nodes/.append style={fill=blue}},
tetris/3/.prefix style={/tikz/omino/nodes/.append style={fill=green!70!blue}},
tetris/4/.prefix style={/tikz/omino/nodes/.append style={fill=yellow!80!black}},
tetris/5/.prefix style={/tikz/omino/nodes/.append style={fill=red!70!black}},
omino/Text={start}{.}
}
\begin{tikzpicture}[omino/nodes/.style={shape=rectangle, rounded corners, inner sep=+0pt, minimum size=1cm-2\pgflinewidth}]
\path [tetris=1];
\path [omino/at=0:1] [tetris=2];
\path [omino/at=0:2] [tetris=3];
\path [omino={at=0:3, rotate=-90, x mirror}][tetris=5];
\path [omino={at={5,1}, rotate=-90}][tetris=3];
\path [omino={at={5,2}, rotate=-90}][tetris=2];
\path [omino={at={4,2}, x mirror}][tetris=5];
\path [omino={at={1,3}}][tetris=4];
\end{tikzpicture}
\end{document}
输出 1
代码 2
\documentclass[tikz,border=2pt,convert=false]{standalone}
\usetikzlibrary{matrix}
\makeatletter
\tikzset{
omino/.style={/tikz/omino.cd,#1},
omino/row sep/.initial=1cm,
omino/column sep/.initial=1cm}
\newcounter{qrr@tikz@omino@y}
\newcounter{qrr@tikz@omino@x}
\def\qrr@tikz@omino@empty{\stepcounter{qrr@tikz@omino@x}}
\def\qrr@tikz@omino@full{%
\stepcounter{qrr@tikz@omino@x}
\node[
every omino node/.try,
every omino row \number\c@qrr@tikz@omino@y/.try,
every omino column \number\c@qrr@tikz@omino@x/.try,
every omino cell \number\c@qrr@tikz@omino@x-\number\c@qrr@tikz@omino@y/.try,
at={(\c@qrr@tikz@omino@x*\pgfkeysvalueof{/tikz/omino/column sep},\c@qrr@tikz@omino@y*\pgfkeysvalueof{/tikz/omino/row sep})}
]{};}
\def\qrr@tikz@omino@nextrow{\setcounter{qrr@tikz@omino@x}{0}\stepcounter{qrr@tikz@omino@y}}
\def\qrr@tikz@omino@final{\endgroup\@gobble}
\def\qrr@omino{%
\afterassignment\qrr@@omino\let\qrr@next@token=}
\def\qrr@@omino{%
\let\qrr@next\relax
\ifx\qrr@next@token.%
\let\qrr@next\qrr@tikz@omino@empty
\else
\ifx\qrr@next@token*%
\let\qrr@next\qrr@tikz@omino@full
\else
\ifx\qrr@next@token:
\let\qrr@next\qrr@tikz@omino@nextrow
\else
\ifx\qrr@next@token;
\let\qrr@next\qrr@tikz@omino@final
\fi
\fi
\fi
\fi
\qrr@next\qrr@omino
}
\newcommand*{\omino}[1][]{\begingroup\tikzset{#1}\setcounter{qrr@tikz@omino@x}{0}\setcounter{qrr@tikz@omino@y}{0}\qrr@omino}
\makeatother
\tikzset{every omino node/.style={circle, inner sep=+0pt, minimum size=+1cm}}
\begin{document}
\begin{tikzpicture}[every omino node/.append style={rectangle, fill,draw}]
\matrix[column sep=.5cm]{
\omino *:*:*:*; & \omino **:*:*; & \omino *:**:*; & \omino .*:**:*; \\};
\end{tikzpicture}
\begin{tikzpicture}[
every omino row 0/.style={fill=blue},
every omino row 1/.style={fill=blue!33!red},
every omino row 2/.style={fill=blue!67!red},
every omino row 3/.style={fill=red}]
\matrix[column sep=.5cm]{
\omino *:*:*:*; & \omino **:*:*; & \omino *:**:*; & \omino .*:**:*; \\};
\end{tikzpicture}
\end{document}
输出 2
答案2
\documentclass{article}
\makeatletter
\def\omino#1{{%
\unitlength10\p@
\@tempcnta\z@
\@tempcntb\@ne
\count@\z@
\xomino#1\relax
\fbox{\begin{picture}(\@tempcnta,\@tempcntb)(0,-\@tempcntb)%
\@tempcnta\z@
\@tempcntb\@ne
\count@\z@
\xxomino#1\relax
\end{picture}}%
}%
}
\def\xomino#1{%
\ifx\relax#1%
\else
\ifx\\#1%
\ifnum\count@>\@tempcnta \@tempcnta\count@\fi
\advance\@tempcntb\@ne
\count@\z@
\else
\advance\count@\@ne
\fi
\expandafter\xomino
\fi}
\def\xxomino#1{%
\ifx\relax#1%
\else
\ifx\\#1%
\advance\@tempcntb\@ne
\count@\z@
\else
\advance\count@\@ne
\ifx*#1%
\put(\count@,-\@tempcntb){\kern-10pt\rule{10pt}{10pt}}%
\fi
\fi
\expandafter\xxomino
\fi}
\makeatother
\begin{document}
\omino{
*\\
*\\
*\\
*\\
*}
\omino{
**\\
.*\\
.*\\
.*}
\omino{
**\\
*\\
*\\
**}
\end{document}
答案3
David 的解决方案将 ASCII 艺术转换为图形。下面是实现类似技巧的衍生版本。
\documentclass{article}
\usepackage{color}
\newdimen\omsq \omsq=20pt
\newdimen\omrule \omrule=2pt
\newdimen\omint
\newif\ifvth \newif\ifhth \newif\ifomblank
\def\OMINO#1{%
\vthtrue \hthtrue
\vbox{ \offinterlineskip\parindent=0pt \OM#1\relax\vskip1pt}}
\def\OM#1{%
\omint=\omsq \advance\omint-\omrule
\ifx\relax#1%
\else
\ifx\\#1 \newline\null \hthtrue \ifvth\vthfalse\else\vskip-\omrule\vthtrue\fi
\else%
\ifx .#1\hskip\ifhth \omrule\else \omint\fi
\else%
\ifx +#1\def\colour{black}\fi%
\ifx -#1\def\colour{black}\fi%
\ifx |#1\def\colour{black}\fi%
\ifx @#1\def\colour{black}\fi%
\ifx r#1\def\colour{red}\fi%
\ifx g#1\def\colour{green}\fi%
\ifx b#1\def\colour{blue}\fi%
\ifx y#1\def\colour{yellow}\fi%
\ifx m#1\def\colour{magenta}\fi%
\ifx c#1\def\colour{cyan}\fi%
\textcolor{\colour}{\rule{\ifhth\omrule\else\omsq\fi}{\ifvth\omrule\else\omsq\fi}}%
\ifhth\else\hskip -\omrule\fi%
\fi%
\ifhth\hthfalse\else\hthtrue\fi%
\fi%
\expandafter\OM%
\fi}
\makeatother
\begin{document}
\OMINO{
+-+-----+\\
|g|@|r.r|\\
|.+-+.+-+\\
|g.g|r|.|\\
+-+.|.|.|\\
|c|g|r|.|\\
|.+-+-+.|\\
|c.c.c|.|\\
+-----+-+
}
\OMINO{
+-+.......+-----+\\
|.|.......|r.r.r|\\
|.+-+-----+---+.|\\
|...|y.y.y.y.y|r|\\
+-+.+-+-----+-+.|\\
..|...|.....|r.r|\\
..+---+.....+---+
}
\end{document}
答案4
接口建议:
d 是 1 到 9 之间的数字 coordinate=d_nd_{n-1}d_{n-2}…d_2d_1 是无数字的数字(不含 0) pattern=number 是数字,其中每个数字最多出现一次,而 0 则不会出现
多格骨牌由一个字典给出,以坐标为键,以图案为值。这是什么意思?
想象一下键盘数字键盘或电话号码键盘。数字 1-9 排列在 3x3 网格中。上面的数字都标识了 3x3 网格中的一个这样的单元格。模式是一个数字。数字中出现的每个数字都意味着所标识的单元格是多格骨牌的一部分。
现在多格骨牌可以比 3x3 模式更大。因此,我们可以将 3x3 个 3x3 模式排列成一个 3x3 元模式。该模式在此元模式中的位置由坐标的数字 d_1 指定。为了变得更大,我们可以将 3x3 元模式放入元元模式中。此元元模式中的位置由 d_2 指定。依此类推。
简写:coordinate=0 表示坐标的最后一位数字不是 d_1 而是 d_0,表示图案内的单元格位于由坐标的前一位数字创建的坐标处。
0=模式意味着整个多格骨牌适合一个 3x3 模式并通过模式描述。
以下是一些示例:(基本模式为 789 456 123)
- f-五格骨牌是
0=24589
- N-五格骨牌是
(1=1478,4=2)
- I-dekomino 是
(11=123,12=123,13=123,21=1)