我接触日本麻将(简称日麻),是从《天才麻将少女》这部动漫开始的,从那之后便跳进日麻的坑中无法自拔,到现在为止已经将近一年了。在这一年中,我对日本麻将也有了一些自己的理解与感悟,我也很希望将这些东西在我的博客上与大家分享。
那么问题来了:当我想说明某个关于日麻的问题时,只凭文字总是显得不那么直观。然而如果用图片的话,对于每张麻将牌都去插入一个<img/>
标签又非常不方便。究竟该如何解决呢?我的解决方法是开发一个Octopress插件,在之后写博客时,只需利用此插件简单地键入几个字符,Octopress就可以自动在生成的网页中插入对应的图片。
比如,日麻中的“一万”通常会简称为1m
;“五饼”则通常会简称为5p
。在我想插入一张“一万”的图片的时候,我只需要使用我开发的插件,写出如下代码{% mahjong 1m %}
,Octopress就会自动添加该图片。是不是比起自己写<img/>
标签来要方便很多?
那么就开始开发自己需要的插件吧!
一、基本功能
具体来说,我的需求分为两部分:首先是在一行文本内部加入单张麻将牌的图片,我计划开发一个名为mahjong
的插件来实现;然后是可以另起一行显示一组麻将牌(通常是13张,表示某位玩家的手牌)的图片,我计划开发一个名为mahjonglist
的插件来实现。这篇博文讲的是第一个插件的实现方式。
然后我们可以开始定义本插件的语法了。我们一般通过{% plugin_name parameters %}
的方式调用插件,所以我将本插件的语法定义为{% mahjong cardName %}
。
下一步定义cardName
的语法。首先我们遵照日本麻将玩家的习惯,“万”简写为m
,“饼”简写为p
,“索”简写为s
,这样就可以表示所有非字牌了。对于字牌,我采用后缀j
来表示,1j
到7j
对应东南西北白发中。
另外,日麻中有红宝牌(赤ドラ)的概念,通常是红五万、红五索、红五饼。我采用在数字后加一个!
的方法将红宝牌与普通牌区分。所以“五索”为5s
,“红五索”则为5!s
。
还有,由于日麻中在吃、碰、杠后会将其中一张牌横置,表示这张牌来自于哪个玩家。所以我采用在数字后加一个$
的方法表示这张牌是横置的。比如要表示一个横置的北风,即为4$j
。后缀符$
和!
的先后顺序无关。
最后,日麻中暗杠的表示方法是中间两张牌正放,旁边两张牌倒放,所以我们还需要表示倒放的牌(暗牌)。我采用数字0加上m, p, s, j
中的任何一个标签表示暗牌。
二、插件开发
首先我们有一组麻将牌图片的资源,我们需要做的是写一个rb
文件,解析cardName
的语法,并且生成对应的<img/>
标签。我们在plugins/
目录下新建一个文件名为mahjong.rb
。笔者之前没有任何Ruby开发的经验,这次开发插件,完全是参照已有插件的写法开发的。
我们发现,大部分插件都是自己定义了一个类,继承自Liquid::Tag
或者Liquid::Block
。在文件的最后,我们需要利用Liquid::Template.register_tag()
对插件进行注册。
其中,继承自Liquid::Block
的插件属于语句块类型的,即用一个开始标识符和一个结束标识符将要显示的内容包裹起来,比如blockquote.rb
;而继承自Liquid::Tag
的插件属于标签类型的,不需要用两个标识符包裹,比如image_tag.rb
。考虑到我们的功能,我们需要选用的是后一种类型,即继承自Liquid::Tag
。
我们还发现,我们的插件需要写的函数包括initialize(tag_name, markup, tokens)
函数,我们的cardName
就是通过markup
参数传递进来的。在该函数中,我们需要对传进来的参数进行解析。
我们还需要写一个render(context)
函数,这个函数执行的结果就是对应的html标签。
注意到这些点之后,我写出的插件代码如下:
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 |
|
关于Ruby语法需要说明的有两点:一是Ruby中变量的命名有一套规范,代码中以@
开头的变量,代表类的成员变量;二是Ruby中的字符串可以通过#{expression}
的方式直接引用一个变量或表达式的值。
需要注意的是,在上面的代码中,我生成html时为每张图片增加了一个属性class="mahjong"
。为什么要这样呢?因为Octopress自己的主题中,显示的图片有默认的样式,如果我们不加这一句,显示时就会按照默认的样式显示。而Octopress默认的样式有很粗的白色边框,还有阴影效果,不适合显示麻将牌。下图是Octopress默认的显示效果:
为了覆盖这种默认的显示效果,我为每张图片增加了一个属性class="mahjong"
,并且在sass/custom/_styles.scss
文件中添加了分类器:
1 2 3 4 5 6 |
|
这样,我们就可以看到没有边框与阴影的麻将牌了。
三、效果测试
类别一:普通麻将牌
{% mahjong 3s %}
会显示出;
{% mahjong 6p %}
会显示出;
{% mahjong 8m %}
会显示出;
{% mahjong 3j %}
会显示出;
类别二:红宝牌与暗牌
{% mahjong 5!p %}
会显示出;
{% mahjong 5!m %}
会显示出;
{% mahjong 5!s %}
会显示出;
{% mahjong 0j %}
会显示出;
{% mahjong 0p %}
会显示出;
类别三:横置的牌与红宝牌综合测试
{% mahjong 5$j %}
会显示出;
{% mahjong 5!$s %}
会显示出;
{% mahjong 5$!p %}
会显示出;
类别四:错误情况测试
- 本插件定义的错误情况包括:最右端标签不是
m, p, s, j
;对于标签j
,数字范围不在0-7
内或对于标签m, p, s
,数字范围不在0-9
内;或者红宝牌的数字不是5;或者企图将暗牌横置(日麻中暗牌不可能横置)等。 {% mahjong 4!s %}
会显示出错误:红宝牌必须是五万、五饼、五索;{% mahjong 5!j %}
会显示出错误:红宝牌必须是五万、五饼、五索;{% mahjong 0$j %}
会显示出错误:暗牌不能横置;{% mahjong 4a %}
会显示出错误:缺少m、p、s、j标签;{% mahjong bs %}
会显示出错误:m、p、s标签对应的编号只能为0到9;{% mahjong 8j %}
会显示出错误:j标签对应的编号只能为0到7;
四、下一步工作:
接下来要做的就是最开始提到的第二部分,即利用mahjonglist
插件实现显示一行麻将牌的功能。当这一部分功能完成之后,我就会开始在我的博客中更新一些关于日麻的内容了~