
成語接龍
今天難得下班早,不用做公司的末班車,和同事乘公交回家。中途上來幾個(gè)學(xué)生,相互在玩著成語接龍游戲。說是成語,但詞匯卻真是不堪入耳。
6月高考的前一天,我發(fā)布的一篇文章,決戰(zhàn)高考,幫你秒變成語之王,當(dāng)時(shí)只是吧網(wǎng)站的成語爬下來保存到數(shù)據(jù)庫中,文末提到有機(jī)會了抽時(shí)間拿這些數(shù)據(jù)搞點(diǎn)事情,那么今天就來搞事情吧。用3W+的成語數(shù)據(jù)庫,開發(fā)一款成語接龍的小游戲。
接龍規(guī)則
成語接龍是中華民族傳統(tǒng)的文字游戲。它不僅有著悠久的歷史和廣泛的社會基礎(chǔ),同時(shí)還是體現(xiàn)我國文字、文化、文明的一個(gè)縮影,是老少皆宜的民間文化娛樂活動。
成語接龍規(guī)則多樣,大家一般熟知的是采用成語字頭與字尾相連不斷延伸的方法進(jìn)行接龍;用四個(gè)字成語的最后一個(gè)字與下一句成語的第一個(gè)相同的字【音同就可以】,首尾相接不斷延伸,形成長龍。
游戲演示
說了這么多,讓我們來先睹為快,開一局接龍比賽吧:

既然是游戲,就得來個(gè)排名才有意思?。≈皽y試了幾輪數(shù)據(jù),這次我們使用一個(gè)Neo的新用戶來進(jìn)行游戲,隨便接龍了幾次,然后我編了一個(gè)“蟬鳴鳥叫”的成語結(jié)束這次演示,不然像我這種學(xué)富五車的有為青年,好好答不來個(gè)幾十輪的哪里能結(jié)束啊,哈哈...可以看到游戲結(jié)束后退回到首頁,并進(jìn)行了挑戰(zhàn)排序。還好沒幾個(gè)號,不然排不到前五都看不到效果了...
數(shù)據(jù)庫信息
先來看看我們的數(shù)據(jù)庫信息:

數(shù)據(jù)庫表idiom分為id,name,speak,meaning,example,hot 幾個(gè)字段,hot是當(dāng)時(shí)搜索的網(wǎng)站熱詞排行,跟咱們沒有太大關(guān)系...主要是name和speak字段。
登陸排行
為了能增強(qiáng)可玩性,我們在每次開場前,允許用戶隨機(jī)輸入一個(gè)名字。在挑戰(zhàn)過程中,針對用戶堅(jiān)持的接龍次數(shù)進(jìn)行排名。

創(chuàng)建用戶排名表:
CREATE TABLE rank (
name VARCHAR (50) NOT NULL,
round_num INT NOT NULL
);
這里為什么不設(shè)置主鍵呢?主要是排名取前5,用戶使用一個(gè)名字多次參戰(zhàn),如果犀利的話包攬前5看這也很帥氣啊,清一色的都是我,想想都覺得自我滿足感爆棚。
游戲界面
首先映入眼簾的是ROUND 1的接龍次數(shù)顯示,有沒有兒時(shí)拳皇對打的感覺...
為了幫助大家在玩游戲的同時(shí)能學(xué)習(xí)成語知識,也避免有些生僻字不認(rèn)識,所以在界面中顯示了成語、注音、解釋和示例,當(dāng)然示例不是每個(gè)成語都有,網(wǎng)站有啥我就展示啥唄...

