一开始我就决定要 可视化 显示各种麻将牌面,但当时还没想好如何设计。
接着我想起 emoji 是有麻将牌的 ,于是 最开始的时候 就用了笨办法——手写 emoji。
由于我的重度强迫症,「分门别类地列出所有役种」对我来说是一件能带来快感的事。
于是我居然写完了《日麻役种一览》一文,50 副牌面每一个 emoji 都是我手写的。
当时不觉得,写完才惊到。
后来由于日麻实在太杀时间了,渐渐就打得少了,这事儿也被遗忘了。
直到 2022.3.15(刚好一年)有读者发邮件来问牌面,我才想起原来这里还有个坑没填。
直到那时我仍然视 emoji 为一种妥协方案,因为 emoji 在不同系统不同平台上的显示风格……不能说各有千秋,也可以说是五花八门了,严重缺乏我想要的一致性。
然后本来想用 SVG 矢量图,没什么好说的,SVG 天下第一。
转念一想,麻将有 9 × 3 + 4 + 3 = 34 种花色,当然要用 CSS Sprite 优化,那不如就用图片。
麻将图片素材预览
以下图片素材来自「麻雀王国」

































































素材有了,开始实现。
相关 Hugo 文档:「图片资源处理」「images.Filter」
具体实现还是用 Hugo 的 shortcode 自动转换快捷缩写,最后显示统一格式。
万子 | 饼子 | 索子 | 东风 | 南风 | 西风 | 北风 | 白板 | 发财 | 红中 |
---|
Man zu | Pin zu | So zu | East | South | West | North | Pai pan | Fa | hon Chi |
m | p | s | E | S | W | N | P | F | C |
1m ~ 9m + 0m | 1p ~ 9p + 0p | 1s ~ 9s + 0s | 1z | 2z | 3z | 4z | 5z | 6z | 7z |
| | | | | | | | | |
实际使用时是不区分大小写的,字牌 此处大写是为了对人类阅读友好(便于肉眼辨识)。
没错,234ssss
或者 sss234s
都可以正确解析为「🀑🀒🀓🀁🀁🀁」。
同理,777PPPP
或者 PPP777P
也可以正确解析为「🀟🀟🀟🀆🀆🀆」。
同类型的牌连在一起可以省略相同的后缀字母:
{{< mahjong 1m2m3m4m0m5m6m7m8m9m >}}
{{< mahjong 1234056789m >}} # 显示效果同上
{{< mahjong 1z2z3z4z5z6z7z >}}
{{< mahjong 1234567z >}} # 显示效果同上
字牌既可以用「1z
~ 7z
」的标准描述方式,也可以用表意更明确的特定字符形式表示:
{{< mahjong 1z2z3z4z5z6z7z >}}
{{< mahjong ESWNPFC >}} # 显示效果同上
如果没有特别指定「不排序」的参数,最后显示会按这个顺序自动排序:
「万子」,「饼子」,「索子」,「东风、南风、西风、北风、白板、发财、红中」。
{{< mahjong main="2716453z91m91s91p" sort="off" >}}
{{< mahjong main="2716453z91m91s91p" sort="on" >}}
至于万、饼、索、字的「种类」顺序永远是自动排序的,这也没必要故意不排序吧。
兼容赤宝牌:
{{< mahjong 0123456789p >}}
{{< mahjong 1234567890p >}} # 显示效果同上
{{< mahjong 234m567p34678sff 25s >}} # 全小写
{{< mahjong 234M567P34678SFF 25S >}} # 全大写
{{< mahjong 234m567p34678sFF 25s >}} # 都是一样的
听
至于同一个字母只要格式正确,即便不区分大小写也并不会混淆,均可以正确解析。
饼子(1p ~ 9p
)& 白板(P
):
{{< mahjong 678pppp >}}
{{< mahjong 678PPPP >}} # 显示效果同上
索子(1s ~ 9s
)& 南风(S
):
{{< mahjong 234ssss >}}
{{< mahjong 234SSSS >}} # 显示效果同上
当然也不会影响自动排序:
{{< mahjong 12z3s4p5z6z777pp88ss >}} # 正常使用基本上也碰不到这种反人类写法 这里只是为了展示兼容性
# 自动排序后等效于 ↓
{{< mahjong "4777p 388s 12z S 5z P 6z" >}} # 兼容空格 会自动忽略
{{< mahjong 567m55567p234sCC 58pC >}}
{{< mahjong 567m55567p234s77z 8888p77z5555555555555555p >}} # 显示效果同上
听
区分听牌和和牌
想了一下最后附加的可能是和牌也可能是听牌,于是单独做了处理:
- 如果附加的牌只有 1 张,自动视为和牌。
- 如果有 2 张及以上,则视为听牌。(重复的牌作为听牌显示时会自动去重)
这样就轻易区分开了单听与和牌。
{{< mahjong 1334455699pEEE 22p >}}
{{< mahjong 1334455699pEEE 2p >}}
听
和
最后只要把 emoji 替换成图片素材就行了。(已替换为 SVG 素材,详见下一节)
不过就在此时,我发现 emoji 呈现的效果已经够好了。
而且 emoji 作为文本,可以直接选中整行复制粘贴,这也是图片没法实现的优势。
后来我发现原来 SVG 也有类似的技术,就叫「SVG Sprite」,是我孤陋寡闻了。
不过网上资料挺少的,好像用的人也不多。
参考资料:
以及相关工具:
另外还查到一些别的 SVG 知识,挺有趣的:
可操作性有了,需要的 麻将 SVG 素材 也找到了。
麻将 SVG 素材预览
以下 SVG 素材来自 
最后只要把 emoji 替换成 SVG 图片就行了。
{{< mahjong main="222678m234s3444p" wait="235p" style="emoji" >}} # emoji 字符
{{< mahjong main="222678m234s3444p" wait="235p" style="svg" >}} # SVG 矢量图
{{< mahjong main="222678m234s3444p" wait="235p" style="img" >}} # PNG 图片
🀈🀈🀈🀌🀍🀎🀛🀜🀜🀜🀑🀒🀓
听🀚🀛🀝
听
大功告成。
其实想想没有什么卵用,不知道什么时候才有空写新的日麻相关博文。
不过无所谓了,有多大用其实没太重要,轮子 写得很开心就是。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
| {{- if .Params -}}
{{- $InputText := slice -}}
{{- $Side := "" -}}
{{- $DefaultStyle := "emoji" -}}
{{- if $.Page.Params.mahjong -}}{{- $DefaultStyle = "svg" -}}{{- end -}}
{{- $Style := $DefaultStyle -}}
{{- $Sort := "on" -}}
{{- if .IsNamedParams -}}
{{- $InputText = slice (.Get "main") -}}
{{- $InputText = $InputText | append (.Get "wait") -}}
{{- $Side = .Get "side" -}}
{{- $Style = .Get "style" | default $DefaultStyle -}}
{{- $Sort = .Get "sort" | default "on" -}}
{{- else -}}
{{- $InputText = first 2 .Params -}}
{{- $Side = .Get 3 -}}
{{- end -}}
{{- $EMOJI := dict "MAN" "🀇🀈🀉🀊🀋🀌🀍🀎🀏" "PIN" "🀙🀚🀛🀜🀝🀞🀟🀠🀡" "SO" "🀐🀑🀒🀓🀔🀕🀖🀗🀘" "ZI" "🀀🀁🀂🀃🀆🀅🀄" -}}
{{- $RedExist := dict "man" false "pin" false "so" false -}}
{{- $Output := slice -}}
{{- range $InputText -}}
{{- $input := lower (replace (trim (chomp .) "\n-_") " " "") -}}
{{- $groups := dict "man" slice "pin" slice "so" slice "zi" slice -}}
{{- range $suit := slice "m" "p" "s" "z" -}}
{{- /* 解析并铺平(为一维)牌型数组(单种: 万子 饼子 索子 字牌) $array_1 */ -}}
{{- $array_1 := slice -}}
{{- $pattern := add "\\d+" $suit -}}
{{- if gt (len (findRE $pattern $input)) 0 -}}
{{- range $slice := findRE $pattern $input -}}
{{- $temp := split (strings.TrimSuffix $suit (index (findRE $pattern $slice) 0)) "" -}}
{{- $array_1 = $array_1 | append $temp -}}
{{- end -}}
{{- $input = replaceRE $pattern "" $input -}}
{{- end -}}
{{- $array_2 := slice -}}
{{- if len $array_1 -}}
{{- range $item := $array_1 -}}
{{- /* 数字牌后处理 标记赤宝牌 */ -}}
{{- if eq $item "0" -}}
{{- $item = "5" -}}
{{- if eq $suit "m" -}}
{{- $RedExist = merge $RedExist (dict "man" true) -}}
{{- else if eq $suit "p" -}}
{{- $RedExist = merge $RedExist (dict "pin" true) -}}
{{- else if eq $suit "s" -}}
{{- $RedExist = merge $RedExist (dict "so" true) -}}
{{- end -}}
{{- end -}}
{{- /* 处理为标准数字形式(1-9m/p/s,1-7z)的牌面 */ -}}
{{- $array_2 = $array_2 | append (add $item $suit) -}}
{{- end -}}
{{- end -}}
{{- /* 字牌后处理 处理剩余的字符形式牌面(字牌: E S W N P F C) */ -}}
{{- if eq $suit "z" -}}
{{- with $input -}}
{{- $temp := slice -}}
{{- range $char := split . "" -}}
{{- if eq $char "e" -}}
{{- $temp = $temp | append "1z" -}}
{{- else if eq $char "s" -}}
{{- $temp = $temp | append "2z" -}}
{{- else if eq $char "w" -}}
{{- $temp = $temp | append "3z" -}}
{{- else if eq $char "n" -}}
{{- $temp = $temp | append "4z" -}}
{{- else if or (eq $char "p") (eq $char "b") -}}
{{- $temp = $temp | append "5z" -}}
{{- else if eq $char "f" -}}
{{- $temp = $temp | append "6z" -}}
{{- else if eq $char "c" -}}
{{- $temp = $temp | append "7z" -}}
{{ end }}
{{- end -}}
{{- $array_2 = $array_2 | append $temp -}}
{{- end -}}
{{- end -}}
{{- /* 排序并写入字典 */ -}}
{{- $temp := $array_2 -}}
{{- if eq $Sort "on" -}}{{- $temp = sort $array_2 -}}{{- end -}}
{{- if eq $suit "m" -}}
{{- $groups = merge $groups (dict "man" $temp) -}}
{{- else if eq $suit "p" -}}
{{- $groups = merge $groups (dict "pin" $temp) -}}
{{- else if eq $suit "s" -}}
{{- $groups = merge $groups (dict "so" $temp) -}}
{{- else if eq $suit "z" -}}
{{- $groups = merge $groups (dict "zi" $temp) -}}
{{- end -}}
{{- end -}}
{{- $Output = $Output | append $groups -}}
{{- end -}}
{{- $count := slice -}}
{{- range $group := $Output -}}
{{- $temp := 0 -}}
{{- range $group -}}
{{- $temp = add $temp (len .) -}}
{{- end -}}
{{- $count = $count | append $temp -}}
{{- end -}}
{{- if or (gt (index $count 0) 1) (gt (index $count 1) 0) -}}<div class="mahjong center" style="margin: 1rem 0; font-size: 2.5rem;">{{- end -}}
{{- /* 展示副露区 */ -}}
{{- with $Side -}}
{{- $input := split . " " -}}
{{- range $index, $item := $input -}}
<span style="margin: 0 0.5rem;">
{{- $type := slicestr $item 0 1 -}}
{{- $pai := slicestr $item 1 3 -}}
{{- $need := "" -}}
{{- if eq (len $item) 5 -}}{{- $need = slicestr $item 4 -}}{{- end -}}
{{- if eq $type "#" -}}
{{- /* 处理吃 TODO 改进显示顺序 */ -}}
{{- range $index := slice "0" "1" "2" -}}
{{- $new_pai := add (htmlEscape (add (int (slicestr $pai 0 1)) (int $index))) (slicestr $pai 1) -}}
{{- if eq $Style "img" -}}
<img class="sticker" src="https://sdfsdf.dev/36x52.png,beige,beige" title="{{- $new_pai -}}" style="width: 36px; height: 52px; margin: 0 1px; border: 2px dashed red;" />
{{- else if eq $Style "emoji" -}}
{{- $i := int (slicestr $new_pai 0 1) -}}
{{- $charset := "" -}}
{{- if eq (slicestr $new_pai 1) "m" -}}
{{- $charset = $EMOJI.MAN -}}
{{- else if eq (slicestr $new_pai 1) "p" -}}
{{- $charset = $EMOJI.PIN -}}
{{- else if eq (slicestr $new_pai 1) "s" -}}
{{- $charset = $EMOJI.SO -}}
{{- else if eq (slicestr $new_pai 1) "z" -}}
{{- $charset = $EMOJI.ZI -}}
{{- end -}}
{{- print (slicestr $charset (sub $i 1) $i) -}}
{{- else -}}
<svg class="{{- if eq $index $need -}}rotate{{- else -}}tile{{- end -}}"><use class="face" xlink:href="#mj-{{- $new_pai -}}" /></svg>
{{- end -}}
{{- end -}}
{{- else if eq $type "." -}}
{{- /* 处理碰 */ -}}
{{- range $index := slice "0" "1" "2" -}}
{{- if eq $Style "img" -}}
<img class="sticker" src="https://sdfsdf.dev/36x52.png,beige,beige" title="{{- $pai -}}" style="width: 36px; height: 52px; margin: 0 1px; border: 2px dashed red;" />
{{- else if eq $Style "emoji" -}}
{{- $i := int (slicestr $pai 0 1) -}}
{{- $charset := "" -}}
{{- if eq (slicestr $pai 1) "m" -}}
{{- $charset = $EMOJI.MAN -}}
{{- else if eq (slicestr $pai 1) "p" -}}
{{- $charset = $EMOJI.PIN -}}
{{- else if eq (slicestr $pai 1) "s" -}}
{{- $charset = $EMOJI.SO -}}
{{- else if eq (slicestr $pai 1) "z" -}}
{{- $charset = $EMOJI.ZI -}}
{{- end -}}
{{- print (slicestr $charset (sub $i 1) $i) -}}
{{- else -}}
<svg class="{{- if eq $index $need -}}rotate{{- else -}}tile{{- end -}}"><use class="face" xlink:href="#mj-{{- $pai -}}" /></svg>
{{- end -}}
{{- end -}}
{{- else if eq $type "-" -}}
{{- /* 处理大明杠 */ -}}
{{- range $index := slice "0" "1" "x" "2" -}}
{{- if eq $Style "img" -}}
<img class="sticker" src="https://sdfsdf.dev/36x52.png,beige,beige" title="{{- $pai -}}" style="width: 36px; height: 52px; margin: 0 1px; border: 2px dashed red;" />
{{- else if eq $Style "emoji" -}}
{{- $i := int (slicestr $pai 0 1) -}}
{{- $charset := "" -}}
{{- if eq (slicestr $pai 1) "m" -}}
{{- $charset = $EMOJI.MAN -}}
{{- else if eq (slicestr $pai 1) "p" -}}
{{- $charset = $EMOJI.PIN -}}
{{- else if eq (slicestr $pai 1) "s" -}}
{{- $charset = $EMOJI.SO -}}
{{- else if eq (slicestr $pai 1) "z" -}}
{{- $charset = $EMOJI.ZI -}}
{{- end -}}
{{- print (slicestr $charset (sub $i 1) $i) -}}
{{- else -}}
<svg class="{{- if eq $index $need -}}rotate{{- else -}}tile{{- end -}}"><use class="face" xlink:href="#mj-{{- $pai -}}" /></svg>
{{- end -}}
{{- end -}}
{{- else if eq $type "+" -}}
{{- /* 处理加杠 TODO 复杂判断 */ -}}
{{- range $index := slice "0" "1" "x" "2" -}}
{{- if eq $Style "img" -}}
<img class="sticker" src="https://sdfsdf.dev/36x52.png,beige,beige" title="{{- $pai -}}" style="width: 36px; height: 52px; margin: 0 1px; border: 2px dashed red;" />
{{- else if eq $Style "emoji" -}}
{{- $i := int (slicestr $pai 0 1) -}}
{{- $charset := "" -}}
{{- if eq (slicestr $pai 1) "m" -}}
{{- $charset = $EMOJI.MAN -}}
{{- else if eq (slicestr $pai 1) "p" -}}
{{- $charset = $EMOJI.PIN -}}
{{- else if eq (slicestr $pai 1) "s" -}}
{{- $charset = $EMOJI.SO -}}
{{- else if eq (slicestr $pai 1) "z" -}}
{{- $charset = $EMOJI.ZI -}}
{{- end -}}
{{- print (slicestr $charset (sub $i 1) $i) -}}
{{- else -}}
<svg class="{{- if eq $index $need -}}rotate{{- else -}}tile{{- end -}}"><use class="face" xlink:href="#mj-{{- $pai -}}" /></svg>
{{- end -}}
{{- end -}}
{{- else if eq $type "_" -}}
{{- /* 处理暗杠 */ -}}
{{- if eq $Style "img" -}}
{{- range slice 1 2 3 4 -}}
<img class="sticker" src="https://sdfsdf.dev/36x52.png,beige,beige" title="{{- $pai -}}" style="width: 36px; height: 52px; margin: 0 1px; border: 2px dashed red;" />
{{- end -}}
{{- else if eq $Style "emoji" -}}
{{- $i := int (slicestr $pai 0 1) -}}
{{- $charset := "" -}}
{{- if eq (slicestr $pai 1) "m" -}}
{{- $charset = $EMOJI.MAN -}}
{{- else if eq (slicestr $pai 1) "p" -}}
{{- $charset = $EMOJI.PIN -}}
{{- else if eq (slicestr $pai 1) "s" -}}
{{- $charset = $EMOJI.SO -}}
{{- else if eq (slicestr $pai 1) "z" -}}
{{- $charset = $EMOJI.ZI -}}
{{- end -}}
{{- range slice 1 2 3 4 -}}
{{- print (slicestr $charset (sub $i 1) $i) -}}
{{- end -}}
{{- else -}}
<svg class="tile"><use class="face" xlink:href="#mj-0z" /></svg><svg class="tile"><use class="face" xlink:href="#mj-{{- $pai -}}" /></svg><svg class="tile"><use class="face" xlink:href="#mj-{{- $pai -}}" /></svg><svg class="tile"><use class="face" xlink:href="#mj-0z" /></svg>
{{- end -}}
{{- end -}}
{{- if and (eq (len $input) 4) (eq $index 1) -}}<br/>{{- end -}}
</span>
{{- end -}}
<br/>
{{- end -}}
{{- /* 展示手牌 */ -}}
{{- range $key, $value := index $Output 0 -}}
{{- range $code := $value -}}
{{- if eq $Style "img" -}}
<img class="sticker" src="https://sdfsdf.dev/36x52.png,beige,beige" title="{{- $code -}}" style="width: 36px; height: 52px; margin: 0 1px; border: 2px dashed red;" />
{{- else if eq $Style "emoji" -}}
{{- $i := int (slicestr $code 0 1) -}}
{{- $charset := "" -}}
{{- if eq $key "man" -}}
{{- $charset = $EMOJI.MAN -}}
{{- else if eq $key "pin" -}}
{{- $charset = $EMOJI.PIN -}}
{{- else if eq $key "so" -}}
{{- $charset = $EMOJI.SO -}}
{{- else if eq $key "zi" -}}
{{- $charset = $EMOJI.ZI -}}
{{- end -}}
{{- print (slicestr $charset (sub $i 1) $i) -}}
{{- else -}}
{{- if eq $code "5m" -}}
{{- if $RedExist.man -}}{{- $code = "0m" -}}{{- $RedExist = merge $RedExist (dict "man" false) -}}{{- end -}}
{{- else if eq $code "5p" -}}
{{- if $RedExist.pin -}}{{- $code = "0p" -}}{{- $RedExist = merge $RedExist (dict "pin" false) -}}{{- end -}}
{{- else if eq $code "5s" -}}
{{- if $RedExist.so -}}{{- $code = "0s" -}}{{- $RedExist = merge $RedExist (dict "so" false) -}}{{- end -}}
{{- end -}}
<svg class="tile"><use class="face" xlink:href="#mj-{{- $code -}}" /></svg>
{{- end -}}
{{- end -}}
{{- end -}}
{{- /* 展示听牌 */ -}}
{{- if index $count 1 -}}
{{- $side := index $Output 1 -}}
<span class="handwriting" style="margin: 0 0.25rem;">
{{- if eq (index $count 1) 1 -}}和{{- else -}}<br/>听{{- end -}}
</span>
{{- range $key, $value := $side -}}
{{- range $ting_pai := (uniq $value) -}}
{{- if eq $Style "img" -}}
<img class="sticker" src="https://sdfsdf.dev/36x52.png,beige,beige" title="{{- $ting_pai -}}" style="width: 36px; height: 52px; margin: 0 1px; border: 2px dashed red;" />
{{- else if and (eq $Style "emoji") (len $ting_pai) -}}
{{- $i := int (slicestr $ting_pai 0 1) -}}
{{- $charset := "" -}}
{{- if eq $key "man" -}}
{{- $charset = $EMOJI.MAN -}}
{{- else if eq $key "pin" -}}
{{- $charset = $EMOJI.PIN -}}
{{- else if eq $key "so" -}}
{{- $charset = $EMOJI.SO -}}
{{- else if eq $key "zi" -}}
{{- $charset = $EMOJI.ZI -}}
{{- end -}}
{{- print (slicestr $charset (sub $i 1) $i) -}}
{{- else -}}
<svg class="tile"><use class="face" xlink:href="#mj-{{- $ting_pai -}}" /></svg>
{{- end -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{- if or (gt (index $count 0) 1) (gt (index $count 1) 0) -}}</div>{{- end -}}
{{- end -}}
|
吃 | 碰 | 大明杠 | 加杠 | 暗杠 |
---|
#7m%0 r7 t9 t8 | .6p%0 r6 t6 t6 | -5s%0 r5 t5 t5 t5 | +4z%0 d4 t4 t4 | _7z X77X |
#7m%1 r8 t9 t7 | .6p%1 t6 r6 t6 | -5s%1 t5 r5 t5 t5 | +4z%1 t4 d4 t4 | |
#7m%2 r9 t8 t7 | .6p%2 t6 t6 r6 | -5s%2 t5 t5 t5 r5 | +4z%2 t4 t4 d4 | |
{{< mahjong main="7788s" wait="7s" side="#7m%0 #6p%1 #5s%2" >}}
和
只可能吃上家,吃哪张的区别。
{{< mahjong main="7788s" wait="8s" side=".7m%0 .6p%1 .5s%2" >}}
和
只可能碰一种牌,碰哪家的区别。
{{< mahjong main="7788s" wait="7s" side="-7m%0 -6p%1 -5s%2" >}}
和
类似碰,只可能杠一种牌,杠哪家的区别。
另外鸣牌含赤宝牌的时候到底是怎么摆的?
1
2
3
4
5
6
7
8
9
| <svg width="1000" height="1000">
<defs>
<pattern id="grid" x="100" y="100" width="0.2" height="0.2" patternUnits="objextBoundingBox">
<circle cx="10" cy="10" r="5" fill="red"></circle>
<polygon points="30 10 60 50 0 50" fill="green"></polygon>
</pattern>
</defs>
<rect x="100" y="100" width="400" height="300" fill="url(#grid)" stroke="blue"></rect>
</svg>
|
{{< mahjong main="7788s" wait="8s" side="+7m%0 +6p%1 +5s%2" >}}
和
和碰一个原理。
{{< mahjong main="7788s" wait="7s" side="_7m _6p _5s" >}}
和
最省心的判定,甚至连赤宝牌都不用额外判定。
