来源:清风Python(ID:BreezePython)

01 接龙规则

成语接龙是中华民族传统的文字游戏。它不仅有着悠久的历史和广泛的社会基础,同时还是体现我国文字、文化、文明的一个缩影,是老少皆宜的民间文化娱乐活动。

成语接龙规则多样,大家一般熟知的是采用成语字头与字尾相连不断延伸的方法进行接龙;用四个字成语的最后一个字与下一句成语的第一个相同的字【音同就可以】,首尾相接不断延伸,形成长龙。

02 游戏演示

说了这么多,让我们来先睹为快,让我来挑战一局接龙比赛吧:

▲游戏展示

既然是游戏,就得来个排名才有意思啊!之前测试了几轮数据,这次我们使用一个Neo的新用户来进行游戏,随便接龙了几次,然后我编了一个“蝉鸣鸟叫”的成语结束这次演示,不然像我这种学富五车的有为青年,好好答不来个几十轮的哪里能结束啊,哈哈…

可以看到游戏结束后退回到首页,并进行了挑战排序。还好没几个号,不然排不到前五都看不到效果了…

03 数据库信息

先来看看我们的数据库信息:

数据库表idiom分为id, name, speak, meaning, example, hot 几个字段,hot是当时搜索的网站热词排行,跟咱们没有太大关系…主要是name和speak字段。

04 登陆排行

为了能增强可玩性,我们在每次开场前,允许用户随机输入一个名字。在挑战过程中,针对用户坚持的接龙次数进行排名。

创建用户排名表:

