目录
前言
要实现的规则如下:根据接龙的成语的第一个字与前一个成语结尾的字的比较,分一下三种模式模式1:字相同拼音也要相同
模式2:字相同拼音不要求相同
模式3:字不要相同拼音要求相同,即谐音就可以接龙的成语必须是四字成语已使用过的成语双方均不得再次使用一方不按照规则接龙或接不下去时判定失败
数据获取和清洗
本文语料来自于Bookdown图书下载网,抓下来之后,经过乱码处理、脏数据去除、分章数据合并、结构化提取等操作,得到了一份结构化好的json类型数据。我已经把它放在了github上,下载地址为github。
本成语库总共包含成3万个成语,其中四字成语大概2.9万个。每条数据包含以下字段:字段说明字段说明idiom成语本身pinyin拼音
source成语出处explanation成语释义
sample示例
代码实现
代码也已经放到了GitHub上,这里就不再贴出。源码地址为https://github.com/lukeplus/Idiom。下面主要讲讲如何使用。
示例1:from solitaire import IdiomSolitairegame = IdiomSolitaire()game.forward("一心一意")# 输出:(True, '意气飞扬')game.forward("扬眉吐气")# 输出:(True, '气壮山河')game.forward("呵呵呵呵")# 输出:(False, None)
示例2:xxxxxxxxxx
game = IdiomSolitaire()game.get_next_idiom("人山人海")# 输出:海市蜃楼game.get_next_idiom("人山人海")# 输出:海阔天空game.get_next_idiom("战战兢兢")# 输出:兢兢乾乾
示例3:xxxxxxxxxx
from solitaire import IdiomSolitairegame = IdiomSolitaire()# bot_first系统先开始idiom = game.bot_first() # 输出:一心一意game.forward("意气飞扬")# 输出:(True, '扬长避短')
IdiomSolitaire类
IdiomSolitaire类负责成语接龙流程,以及游戏状态维护。支持三种模式,如下:xxxxxxxxxx
game= IdiomSolitaire(mode="pw")# pw表示字和拼音都要保持一致game= IdiomSolitaire(mode="p")# p表示拼音一致即可game= IdiomSolitaire(mode="w")# w表示字一样即可xxxxxxxxxx
game = IdiomSolitaire(mode="p")game.get_next_idiom("不三不四")# 输出:肆意横行
forward方法
推进游戏运行的主要方法,当第一次调用时,允许输入参数为空,表示由系统起头开始游戏。第一次调用不为空时,表示由客户端开始游戏。forward既要检验输入成语对上一个成语的承接(这是与get_next_idiom的主要区别),也要计算下一个成语。
返回二元组,第一个元素代表输入的成语是否准确,是否能承接上一个成语,第二个元素是下一个待接龙的成语。当返回(False, None),表示输入的成语不能连接上一个成语。用户输掉比赛。
当返回(True, None) , 表示机器找不到一个成语能接上用户输入的成语。机器输掉比赛。
get_next_idiom
不考虑上下文,单纯返回能承接输入词的词语。
总结与改进
总的来说,简单需求的成语接龙的实现几乎没什么难点,没有牵涉到复杂的算法。而实现它的目的,是觉得可以拿这份成语语料做其他NLP相关的更酷的事情。比如说,给定一段话,通过语义分析之后,得到与这段话意思最相近的一个成语。
当然,要把成语接龙做得更人性化,还是得花很多心思的,也没有那么简单,需要改进的地方很多。比如系统选词不应该是简单的随机选,而是应该考虑成语的难易程度、普及程度,毕竟如果老是随机选一些冷门词,那游戏就不好玩了。