开发之前
Python非常有意思,可以开发各种好玩的东西,而且代码很简洁。本文将指导大家怎样用Python实现成语接龙。我们将分为分为两个版本,一个是基础版,实现基本的成语接龙功能。还有一个是加强版,是在简易版上进行扩展,功能更为复杂且完善。
这个可以应用在很多方面,比如说聊天机器人,而且还可以结合itchat这个Python的微信接口玩出花样等等。
下面放实例:
开发环境:Windows
Python版本:3.x
外置模块准备:无
文件准备:成语库文件(例如我使用的是idiom.txt),当然也可以从网上抓取匹配成语,但效率相对要慢。本功能是完全可以在本地实现的。
文件链接:https://pan.baidu/s/1dFFyHQ5 密码:6eiv
文件内容图:
我整理出了共11174个常用成语,不是很全但一般使用是没有问题的,你们也可以酌情自行添加补充。
基础版实现
实现原理,就是调用本地成语库进行字符串首尾条件匹配。
先说一下简易版成语接龙规则:
1.接龙的成语的第一个字必须要与前一个成语结尾的字相同
2.接龙的成语必须是四字成语
3.已使用过的成语双方均不得再次使用
4.一方不按照规则接龙或接不下去时判定失败
我们将其功能用函数分解了,似的结构更加清晰也方便调试,源码(文件名为”idiom_s.py”)及注释如下:
import random
def idiom_exists(x):
"""判断是否为成语的函数,参数为字符串,判断该字符串是否在成语库中"""
with open('idiom.txt','r') as f:
for i in set(f.readlines()):
if x == i.strip():
return True
return False
def idiom_test(idiom1, idiom2):
"""判断两个成语是否达成接龙条件"""
if idiom2[0] != idiom1[-1] or len(idiom2) != 4:
return False
return True
def idiom_select(x):
"""核心代码部分,参数x为成语,返回该成语的接龙匹配成语"""
if x == None:
with open('idiom.txt','r') as f:
return random.choice(f.readlines())[:-1]
else:
with open('idiom.txt','r') as f:
base = f.readlines()
random.shuffle(base)
for i in base:
if i[:-1] == x or len(i) != 5:
continue
if i[0] == x[-1]:
return i[:-1]
return None
def idiom_start(start = 0):
"""start参数表示先后手,0表示电脑先手,1表示玩家先手;返回值代表游戏结果,为0表示玩家失败,为1代表玩家胜利"""
memory = set() #记忆集合,用于判断成语是否被重复使用
#如果电脑先手,电脑先抛出的第一个成语我们给点限制,要求它的接龙成语必须存在
if start == 0:
while True:
t = idiom_select(None)
if idiom_select(t) != None and len(t) == 4:
break
print(t)
else:
p = input("请输入成语:")
if p.strip() == '':
print("游戏结束!你输了")
return 0
if idiom_exists(p) == False:
print("游戏结束!该成语不存在")
return 0
memory.add(p)
cycle_flag = 0 #控制while True循环次数
while True:
t = idiom_select(p)
cycle_flag += 1
if t not in memory:
break
if cycle_flag == 10:
t = None
break
if t == None:
print("恭喜你,你赢了!")
return 1
else:
print(t)
memory.add(t)
while True:
p = input("请输入成语:")
if p.strip() == '':
print("游戏结束!你输了")
if idiom_exists(p) == False:
print("游戏结束!该成语不存在")
return 0
if p in memory:
print("游戏结束!该成语已被使用过")
return 0
if idiom_test(t, p) == False:
print("游戏结束!你未遵守游戏规则")
return 0
memory.add(p)
cycle_flag = 0
while True:
t = idiom_select(p)
cycle_flag += 1
if t not in memory:
break
if cycle_flag == 10:
t = None
break
if t == None:
print("恭喜你,你赢了!")
return 1
else:
print(t)
memory.add(t)
#测试运行
idiom_start()
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
importrandom
defidiom_exists(x):
"""判断是否为成语的函数,参数为字符串,判断该字符串是否在成语库中"""
withopen('idiom.txt','r')asf:
foriinset(f.readlines()):
ifx==i.strip():
returnTrue
returnFalse
defidiom_test(idiom1,idiom2):
"""判断两个成语是否达成接龙条件"""
ifidiom2[0]!=idiom1[-1]orlen(idiom2)!=4:
returnFalse
returnTrue
defidiom_select(x):
"""核心代码部分,参数x为成语,返回该成语的接龙匹配成语"""
ifx==None:
withopen('idiom.txt','r')asf:
returnrandom.choice(f.readlines())[:-1]
else:
withopen('idiom.txt','r')asf:
base=f.readlines()
random.shuffle(base)
foriinbase:
ifi[:-1]==xorlen(i)!=5:
continue
ifi[0]==x[-1]:
returni[:-1]
returnNone
defidiom_start(start=0):
"""start参数表示先后手,0表示电脑先手,1表示玩家先手;返回值代表游戏结果,为0表示玩家失败,为1代表玩家胜利"""
memory=set()#记忆集合,用于判断成语是否被重复使用
#如果电脑先手,电脑先抛出的第一个成语我们给点限制,要求它的接龙成语必须存在
ifstart==0:
whileTrue:
t=idiom_select(None)
ifidiom_select(t)!=Noneandlen(t)==4:
break
print(t)
else:
p=input("请输入成语:")
ifp.strip()=='':
print("游戏结束!你输了")
return0
ifidiom_exists(p)==False:
print("游戏结束!该成语不存在")
return0
memory.add(p)
cycle_flag=0#控制while True循环次数
whileTrue:
t=idiom_select(p)
cycle_flag+=1
iftnotinmemory:
break
ifcycle_flag==10:
t=None
break
ift==None:
print("恭喜你,你赢了!")
return1
else:
print(t)
memory.add(t)
whileTrue:
p=input("请输入成语:")
ifp.strip()=='':
print("游戏结束!你输了")
ifidiom_exists(p)==False:
print("游戏结束!该成语不存在")
return0
ifpinmemory:
print("游戏结束!该成语已被使用过")
return0
ifidiom_test(t,p)==False:
print("游戏结束!你未遵守游戏规则")
return0
memory.add(p)
cycle_flag=0
whileTrue:
t=idiom_select(p)
cycle_flag+=1
iftnotinmemory:
break
ifcycle_flag==10:
t=None
break
ift==None:
print("恭喜你,你赢了!")
return1
else:
print(t)
memory.add(t)
#测试运行
idiom_start()
这就是简易版的全部内容,测试时将该程序”idiom_s.py”和成语库文件”idiom.txt”置于同一目录下,放个测试效果图:
增强版实现
简易版的游戏规则略显严格,我们可以稍微对其进行点改变使其更加有趣。但原则上增强版也兼容简易版的规则,这时我们可以用参数调节游戏规则。
拓展版成语接龙规则:
1.接龙的成语的第一个字必须要与前一个成语结尾的字相同(mode = 0); 接龙的成语的第一个字的拼音包括音调要与前一个成语结尾的字的拼音和音调相同(mode = 1);接龙的成语的第一个字的拼音字母(不包括音调)与前一个成语结尾的字的拼音字母相同(mode = 2)
2.接龙的成语必须是四字成语(opt = 0);接龙的成语可以不是四字成语(opt = 1)
3.已使用过的成语双方均不得再次使用
4.一方不按照规则接龙或接不下去时判定失败
可以看出拓展版的确对简易版做了比较大的拓展,还涉及汉字转拼音,实现详见我的另一篇文章:Python实现文字转语音功能 – 知乎专栏
下面展示源码(文件名为”idiom_p.py”):
import random
def chinese_to_pinyin(x):
"""参数为字符串,返回为该字符串对应的汉语拼音"""
y = ''
dic = {}
with open("unicode_pinyin.txt") as f:
for i in f.readlines():
dic[i.split()[0]] = i.split()[1]
for i in x:
i = str(i.encode('unicode_escape'))[-5:-1].upper()
try:
y += dic[i] + ' '
except:
y += 'XXXX ' #非法字符我们用XXXX代替
return y
def idiom_exists(x):
"""判断是否为成语的函数,参数为字符串,判断该字符串是否在成语库中"""
with open('idiom.txt','r') as f:
for i in set(f.readlines()):
if x == i.strip():
return True
return False
def idiom_test(idiom1, idiom2, mode, opt):
"""判断两个成语是否达成接龙条件"""
#为了可读性,我把它分开写,比较清晰
if mode == 0 and idiom2[0] != idiom1[-1]:
return False
if mode == 1 and chinese_to_pinyin(idiom2[0]) != chinese_to_pinyin(idiom1[-1]):
return False
if mode ==2 and chinese_to_pinyin(idiom2[0])[:-2] != chinese_to_pinyin(idiom1[-1])[:-2]:
return False
if opt == 0 and len(idiom2) != 4:
return False
return True
def idiom_select(x, mode, opt):
"""核心代码部分,参数x为成语,返回该成语的接龙匹配成语"""
if x == None:
with open('idiom.txt','r') as f:
return random.choice(f.readlines())[:-1]
else:
with open('idiom.txt','r') as f:
#以下六行代码,通过索引排除无效循环,显著提升运行效率
pinyin = chinese_to_pinyin(x[-1])
base = f.readlines()
if pinyin[0] != 'Z':
base = base[base.index(pinyin[0]+'\n'):base.index(chr(ord(pinyin[0])+1)+'\n')]
else:
base = base[base.index(pinyin[0]+'\n'):]
random.shuffle(base)
for i in base:
if i[:-1] == x or (opt == 0 and len(i) != 5):
continue
if mode == 0 and i[0] == x[-1]:
return i[:-1]
if mode == 1 and chinese_to_pinyin(i[0]) == pinyin:
return i[:-1]
if mode == 2 and chinese_to_pinyin(i[0])[:-2] == pinyin[:-2]:
return i[:-1]
return None
def idiom_start(start = 0, mode = 0, opt = 0):
"""start参数表示先后手,0表示电脑先手,1表示玩家先手;返回值代表游戏结果,为0表示玩家失败,为1代表玩家胜利"""
memory = set() #记忆集合,用于判断成语是否被重复使用
if start == 0:
while True:
t = idiom_select(None, mode, opt)
if idiom_select(t, mode, opt) != None:
break
print(t)
else:
p = input("请输入成语:")
if p.strip() == '':
print("游戏结束!你输了")
return 0
if idiom_exists(p) == False:
print("游戏结束!该成语不存在")
return 0
memory.add(p)
cycle_flag = 0 #控制while True循环次数
while True:
t = idiom_select(p, mode, opt)
cycle_flag += 1
if t not in memory:
break
if cycle_flag == 10:
t = None
break
if t == None:
print("恭喜你,你赢了!")
return 1
else:
print(t)
memory.add(t)
while True:
p = input("请输入成语:")
if p.strip() == '':
print("游戏结束!你输了")
if idiom_exists(p) == False:
print("游戏结束!该成语不存在")
return 0
if p in memory:
print("游戏结束!该成语已被使用过")
return 0
if idiom_test(t, p, mode, opt) == False:
print("游戏结束!你未遵守游戏规则")
return 0
memory.add(p)
cycle_flag = 0
while True:
t = idiom_select(p, mode, opt)
cycle_flag += 1
if t not in memory:
break
if cycle_flag == 10:
t = None
break
if t == None:
print("恭喜你,你赢了!")
return 1
else:
print(t)
memory.add(t)
#测试运行,修改参数使其变为规则更加宽松的接龙(mode和opt默认为0则为简易版的成语接龙)
idiom_start(start=1, mode=2, opt=1)
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
importrandom
defchinese_to_pinyin(x):
"""参数为字符串,返回为该字符串对应的汉语拼音"""
y=''
dic={}
withopen("unicode_pinyin.txt")asf:
foriinf.readlines():
dic[i.split()[0]]=i.split()[1]
foriinx:
i=str(i.encode('unicode_escape'))[-5:-1].upper()
try:
y+=dic[i]+' '
except:
y+='XXXX '#非法字符我们用XXXX代替
returny
defidiom_exists(x):
"""判断是否为成语的函数,参数为字符串,判断该字符串是否在成语库中"""
withopen('idiom.txt','r')asf:
foriinset(f.readlines()):
ifx==i.strip():
returnTrue
returnFalse
defidiom_test(idiom1,idiom2,mode,opt):
"""判断两个成语是否达成接龙条件"""
#为了可读性,我把它分开写,比较清晰
ifmode==0andidiom2[0]!=idiom1[-1]:
returnFalse
ifmode==1andchinese_to_pinyin(idiom2[0])!=chinese_to_pinyin(idiom1[-1]):
returnFalse
ifmode==2andchinese_to_pinyin(idiom2[0])[:-2]!=chinese_to_pinyin(idiom1[-1])[:-2]:
returnFalse
ifopt==0andlen(idiom2)!=4:
returnFalse
returnTrue
defidiom_select(x,mode,opt):
"""核心代码部分,参数x为成语,返回该成语的接龙匹配成语"""
ifx==None:
withopen('idiom.txt','r')asf:
returnrandom.choice(f.readlines())[:-1]
else:
withopen('idiom.txt','r')asf:
#以下六行代码,通过索引排除无效循环,显著提升运行效率
pinyin=chinese_to_pinyin(x[-1])
base=f.readlines()
ifpinyin[0]!='Z':
base=base[base.index(pinyin[0]+'\n'):base.index(chr(ord(pinyin[0])+1)+'\n')]
else:
base=base[base.index(pinyin[0]+'\n'):]
random.shuffle(base)
foriinbase:
ifi[:-1]==xor(opt==0andlen(i)!=5):
continue
ifmode==0andi[0]==x[-1]:
returni[:-1]
ifmode==1andchinese_to_pinyin(i[0])==pinyin:
returni[:-1]
ifmode==2andchinese_to_pinyin(i[0])[:-2]==pinyin[:-2]:
returni[:-1]
returnNone
defidiom_start(start=0,mode=0,opt=0):
"""start参数表示先后手,0表示电脑先手,1表示玩家先手;返回值代表游戏结果,为0表示玩家失败,为1代表玩家胜利"""
memory=set()#记忆集合,用于判断成语是否被重复使用
ifstart==0:
whileTrue:
t=idiom_select(None,mode,opt)
ifidiom_select(t,mode,opt)!=None:
break
print(t)
else:
p=input("请输入成语:")
ifp.strip()=='':
print("游戏结束!你输了")
return0
ifidiom_exists(p)==False:
print("游戏结束!该成语不存在")
return0
memory.add(p)
cycle_flag=0#控制while True循环次数
whileTrue:
t=idiom_select(p,mode,opt)
cycle_flag+=1
iftnotinmemory:
break
ifcycle_flag==10:
t=None
break
ift==None:
print("恭喜你,你赢了!")
return1
else:
print(t)
memory.add(t)
whileTrue:
p=input("请输入成语:")
ifp.strip()=='':
print("游戏结束!你输了")
ifidiom_exists(p)==False:
print("游戏结束!该成语不存在")
return0
ifpinmemory:
print("游戏结束!该成语已被使用过")
return0
ifidiom_test(t,p,mode,opt)==False:
print("游戏结束!你未遵守游戏规则")
return0
memory.add(p)
cycle_flag=0
whileTrue:
t=idiom_select(p,mode,opt)
cycle_flag+=1
iftnotinmemory:
break
ifcycle_flag==10:
t=None
break
ift==None:
print("恭喜你,你赢了!")
return1
else:
print(t)
memory.add(t)
#测试运行,修改参数使其变为规则更加宽松的接龙(mode和opt默认为0则为简易版的成语接龙)
idiom_start(start=1,mode=2,opt=1)
这就是扩展版的全部内容,测试时将该程序”idiom_p.py”,成语库文件”idiom.txt”和汉字拼音文件”unicode_pinyin.txt”置于同一目录下,放个测试效果图:
大致实现就是这样,大家也可以自己在此基础上进行更多拓展,如结合我上一篇文章实现成语的语音输出,也是非常不错的。
实例结束,我的表演完了,谢谢大家!如果这篇文章对你有帮助,请在收藏的同时一赞支持,谢谢!光收藏不点赞的让我好心塞啊。
更多推荐
python成语接龙代码_Python实现成语接龙
发布评论