python从键盘上输入五个数字打一成语_python实现成语填字游戏 自动生成题目

本文介绍了一个Python程序,用于自动生成成语填字游戏。程序通过连接数据库,根据给定的关键字随机选择成语,并确保它们在棋盘上正确排列,避免坐标重复。最后在终端展示成语游戏的布局。
摘要由CSDN通过智能技术生成

开心!先来个成果图记录一下,之前一直觉得很神奇,自动生成题目的算法是怎样的,好奇着好奇着就去试试,其实好像也不涉及到啥算法,摸索着总算弄出来啦,大神莫笑小白之欢喜。

image.png

代码还没整理好,如果有人感兴趣的话,我再把源码贴出来分享分享~

===============================================

2020.04.07补一下源码

不常上简书没留意到留言,嘻嘻嘻,当时偷懒没有上传。我是写java的,本身不是写python的,所以代码里面可能有些不太优雅的地方,目标只是实现功能,见谅哈。另外有些代码可能是过程中为了调试写的,也懒得删了,记录了最原始的创作过程。(对了,我实现的这个,也是有参考别人的文章的,但是不记得是哪一篇了,看了好多篇,如果觉得有相同的地方,抱歉啊,欢迎原文作者们联系,一定把您大名署上)

可以调整目标成语数量target参数,改成你想要一次输出的成语数量。当然,你也可以优化将它变成传入参数,那会更加优雅一些,交给你自己啦。

在terminal里面运行时,要注意窗口大小,尤其是x轴方向的长度,要符合代码里的设定,不然的话出来的是对不齐的,正常应该是这样:

image.png

如果大小不注意错位的话就会这样了:

image.png

import random

import pymysql

from enum import Enum

#

conn = pymysql.connect(host="localhost", user="root", password="123456", database="idiom", charset="utf8")

cursor = conn.cursor()

class Coordinate(Enum):

X = "x"

Y = "y"

# 选中的成语列表,[‘一心一意’,’掩耳盗铃’]

idioms = []

# 选中的成员的拆分列表,含坐标,[[0,0,’一’],[1,0,’心’],[2,0,’一’],[3,0,’意’]]

splitIdioms = []

# 关键字拆分列表,含坐标,[[0,0,’一’],[1,0,’意’]]

splitKeys = []

# 已使用过的坐标

usedSeats = []

# 目标成语数量(!!!!这里可以修改参数!!!!)

target = 5

# 已经用过的坐标(后续避免重复)

def add_used_seats(idiom_split):

for en in idiom_split:

usedSeats.append((en[0], en[1]))

# 检查坐标是否已被使用

def check_not_in_used_seats(idiom_split, exclude_index):

for i in range(len(idiom_split)):

if usedSeats.__contains__((idiom_split[i][0], idiom_split[i][1])):

if i != exclude_index:

return False

return True

# 获取一个切分好的成语

def get_one(x, y, keyword):

idiom = get_random_idiom(keyword)

idioms.append(idiom)

# 第单数个成语:横放; 第双数个成语:竖放

if len(idioms) % 2 == 0:

direction = Coordinate.Y

else:

direction = Coordinate.X

# 找出这个成语中和上个成语的重用字的索引

last_used_index = idiom.find(keyword) if len(idioms) > 1 else -1

# print("last_used_index is: %s" % last_used_index)

# 切分,添加坐标

idiom_split = split_idiom(x, y, last_used_index, idiom, direction)

# 检查坐标是否已被使用

if not check_not_in_used_seats(idiom_split, last_used_index):

idioms.pop(-1)

return False, None

return True, idiom_split

# 将使用的成语加入到列表中

def add_one(idiom_split):

splitIdioms.extend(idiom_split)

add_used_seats(idiom_split)

def main():

x, y, keyword, last_used_index = 0, 0, '', -1

for i in range(target):

# 获取一个切分好的成语

ret, idiom_split = get_one(x, y, keyword)

# 如果不成功,重新获取,直到成功为止

while not ret:

ret, idiom_split = get_one(x, y, keyword)

# print("succeed to get one idiom: %s" % idiom_split)

# 将获取到的成语加入到列表中

add_one(idiom_split)

# 确定下个成语的关键字

last_used_index = -1 if len(idioms) <= 1 else idioms[-1].find(splitKeys[-1][2])

key_index = random.randint(0, len(idioms[-1]) - 1)

while last_used_index == key_index:

key_index = random.randint(0, len(idioms[-1]) - 1)

