python编写古诗_用Python实现古诗词填字游戏(一)

利用古诗词做填字游戏是一项很有趣的活动,通常的填字游戏都是由几横几竖构成,如下图:

显然,横竖交叉的位置就是两句诗共有的字。那么,问题来了,如何从众多诗文中找到有共同字的句子呢?

这里Mr. PosPro用Python写了一个小程序,可以生成简单填字游戏(的模型),程序输出的效果如下:

可以看到,程序从全唐诗中找到了3句有共同字的句子,并以合适的位置完成了排列。?和#代表了交叉处的字,同时在屏幕下方给出了最后答案。

下面Mr. PosPro教你如何实现这个程序。程序总体上分为三个部分:

(一)从TXT文件《全唐诗》中提取有用信息,并按照我们需要的格式保存到新文件中

(二)实现一个在DOS窗口的输出程序,以便在指定位置输出特定文字

(三)核心部分,抽取诗句,找到关联的字,确定每一个字的输出位置,并把最后结果交给(二)中实现的程序

本次主要讨论第(一)部分内容,其它部分的实现请参见后续博客。

想要做一个古诗词的填字游戏,首先得收集到足够多的诗句作为原料库。可以在网上搜索“全唐诗TXT“,我选择的版本大概有8.2M,内容如图:

这个版本适合直接阅读,但却不适合用程序处理,所以首先得写一段程序,把这四百多万字的文本文件,转化成我想要形式。对此我是这样设计的:

1>去掉所有无关信息,只保留标题,作者,诗文内容(标点符号也不要)

2>一首诗的所有信息都在一行中表达,从左到右依次为:行号,题目,作者,诗句全文,所有内容Tab隔开。

即,形成如下这个样子

下面就是具体的程序实现了:

1.读入文件

i=3200 # PosPro says:在测试时无需读取全部信息,可以通过此参数调整读入行数,加快测试

with open('全唐诗.txt',encoding='gbk',errors="ignore") as f:

for line in f:

line=line.rstrip().lstrip() #去除左右空白字符

if i>0:

analyzeText(line)

i-=1

else:

break

代码很简单,但有个小技巧可以和大家分享一下:由于文件很大(超过400万字),在测试阶段如果一次性读入的话,会很耗时间。这里用i控制一下读入的行数。毕竟,我们首先要验证的是功能的正确。

2. analyzeText函数在干什么?

仔细分析《全唐诗》的文本,可以发现一个特点,即‘卷’和‘【’同时出现的那一行就是诗文的起始,我们应该以此为标志,将程序分为寻找下一首诗,处理标题,处理诗文等几个阶段,代码如下:(PosPro says: Python的优美之处就在于,程序本身和对程序的解释几乎是一体的,你读懂了代码也就理解了代码。当然,我也会加上足够多的注释的。)

INDEXNUM=0

EMPTYLINE=0

STATEFLAG=0

def analyzeText(line):

global INDEXNUM, EMPTYLINE, STATEFLAG

if line=='':

EMPTYLINE+=1

#PosPro says:构成一个无限循环,只有通过return才能够退出整个函数,读取下一行

while (True):

if STATEFLAG==0:

#0:始状态,在此状态下若发现某一行同时包含'卷'和'【',则进入诗句标题

if ('卷' in line) and ('【' in line):

STATEFLAG=1

else:

return

#1: 表示当前句为标题

if STATEFLAG==1:

INDEXNUM+=1

processTitle(line)

STATEFLAG=2

EMPTYLINE=0

return

#2: 表示正在读取诗文,但需要特别考虑空行和进入下一首诗标题的情况

if STATEFLAG==2:

if EMPTYLINE>2:

processEndPoem()

STATEFLAG=0

EMPTYLINE=0

return

elif ('卷' in line) and ('【' in line):

processEndPoem()

STATEFLAG=1

EMPTYLINE=0

#PosPro says:此处不return,因为该line还需交由状态1处理

else:

processPoemText(line)

return

3. 分而治之,实现对标题、诗文,以及结束的分别处理。三个函数一起给出:

def processTitle(line):

print (str(INDEXNUM), end='\t') #INDEX就是我自己做的诗文索引

idx1=line.find('【')

idx2=line.find('】')

poemTitle=line[idx1+1:idx2]

author=line[idx2+1:]

print(poemTitle,end='\t')

if author.rstrip()=='':

print ('佚名',end='\t') #发现有些诗句没有注明作者,那我就自己标一下

else:

print(author,end='\t')

def processPoemText(line):

#此时已深入到诗句中了,要将各种标点符号删掉,并将每句诗文作为list中的一项

if not line=='':

#如果要以多个不同字符作为分隔符,就必须用

everyLine=re.split(',|。',line)

for l in everyLine:

print (l, end='\t')

def processEndPoem():

print ('') #完成一个换行

4. 等等,不是说要产生一个新文件么?怎么都是在DOS窗口显示的啊?

别急,这就是Python另一个优雅之处了。在命令行敲完文件名之后,加上">1.txt",想输出到哪里就到哪里

附:全部代码如下:

## Created by PosPro

## http://blog.csdn.net/pospro

import re

i=3200 # PosPro says:在测试时无需读取全部信息,可以通过此参数调整读入行数,加快测试

INDEXNUM=0

EMPTYLINE=0

STATEFLAG=0

def processTitle(line):

print (str(INDEXNUM), end='\t') #INDEX就是我自己做的诗文索引

idx1=line.find('【')

idx2=line.find('】')

poemTitle=line[idx1+1:idx2]

author=line[idx2+1:]

print(poemTitle,end='\t')

if author.rstrip()=='':

print ('佚名',end='\t') #发现有些诗句没有注明作者,那我就自己标一下

else:

print(author,end='\t')

def processPoemText(line):

#此时已深入到诗句中了,要将各种标点符号删掉,并将每句诗文作为list中的一项

if not line=='':

#PosPro says:如果要以多个不同字符作为分隔符,就必须用到re模块了

everyLine=re.split(',|。',line)

for l in everyLine:

print (l, end='\t')

def processEndPoem():

print ('') #完成一个换行

def analyzeText(line):

global INDEXNUM, EMPTYLINE, STATEFLAG

if line=='':

EMPTYLINE+=1

#PosPro says:构成一个无限循环,只有通过return才能够退出整个函数,读取下一行

while (True):

if STATEFLAG==0:

#0:始状态,在此状态下若发现某一行同时包含'卷'和'【',则进入诗句标题

if ('卷' in line) and ('【' in line):

STATEFLAG=1

else:

return

#1: 表示当前句为标题

if STATEFLAG==1:

INDEXNUM+=1

processTitle(line)

STATEFLAG=2

EMPTYLINE=0

return

#2: 表示正在读取诗文,但需要特别考虑空行和进入下一首诗标题的情况

if STATEFLAG==2:

if EMPTYLINE>2:

processEndPoem()

STATEFLAG=0

EMPTYLINE=0

return

elif ('卷' in line) and ('【' in line):

processEndPoem()

STATEFLAG=1

EMPTYLINE=0

#PosPro says:此处不return,因为该line还需交由状态1处理

else:

processPoemText(line)

return

with open('全唐诗.txt',encoding='gbk',errors="ignore") as f:

for line in f:

#去除左右空白字符

line=line.rstrip().lstrip()

if i>0:

analyzeText(line)

i-=1

else:

break

你可能感兴趣的:(python编写古诗)