我的问题的基础是我正在制作一个 14x14 的填字游戏,我有来自外部文档的 196 个单元格中的每一个的数据,但只需要内部带有文本的单元格有边框。
我尝试使用 MetaPost 来解决这个问题。为简单起见,我在这里将代码简化为 14x1 网格示例。
我创建了一个外部脚本,它为我提供了网格内应包含的所有值。例如,如果第一行有“cat”,则它会给出以下内容:
\setvalue{1}{c}
\setvalue{2}{a}
\setvalue{3}{t}
\setvalue{4}{}
\setvalue{5}{}
\setvalue{6}{}
\setvalue{7}{}
\setvalue{8}{}
\setvalue{9}{}
\setvalue{10}{}
\setvalue{11}{}
\setvalue{12}{}
\setvalue{13}{}
\setvalue{14}{}
完整的 14x14 示例有 196 个这样的变量,但通过脚本放在另一个文件中,因此它们并不笨重。
我使用 MetaPost 创建了许多框而不是表格,因为我找不到干净的方法将下标文本添加到表格中单元格的角落,而不会将该单元格中的字母推到右侧。
以下是解决方案页面的最小工作示例:
\setvalue{1}{c}
\setvalue{2}{a}
\setvalue{3}{t}
\setvalue{4}{}
\setvalue{5}{}
\setvalue{6}{}
\setvalue{7}{}
\setvalue{8}{}
\setvalue{9}{}
\setvalue{10}{}
\setvalue{11}{}
\setvalue{12}{}
\setvalue{13}{}
\setvalue{14}{}
\define\crosswordsolution{%
\scale[width=\textwidth]{%
\startMPcode
draw (0,0)--(100,0)--(100,100)--(0,100)--(0,0);
draw (100,0)--(200,0)--(200,100)--(100,100)--(100,0);
draw (200,0)--(300,0)--(300,100)--(200,100)--(200,0);
draw (300,0)--(400,0)--(400,100)--(300,100)--(300,0);
draw (400,0)--(500,0)--(500,100)--(400,100)--(400,0);
draw (500,0)--(600,0)--(600,100)--(500,100)--(500,0);
draw (600,0)--(700,0)--(700,100)--(600,100)--(600,0);
draw (700,0)--(800,0)--(800,100)--(700,100)--(700,0);
draw (800,0)--(900,0)--(900,100)--(800,100)--(800,0);
draw (900,0)--(1000,0)--(1000,100)--(900,100)--(900,0);
draw (1000,0)--(1100,0)--(1100,100)--(1000,100)--(1000,0);
draw (1100,0)--(1200,0)--(1200,100)--(1100,100)--(1100,0);
draw (1200,0)--(1300,0)--(1300,100)--(1200,100)--(1200,0);
draw (1300,0)--(1400,0)--(1400,100)--(1300,100)--(1300,0);
label("\getvalue{1}", (50,50));
label("\getvalue{2}", (150,50));
label("\getvalue{3}", (250,50));
label("\getvalue{4}", (350,50));
label("\getvalue{5}", (450,50));
label("\getvalue{6}", (550,50));
label("\getvalue{7}", (650,50));
label("\getvalue{8}", (750,50));
label("\getvalue{9}", (850,50));
label("\getvalue{10}", (950,50));
label("\getvalue{11}", (1050,50));
label("\getvalue{12}", (1150,50));
label("\getvalue{13}", (1250,50));
label("\getvalue{14}", (1350,50));
label("1", (25,75));
\stopMPcode
}%
}%
\starttext
\crosswordsolution
\stoptext
我遇到的问题是,我只需要绘制里面有字母的框。空框根本不需要绘制。换句话说,只需要绘制包含 CAT 中字母的框,其他框是不可见的。
我尝试在 MetaPost 中使用简单的 TeX 条件,检查变量是否为空,但代码出现错误,所以我怀疑 MetaPost 里面不能有 TeX 或 ConTeXt\startMPcode
代码\endMPcode
。
是否有某种方法可以创建条件,仅当匹配变量有文本时才允许绘制特定的框?
答案1
您会发现使用 Metapost 逻辑结构更容易。这里有一些简单的 MP,可以满足您的要求(我认为):
prologues := 3;
outputtemplate := "%j%c.eps";
beginfig(1);
string cell[];
cell1 := "C";
cell2 := "A";
cell3 := "T";
cell4 := "";
cell5 := "S";
cell6 := "A";
cell7 := "T";
cell8 := "";
cell9 := "";
cell10 := "";
cell11 := "H";
cell12 := "E";
cell13 := "R";
cell14 := "E";
path box;
box = unitsquare shifted -(1/2, 1/2) scaled 10;
numeric x, y;
y = 5;
x = 5;
for i=1 upto 14:
if cell[i] <> "":
label(cell[i], (x, y));
draw box shifted (x, y);
fi
x := x + 10;
endfor
endfig;
end.
如果你用纯文本编译它,mpost
你应该得到这个:
在 和 之间的普通 Metapost 中运行的所有内容都应该在 Context 中的beginfig
和之间endfig
无须改变地运行。\startMPcode
\stopMPcode
cell1 := "\getvalue{1}"
您可以通过分配等方式使其适应您的价值观。
答案2
你能在 MetaPost 中使用 TeX 条件,但它们必须是完全可扩展的,并避免“不完整的 if”问题。生成的代码并不漂亮,Toby 的答案显然更可取。
\setvalue{1}{c}
\setvalue{2}{a}
\setvalue{3}{t}
\setvalue{4}{}
\setvalue{5}{}
\setvalue{6}{}
\setvalue{7}{}
\setvalue{8}{}
\setvalue{9}{}
\setvalue{10}{}
\setvalue{11}{}
\setvalue{12}{}
\setvalue{13}{}
\setvalue{14}{}
% \getvalue only yields its value after two expansion steps,
% therefore we need to use \doubleexpandafter
\def\expdoifvalue#1%
{\doubleexpandafter\ifx\getvalue{#1}\empty
\expandafter\gobbleoneargument
\else
\expandafter\firstofoneargument
\fi}
\define\crosswordsolution{%
\scale[width=\textwidth]{%
\startMPcode
\expdoifvalue{1}{
draw (0,0)--(100,0)--(100,100)--(0,100)--(0,0);
label("\getvalue{1}", (50,50));
}
\expdoifvalue{2}{
draw (100,0)--(200,0)--(200,100)--(100,100)--(100,0);
label("\getvalue{2}", (150,50));
}
\expdoifvalue{3}{
draw (200,0)--(300,0)--(300,100)--(200,100)--(200,0);
label("\getvalue{3}", (250,50));
}
\expdoifvalue{4}{
draw (300,0)--(400,0)--(400,100)--(300,100)--(300,0);
label("\getvalue{4}", (350,50));
}
\expdoifvalue{5}{
draw (400,0)--(500,0)--(500,100)--(400,100)--(400,0);
label("\getvalue{5}", (450,50));
}
\expdoifvalue{6}{
draw (500,0)--(600,0)--(600,100)--(500,100)--(500,0);
label("\getvalue{6}", (550,50));
}
\expdoifvalue{7}{
draw (600,0)--(700,0)--(700,100)--(600,100)--(600,0);
label("\getvalue{7}", (650,50));
}
\expdoifvalue{8}{
draw (700,0)--(800,0)--(800,100)--(700,100)--(700,0);
label("\getvalue{8}", (750,50));
}
\expdoifvalue{9}{
draw (800,0)--(900,0)--(900,100)--(800,100)--(800,0);
label("\getvalue{9}", (850,50));
}
\expdoifvalue{10}{
draw (900,0)--(1000,0)--(1000,100)--(900,100)--(900,0);
label("\getvalue{10}", (950,50));
}
\expdoifvalue{11}{
draw (1000,0)--(1100,0)--(1100,100)--(1000,100)--(1000,0);
label("\getvalue{11}", (1050,50));
}
\expdoifvalue{12}{
draw (1100,0)--(1200,0)--(1200,100)--(1100,100)--(1100,0);
label("\getvalue{12}", (1150,50));
}
\expdoifvalue{13}{
draw (1200,0)--(1300,0)--(1300,100)--(1200,100)--(1200,0);
label("\getvalue{13}", (1250,50));
}
\expdoifvalue{14}{
draw (1300,0)--(1400,0)--(1400,100)--(1300,100)--(1300,0);
label("\getvalue{14}", (1350,50));
}
label("1", (25,75));
\stopMPcode
}%
}%
\starttext
\crosswordsolution
\stoptext
除了实现之外,\expdoifvalue{1}{...}
您还可以使用内置的\expdoifnot{\getvalue{1}}{}{...}
。但是,\expdoifnot
执行完全扩展可能并不总是理想的。