splitKeys.append(idiom_split[key_index])

# print("next keyword is: %s" % idiom_split[key_index])

# 准备下一个成语的基础

x = splitKeys[-1][0]

y = splitKeys[-1][1]

keyword = splitKeys[-1][2]

# 调整坐标

# print("usedIdioms: %s" % idioms)

# print("beforeList: %s" % splitIdioms)

fix_border()

# print("finalList: %s" % splitIdioms)

printOnScreen(splitIdioms)

def get_random_idiom(keyword):

if len(keyword) > 0:

keyword = '%' + keyword + '%'

sql = "SELECT chengyu FROM XUEBIJUN AS t1 JOIN (SELECT ROUND(RAND() * (SELECT MAX(id) FROM XUEBIJUN)) AS id) AS t2 WHERE not locate(',',t1.chengyu) %s and t1.id >= t2.id ORDER BY t1.id ASC LIMIT 1" % "and chengyu like '%s'" % keyword

else:

sql = "SELECT chengyu FROM XUEBIJUN AS t1 JOIN (SELECT ROUND(RAND() * (SELECT MAX(id) FROM XUEBIJUN)) AS id) AS t2 WHERE not locate(',',t1.chengyu) and t1.id >= t2.id ORDER BY t1.id ASC LIMIT 1"

cursor.execute(sql)

ret = cursor.fetchone()

while ret is None or idioms.__contains__(ret[0]):

ret = get_random_idiom(keyword)

# print("random idiom: %s" % ret)

return ret[0]

# 切分,添加坐标

def split_idiom(x, y, key_index, idiom, direction):

ret = []

key_index = key_index if key_index > 0 else 0

if direction == Coordinate.X:

for index in range(len(idiom)):

ret.append([x + index - key_index, y, idiom[index]])

else:

for index in range(len(idiom)):

ret.append([x, y + index - key_index, idiom[index]])

return ret

def fix_border():

min_x, min_y = 0, 0

for p in usedSeats:

min_x = p[0] if p[0] < min_x else min_x

min_y = p[1] if p[1] < min_y else min_y

for p in splitIdioms:

p[0] = p[0] + abs(min_x)

p[1] = p[1] + abs(min_y)

def printOnScreen(info):

newStr = ' ' * (40 * 40)

# 注意上面的空格是个中文空格!!

newList = list(newStr)

# 把字符串编程list以方便下面的直接索引操作

# 如果输入值对某个坐标位置有定义,则将该位置的空格换成对应字符

for pinfo in info:

index = 40 * pinfo[1] + pinfo[0]

newList[index] = pinfo[2]

# 再把list变回字符串,以方便输出

finalStr = ''.join(newList)

print(finalStr)

# info = [(0, 0, '天'), (1, 0, '地'), (3, 0, '人'), (2, 1, '日'), (2, 2, '月'), (2, 3, '风')]

# printOnScreen(info)

main()

经典填字游戏:在3*3个方格的方阵中要填入数字1到N(N>=10)内的某9个数字,每个方格填一个整数,使得所有相邻两个方格内的两个整数之和为质数。试求出所有满足这个要求的各种数字填法。 //我们可以通过改变N的值来求不同数字范围的质数数组,如果超出整型的范围,还需要改变数据类型。 //f[i]来记录数字i是否使用过, //T[i]用来记录下一个可以插在数字i后面的与其和为质数的数字在F[i][]中的位置。 //用F[i][j]来存储按数字从小到大的顺序得出的与数字i和为质数的第j个数字, //例如:F[1][2]存储的是与数字1的和为质数的第二个数字,我们可以通过查询数组F[][]的第一行找出第二个不为0 //值,然后将当前数组单元的列号存储到F[1][2]中,即F[1][2] = 4。 //算法思想是通过查询二维数组F[][],来确定下一个可以插入数组num[]的未使用过的数字,并记录该数字位于数组F[][]的位置, //以便回溯时寻找下一个符合要求的数字。如果不存在这样的未使用的数字,则需要回溯到上一个已插入num[]的数字, //寻找下一个可以插在该数字后面的未使用过的数字进行插入,如果所有的数字都已经插入到num[]中, //如是则打印结果。当所有数字都已插入num[]中,开始 //进行回溯,重复上述操作,寻找其他符合要求的序列。 //这里面有一个关键在于处理位于num数组右下角四个格子的数时,不光需要判断与前一个数i的关系,还需要判断其头顶上的元素之和是否为素数。 //程序中有一大段代码是处理i和j的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值