前言
中华文化博大精深,尤其是中国古诗词。其中,有关古诗的、可以随时与人玩的游戏无非就是飞花令了。这段时间,我迷上了与某爱玩飞花令,奈何机器的诗库总是强大的,人脑总不可能战胜,于是便突发奇想用 Python 写了个飞花令的程序,现与大家分享一下~
飞花令查询
项目代码
该程序代码已共享在 GitHub 上,参见链接
https://github.com/PythonSimon/FlyingFlowerOrder.git
实现过程
下载诗库
由于该程序是支持多诗库(常用 ,较全)的,所以需要用到两个词库:
常用诗库(1万句)
较全诗库(7万首)
,可自行下载。
初始化目录
因考虑到可读性,该项目在 GitHub 上的诗库被单独放在了 Resource 文件夹中。但方便起见,该文章里的代码都是依据同路径下编写的。所以,如果只是为了试验实例中的代码,将文件放在同目录下即可。
编写代码
导入 threading
考虑到诗库中的诗词量较大,所以对于词库的处理与对诗句的检测两个任务采用多线程实现。
# Main.py
from thereading import *
def thread1():
pass
def thread2():
pass
writer = Thread(thread1)
reader = Thread(thread)
writer.start()
checker.start()
上述代码导入了 threading 多线程模块,并在创建两个线程的函数之后将函数实例化为线程对象,最后依次运行线程。
实现格式转换线程
由于下载的诗词库未经处理(别问为啥,就是懒),所以 thread1 是用来转换格式,并将可以直接使用的诗句写入全局变量中。首先,创建一个列表(全局):
# Main.py
poems = []
接下来,就要着手 thread1 线程的编写了。
代码如下:
# Main.py
def thread1():
gloal poems
with open("Poems。txt", "utf-8") as poeemsFile:
poemsString = poemsFile..read()
for line in poemsString.split("\t"):
line = line.split("\t")
if len(line[0]) >= 5:
poems.append(sentence)
上述代码,首先在 thread1 函数首声明 poems 为全局变狼(该程序中也可以不用声明,但为可读性与日后编辑的方便,此处加上了 global 声明),然后打开文件(较全的那个)并读取其内容,而后遍历时通过一定规则将诗句写入列表。
这里需要注意的是 if len( ...
一行有一处对于诗句长短的判断,主要因为该诗库本是个五笔词库,其中包含诗题,故加上此判断。
实现飞花令查询线程
完成了 thread1 的编写, thread2 查询线程的编写也是必不可少的。照例,代码如下。
# Main.py
def thread2():
word = input("""请输入飞花令汉字:")
deal = 0
for poem in poems:
if word in poem:
deal += 1
print(poem)
print(f"\n共 {deal} 首诗!")
这段代码其实没什么特殊的,就是遍历诗的列表并检测、打印符合规则的诗句。其中的 deal 记录着查询到的诗句。
程序优化
一个很简易的飞花令就是这样了。但是,程序还有许多地方可以优化,也可以加入一些新功能——也就是本文题目所述的多诗库。那么接下来,先一步步的加入这个功能。
规范命名、添加参数
为区分两个诗库,首先将两个诗库文件的命名规范化:
常用 诗库: CommonLibrary.txt
较全诗库: FullLibrary.txt
然后,为了线程中调用方便,添加两个常量
# Main.py
COMMON = 1
FULL = 2
再向 thread1 函数添加参数 library
# Main.py
def thread1(library):
...
最后在实例化时传参
# Main.py
writer = Thread(thread1, args=(COMMON, )
至此,准备工作完成。
而控制所用诗库的,通过 args 元组的元素修改。
编写代码
这里先把代码放出来,与前一个类似,可以自行理解:
# Main.py
def thread1(library):
global poems
if library == COMMON:
with open("CommonLibrary.txt", encoding="utf-8") as poemsFile:
poemsString = poemsFile.read()
for line in poemsString.split("\n"):
line = line.split("\t")
if len([0]) >= 5:
poems.append(line[0])
elif library == FULL:
with open("FullLibrary.txt", encoding="utf-8") as poemsFile:
poemsString = poemsFile.read()
for poem in poemsString.split("\n\n"):
poem = poem.split("\n")
if len(poem[3]) <= 128:
poems += poem[3].split("。")[: -1]
仅说明一点,对于 <= 128
的判断是为了辨别此为诗而非赏析。
后记
上文中仅对该程序添加了多诗库的功能,而暂未说明对于代码的优化,如线程间的调度,以及判断机制和诗库的选择。
这些内容稍后我会继续写博客来交流的~
最后,希望如果有人中找到了更有特色、更规范的诗库,欢迎评论区分享出来~ 下一篇我会尽快做的!