CREATE TABLE rank (
    name  VARCHAR (50NOT NULL,
    round_num INT      NOT NULL
);

这里为什么不设置主键呢?主要是排名取前5,用户使用一个名字多次参战,如果犀利的话包揽前5看这也很帅气啊,清一色的都是我,想想都觉得自我满足感爆棚。

05 游戏界面

首先映入眼帘的是ROUND 1的接龙次数显示,有没有儿时拳皇对打的感觉…

为了帮助大家在玩游戏的同时能学习成语知识,也避免有些生僻字不认识,所以在界面中显示了成语、注音、解释和示例,当然示例不是每个成语都有,网站有啥我就展示啥呗…

06 成语判断

首先必须是四字的成语,用户输入非四字的成语会弹出警示栏,其次用户填写完成语后,会将成语在数据库中进行检索,如果是成语则进行接龙后返回电脑的匹配结果,进行第二轮的基隆,如果数据库中无此成语会弹出游戏结束的提示“挑战结束:用户输入的成语是自己编的吧!”返回登陆页,并将用户的挑战结果入库rank表进行排行。

这里需要注意,成语接龙的收尾字可以不一样但音必须相同,包括声调哦!

07 拼音识别

数据库中的成语我们存在拼音了,但用户输入的是汉字,我们如何进行拼音转化呢?这里需要使用到Python的一个模块pypinyin。针对这个模块的使用,之前写过一篇文章Python为文档批量注音(生僻字歌词为例),喜欢的朋友可以去看看。用法很简单,但我们需要做到和数据库中相对应才行。

from pypinyin import pinyin
pinyin(\'唇枪舌剑\')
# output:
[[\'chún\'], [\'qiāng\'], [\'shé\'], [\'jiàn\']]
# 此处为一个嵌套列表,我们需要转化为数据库中的格式
\'  \'.join(map(lambda x: x[0], pinyin(\'唇枪舌剑\')))
# output:
\'chún  qiāng  shé  jiàn\'

08 Jinjia2模板

大家看到不管是用户登录还是游戏界面,外框内容基本一致,基于这种场景使用Jinjia2的模板继承是个很不错的选择:

layout.html主要负责整体框架及相关css和js的引入工作,使用Bootstrap+Jquery分分钟搞定。


<html lang=\"en\">
<head>
    <meta charset=\"UTF-8\">
    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">
    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1 ,user-scalable=no\">
    <title>清风python</title>
    <link rel=\"icon\" href=\"{{ url_for(\'static\',filename=\'favicon.ico\') }}\">
    <link rel=\"stylesheet\" href=\"{{ url_for(\'static\',filename=\'css/bootstrap.min.css\') }}\">
    <link rel=\"stylesheet\" href=\"{{ url_for(\'static\',filename=\'css/main.css\') }}\">
    <script src=\"{{ url_for(\'static\',filename=\'js/jquery.min.js\') }}\"></script>
</head>
<body>

<div class=\"container container-small\">
    <div class=\"content\">
        <div class=\"header\">
            成语接龙
        </div>
        <div class=\"block-info\">
            {% block contents %}
            {% endblock %}
        </div>
    </div>
    <div class=\"footer\">
        ©2019-欢迎关注我的公众号:<a href=\"https://www.jianshu.com/u/d23fd5012bed\">清风Python</a>
    </div>
</div>

</body>
</html>

由于篇幅有限就不再这里赘述了,代码文末会给出。

09 Flask装饰器

首先学富五车读音,我们的游戏涉及到SQLite数据库的交互,所以在每次请求前,需要建立数据库,请求结束后需要释放连接。此时我们需要使用到两个装饰器,@app.before_request和@app.teardown_request学富五车读音,before_request见名知意就是在请求访问前调动该装饰器,那么为什么不用对应的@app.after_request呢?

因为即便用户代码在执行过程中,出现任何错误,也可以通过@app.teardown_request装饰器最终释放数据库连接,但@app.after_request可不行…

Flask整体代码如下:

import sqlite3
from flask import Flask, render_template, request, g, session, redirect, url_for, jsonify
import random
from pypinyin import pinyin

app = Flask(__name__)
DATABASE = \'static/db/database.db\'
app.secret_key = \'Breeze Python\'


def connect_db():
    return sqlite3.connect(DATABASE)


@app.before_request
def before_request():
    g.db = connect_db()


@app.teardown_request
def teardown_request(exception):
    if hasattr(g, \'db\'):
        g.db.close()


def query_db(query, args=(), one=True):
    cur = g.db.execute(query, args)
    rv = [dict((cur.description[idx][0], value)
               for idx, value in enumerate(row)) for row in cur.fetchall()]
    if not query.startswith(\'select\'):
        g.db.commit()
    return (rv[0if rv else Noneif one else rv


@app.route(\'/\', methods=[\'GET\', \'POST\'])
def index():
    if request.method == \'POST\':
        user = request.form.get(\'name\')
        session[\'user\'] = user
        session[\'round\'] = 1
        return redirect(url_for(\'game\'))
    rank_list = query_db(\'select * from rank order by round_num desc limit 5\',one=False)
    print(rank_list)
    return render_template(\'login.html\', rank_list=rank_list)


@app.route(\'/game\')
48def game():
    if not session.get(\'user\'):
        return redirect(url_for(\'index\'))
    id = random.randint(130000)
    idiom = query_db(\'select * from idiom where id = ?\',
                     [id])
    return render_template(\'game.html\', user=session.get(\'user\'), idiom=idiom)


@app.route(\'/more/\')
def more(user_idiom):
    speak_list = pinyin(user_idiom)
    print(speak_list[0][-1])
    idiom_speak = \'  \'.join(map(lambda x: x[0], speak_list))
    if query_db(\'select * from idiom where speak = ?\',
                [idiom_speak]):
        new_idiom = query_db(\"select * from idiom where speak like (\'%s%%\')\" % speak_list[-1][0])
        session[\'round\'] = session.get(\'round\') + 1
        print({\'code\'200\'round\': session.get(\'round\'), \'info\': new_idiom})
        return jsonify({\'code\'200\'round\': session.get(\'round\') + 1\'info\': new_idiom})
    else:
        query_db(\'replace into rank (name,round_num) values (?,?)\',
                 [session.get(\'user\'), session.get(\'round\')])
        return jsonify({\'code\'404\'error\'\"挑战结束:用户输入的成语是自己编的吧!\"\'url\': request.host_url})

代码我已经上传到了我的git仓库:

划重点

干货直达

发表回复

后才能评论

本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。

最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。 若排除这种情况,可在对应资源底部留言,或联络我们。

对于会员专享、整站源码、程序插件、网站模板、网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。

如果您已经成功付款但是网站没有弹出成功提示,请联系站长提供付款信息为您处理

源码素材属于虚拟商品,具有可复制性,可传播性,一旦授予,不接受任何形式的退款、换货要求。请您在购买获取之前确认好 是您所需要的资源