成語判斷
首先必須是四字的成語,用戶輸入非四字的成語會彈出警示欄,其次用戶填寫完成語后,會將成語在數(shù)據(jù)庫中進(jìn)行檢索,如果是成語則進(jìn)行接龍后返回電腦的匹配結(jié)果,進(jìn)行第二輪的基隆,如果數(shù)據(jù)庫中無此成語會彈出游戲結(jié)束的提示“挑戰(zhàn)結(jié)束:用戶輸入的成語是自己編的吧!”,返回登陸頁,并將用戶的挑戰(zhàn)結(jié)果入庫rank表進(jìn)行排行。
這里需要注意,成語接龍的收尾字可以不一樣但音必須相同,包括==聲調(diào)==哦!
拼音識別
數(shù)據(jù)庫中的成語我們存在拼音了,但用戶輸入的是漢字,我們?nèi)绾芜M(jìn)行拼音轉(zhuǎn)化呢?這里需要使用到python的一個(gè)模塊pypinyin。針對這個(gè)模塊的使用,之前寫過一篇文章Python為文檔批量注音(生僻字歌詞為例),喜歡的朋友可以去看看。用法很簡單,但我們需要做到和數(shù)據(jù)庫中相對應(yīng)才行。
from pypinyin import pinyin
pinyin('唇槍舌劍')
# output:
[['chún'], ['qiāng'], ['shé'], ['jiàn']]
# 此處為一個(gè)嵌套列表,我們需要轉(zhuǎn)化為數(shù)據(jù)庫中的格式
' '.join(map(lambda x: x[0], pinyin('唇槍舌劍')))
# output:
'chún qiāng shé jiàn'
Jinjia2模板
大家看到不管是用戶登錄還是游戲界面,外框內(nèi)容基本一致,基于這種場景使用Jinjia2的模板繼承是個(gè)很不錯的選擇:
layout.html主要負(fù)責(zé)大體框架及相關(guān)css和js的引入工作,使用Bootstrap+Jquery分分鐘搞定。
<!DOCTYPE html>
<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>清風(fēng)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-歡迎關(guān)注我的公眾號:<a href="http://www.itdecent.cn/u/d23fd5012bed">清風(fēng)Python</a>
</div>
</div>
</body>
</html>
login.html涉及到挑戰(zhàn)者排行和用戶名提交與頁面跳轉(zhuǎn)
game.html主要負(fù)責(zé)成語接龍游戲的監(jiān)控與AJAX數(shù)據(jù)的后臺刷新。
由于篇幅有限就不再這里贅述了,代碼文末會給出。
Flask裝飾器
首先,我們的游戲涉及到SQLite數(shù)據(jù)庫的交互,所以在每次請求前,需要建立數(shù)據(jù)庫,請求結(jié)束后需要釋放連接。此時(shí)我們需要使用到兩個(gè)裝飾器,@app.before_request和@app.teardown_request,before_request見名知意就是在請求訪問前調(diào)動該裝飾器,那么為什么不用對應(yīng)的@app.after_request呢?因?yàn)榧幢阌脩舸a在執(zhí)行過程中,出現(xiàn)任何錯誤,也可以通過@app.teardown_request裝飾器最終釋放數(shù)據(jù)庫連接,但@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[0] if rv else None) if 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')
def game():
if not session.get('user'):
return redirect(url_for('index'))
id = random.randint(1, 30000)
idiom = query_db('select * from idiom where id = ?',
[id])
return render_template('game.html', user=session.get('user'), idiom=idiom)
@app.route('/more/<user_idiom>')
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': "挑戰(zhàn)結(jié)束:用戶輸入的成語是自己編的吧!", 'url': request.host_url})
手機(jī)搭建項(xiàng)目
搭建好的游戲網(wǎng)站,我們可以在局域網(wǎng)內(nèi)共享, 但日常想進(jìn)行練手,如果能使用手機(jī)運(yùn)行我們的網(wǎng)站豈不是更爽?
之前寫過一篇將安卓手機(jī)打造成你的python全棧開發(fā)利器,通過這種方式我們就能把python程序在手機(jī)端完美運(yùn)行了,來試試看吧。
代碼clone
代碼我已經(jīng)上傳到了我的git倉庫,手機(jī)登陸Termux直接clone下載即可:
git clone https://github.com/BreezePython/IdiomsGame.git
pipenv導(dǎo)入
進(jìn)入clone好的代碼路徑,之后輸入pipenv install創(chuàng)建虛擬環(huán)境并下載依賴的模塊
鍵入pipenv shell 進(jìn)入虛擬環(huán)境
通過flask run運(yùn)行我們的Flask app程序...



The End
今天的Flask項(xiàng)目開發(fā)成語接龍游戲的文章,公眾號清風(fēng)Python回復(fù)成語接龍,自動獲取代碼的百度網(wǎng)盤地址。如果你覺得不錯,希望能動動手指轉(zhuǎn)發(fā)給你身邊的朋友們。