国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

在線捉鬼游戲開發(fā)之二-設(shè)計(jì)業(yè)務(wù)對象與對象職責(zé)劃分(3)

2019-11-14 15:52:22
字體:
供稿:網(wǎng)友

“回憶總是殘酷的”——在“設(shè)計(jì)業(yè)務(wù)對象與對象職責(zé)劃分(2)”中,對舊版本的代碼進(jìn)行了剖析,也發(fā)現(xiàn)了不少臭味道,本篇將記錄我是如何建設(shè)新版的業(yè)務(wù)對象職責(zé)劃分。

一、復(fù)習(xí)設(shè)計(jì)模式

當(dāng)初自學(xué)設(shè)計(jì)模式的路徑是:從《大話設(shè)計(jì)模式》開始(做了筆記),到Gof的《設(shè)計(jì)模式》,再到辛勤網(wǎng)友們的各篇總結(jié)日志(只看C#的可能會(huì)有些局限~)。此后,每當(dāng)我有需要更新代碼的時(shí)候,或者覺得不太記得清23種經(jīng)典設(shè)計(jì)模式的時(shí)候,我就會(huì)回翻我的筆記,主要看:模式目的、應(yīng)用場景,以最快速度在腦子里回放。在復(fù)習(xí)的同時(shí),會(huì)不自覺就想到這個(gè)設(shè)計(jì)模式可能可以解決要更新項(xiàng)目中的某些問題,然后立即翻看第(2)篇中的代碼剖析,并在草稿板(買了塊白板當(dāng)草稿紙)上做uml類圖簡單設(shè)計(jì),并在腦海里過示例代碼。我覺得這個(gè)做法就好像、也應(yīng)該像日后需要熟能生巧的動(dòng)作一樣,要不斷重復(fù),直到嫻熟。

寫到這里的時(shí)候,覺得有必要分享一份筆記中一句話總結(jié)23中設(shè)計(jì)模式的部分,所以寫了:一句話的設(shè)計(jì)模式,相信必是槽點(diǎn)滿滿:)

經(jīng)過復(fù)習(xí),初步覺得也許能用上的模式有:

創(chuàng)建型:單例(Setting),候選:工廠;

結(jié)構(gòu)型:裝飾(處理各角色間的結(jié)構(gòu)關(guān)系),候選:橋接、代理;

行為型:觀察者(定時(shí)更新)、中介者(由Game作為各參與者的中介)、狀態(tài)(投死狀態(tài)改變,可能會(huì)設(shè)計(jì)過度),候選:訪問者;

 

二、優(yōu)化游戲流程

(1)舊版:進(jìn)入后有旁觀/報(bào)名按鈕供登陸者選擇,Table類負(fù)責(zé)維護(hù)所有人的名單列表,退出旁觀/報(bào)名都會(huì)不斷地變更類;

優(yōu)化:進(jìn)入后旁觀者什么也不需要做,而是報(bào)名者需要點(diǎn)擊“入座”按鈕——較符合現(xiàn)實(shí)場景;Table類不再維護(hù)旁觀者列表——因?yàn)門able游戲桌只需要管誰參與游戲,旁觀者叫什么名字在整個(gè)游戲流程中并沒有貢獻(xiàn);游戲開始前的站起/入座(也就是報(bào)名與旁觀)都不會(huì)有新的類生成——因?yàn)榫唧w是平民、白癡還是鬼的身份應(yīng)該在游戲開始后才生成,而不是這一開始就確定下來,如此做法,也避免了(2)篇中類之間復(fù)雜轉(zhuǎn)換的問題。

(2)舊版:投票沒做完

優(yōu)化:由AddBallot()增加投票—IsVoteEnd()是否投票結(jié)束——Roll()唱票,三個(gè)部分。即:投票環(huán)節(jié)時(shí),每當(dāng)有一位參與者點(diǎn)選了要投的人或棄權(quán)票,投票管理者都會(huì)檢查是否已經(jīng)結(jié)束,若沒結(jié)束,則繼續(xù)接收投票,若已結(jié)束,就開始唱票。很好理解吧~

 

三、劃分對象職責(zé)與對象協(xié)作順序

想必這是本篇、也是本系列最重要的一節(jié):在后續(xù)代碼實(shí)現(xiàn)過程中將不斷回顧此節(jié)內(nèi)容,甚至發(fā)現(xiàn)此節(jié)可進(jìn)一步優(yōu)化之處,并更新之。

此節(jié)以UML2.0作為表示法,使用Rational Rose工具,從類圖、順序圖角度描述了關(guān)鍵業(yè)務(wù)類之間的關(guān)系,以及這些類在游戲主流程中是如何分發(fā)消息、互相協(xié)作完成任務(wù)的。

(1)首先看類圖

 

Class Diagram

不算復(fù)雜吧,其中還省略了部分關(guān)聯(lián)關(guān)系(如Ghost可直接與SpeakManager、VoteManager關(guān)聯(lián),解決一開始的鬼內(nèi)部討論首輪發(fā)言順序的問題),只顯示主要關(guān)系,我們先從舊版中沿用的類開始說:

舊版的7個(gè)類:Table、Game、Subject、Setting、Audience、Civilian、Ghost,除了Audience外,其他都沿用寫來了。

按照游戲順序來吧:

Table:是游戲程序一啟動(dòng)就會(huì)存在的由單例模式創(chuàng)建的游戲桌類,內(nèi)部維護(hù)了一個(gè)Game類與PlayerManager類。

為什么沒有方法呢?當(dāng)然是有的,只是現(xiàn)在屬于初步設(shè)計(jì)階段,如前述提到的,這些類圖、順序圖,甚至游戲流程都可能在后續(xù)代碼實(shí)現(xiàn)中發(fā)現(xiàn)不合理之處,到時(shí)候再回頭修改(我也會(huì)回到相應(yīng)文章進(jìn)行修改,專門寫一篇此系列的日志——用于記錄關(guān)鍵的修改行為)。

PlayerManager:舊版Table類的臭味道之一就是職責(zé)過多,不但負(fù)責(zé)了通知Game類開始游戲,還負(fù)責(zé)維護(hù)桌面人數(shù)、核查是否開始,此處就將這些不必要的職責(zé)進(jìn)行了分離,新建了專門維護(hù)人數(shù)的PlayerManager類,可見其方法是對Player進(jìn)行Set、Delete與Get。關(guān)鍵屬性是維護(hù)了一個(gè)9個(gè)成員的String數(shù)組,NameArray,負(fù)責(zé)游戲開始前入座者名單的確定,以便列出順序。游戲開始并分配角色后,轉(zhuǎn)而維護(hù)9個(gè)成員的Player數(shù)組,PlayerArray。為什么用數(shù)組Array而不是舊版中的列表List——因?yàn)楸緛砭投ê昧藰?biāo)配人數(shù)(可在xml中維護(hù),此處以標(biāo)配來說),只等對應(yīng)入座,且所需內(nèi)存更少,類之間傳遞的運(yùn)算速度更快,便于存儲(chǔ)。

Setting:與舊版唯一不同的是,由Setting來負(fù)責(zé)檢查入座報(bào)名參加的人是否已經(jīng)滿了IsFull(),以此返回布爾值類型,再一路向上匯報(bào)回到Table,由Table向Game發(fā)起開始游戲Start()的通知。

Game:原來的一大堆職責(zé)都分配出去了,無事一身輕了吧~嘿嘿!的確,分配出職責(zé)之后就只剩下開始Start(),與重新開始Restart()——結(jié)束一場游戲又開啟新一場時(shí)用,當(dāng)然其實(shí)也可以由Table負(fù)責(zé)重新創(chuàng)建一個(gè)Game對象,那么Game就更輕松了~現(xiàn)在活脫脫一位嘴巴叼著煙斗的看門兒大爺,樂呵呵看著下邊兒小弟干活,自己只管發(fā)號(hào)開工、收工的指令,喔對了,連收工都不用說,底下小弟自己會(huì)判斷游戲是否結(jié)束。

Subject:與舊版唯一不同的是,由Subject來負(fù)責(zé)向詞庫獲取題目GetSubject(),并填充本身維護(hù)的三個(gè)存放詞的屬性,以后外界要詞,就都找他(舊版中做法是復(fù)制了一份給到各參與者手中,新的做法看似與現(xiàn)實(shí)不符,但實(shí)際上是優(yōu)化現(xiàn)實(shí)中可能存在手動(dòng)改題作弊的信息化流程的優(yōu)勢),所以需要建立全局訪問點(diǎn),故還是考慮單例模式創(chuàng)建。

Player、Civilian、Idiot、Ghost:后三者繼承Player,眼疾手快的應(yīng)該看出來了——PlayerManager維護(hù)的Player數(shù)組是對抽象類Player,此后若需要從中提出指定的一類對象,就可考慮用lambda表達(dá)式完成了,如:List<Ghost> ghostList = PlayerManager.Player.ToList().Where(g=>g.Type().Equals(Ghost)); ——直接打的沒在vs運(yùn)行過,有bug請多包涵哈[憨笑]!在舊版當(dāng)中,Ghost繼承自Civilian,Civilian繼承自Audience,此處不考慮旁觀者類(在代碼實(shí)現(xiàn)部分在考慮補(bǔ)充,也許還會(huì)增加回來這個(gè)Audience類,就看增在哪了),且Ghost實(shí)際上不是一個(gè)Civilian,所以不應(yīng)使用繼承關(guān)系表示,所有他們相似的方法,應(yīng)該提升到Player抽象類來完成,如設(shè)計(jì)模式中提及的:非is-a關(guān)系的,不應(yīng)該用繼承關(guān)系表示。那么如何區(qū)分Civilian平民、Idiot白癡、Ghost鬼呢——別忘了裝飾模式能夠動(dòng)態(tài)給所包裝的對象額外添加職責(zé)或標(biāo)簽喔~(回顧本篇第一節(jié)復(fù)習(xí)設(shè)計(jì)模式后,列出的可能用得上的設(shè)計(jì)模式部分)

好了,剩下沒講到的類,都是從舊版Game中分離出來的職責(zé):

RoleManager負(fù)責(zé)分配角色、SpeakManager負(fù)責(zé)管理對話列表、LoopManager負(fù)責(zé)檢查此輪發(fā)言(包括PK時(shí)的發(fā)言)是否結(jié)束、VoteManager負(fù)責(zé)管理投票環(huán)節(jié)、DeathManager負(fù)責(zé)充當(dāng)劊子手,WinManager負(fù)責(zé)檢查鬼是否勝利(鬼沒勝利就繼續(xù),直到鬼全死或者鬼勝利,所以無需以好人們勝利作為結(jié)束游戲的標(biāo)準(zhǔn))。

好了,如此一來各個(gè)類都比較專一的負(fù)責(zé)自己要做的事情了——單一職責(zé)原則——如果現(xiàn)實(shí)生活中真有這樣單一職責(zé)的工作該多好,而偏偏社會(huì)需要的是全才,就好比學(xué)計(jì)算機(jī)的也會(huì)被領(lǐng)導(dǎo)叫去搬主機(jī)箱一樣(比喻,比喻~),關(guān)于工作的話題小生我也就4年工作經(jīng)驗(yàn),不敢在各位老江湖面前班門弄斧、講些閱歷少見識(shí)短的大道理,還是趁年輕、趁著夢想沒被現(xiàn)實(shí)叫醒,趕緊做能承受的起的事情吧~

(2)進(jìn)入與游戲開始順序圖

Enter Diagram

順序圖是個(gè)啥東西,此處相信不認(rèn)識(shí)的朋友們也能聽懂一二。

1-4. 每當(dāng)有人入座,Table就會(huì)將此人昵稱丟給PlayerManager,由PlayerManager問Setting“人齊了沒?”(IsFull())。有人起立的時(shí)也一樣告訴PlayerManager要?jiǎng)h掉人名,此時(shí)PlayerManager維護(hù)的是String數(shù)組。若Setting告訴PlayerManager“人齊啦!”,消息會(huì)傳回Table的耳朵里,Table拔出一根猴毛那么一吹啊(作為繪畫愛好者,一定要向燃起的國產(chǎn)動(dòng)畫《大圣歸來》致敬!),就蹦出個(gè)Game類,游戲就此開始。

5-6. Game先向Subject要題,再叫來RoleManager隨機(jī)給PlayerManager維護(hù)的String數(shù)組分配角色,并將角色依次披上Player抽象類外衣,再列隊(duì)回到PlayerManager中。是不是感覺RoleManager有點(diǎn)像建造者模式中的指揮者——大老遠(yuǎn)敢來只帶一身才華(類的方法),匆忙按要求完成任務(wù)后也不帶走一片云彩。哈哈,是有這么個(gè)意思,具體能否結(jié)合建造者模式、是否有必要結(jié)合建造者模式,我們在代碼實(shí)現(xiàn)部分與大家共同探討。

7-8. 題目和身份角色都準(zhǔn)備好了,就由系統(tǒng)說話,向Player參賽者們說明他們各自的身份與題目,并說明現(xiàn)在進(jìn)入鬼指定首輪發(fā)言人的時(shí)候。SpeakManager當(dāng)之無愧作為此任務(wù)的完成者,顯示記錄下系統(tǒng)說了什么SystemSpeak(),再將記錄發(fā)布到前臺(tái)ShowRecord()。

(3)鬼討論順序圖

Ghost Speak Diagram

非常簡單,找SpeakManager就夠了~

(4)鬼投票(決定首輪發(fā)言人)順序圖

Ghost Vote Diagram

1-3. 在鬼投票決定首輪發(fā)言人的時(shí)候,前臺(tái)界面會(huì)出現(xiàn)所有人名字的按鈕(PlayerManager維護(hù)的String人名數(shù)組又派上用場了吧),每當(dāng)有一個(gè)鬼點(diǎn)選投票的時(shí)候,Ghost對象將票遞給檢票官VoteManager,由檢票官查看大家都投完了嗎IsVoteEnd(),投完了咱就唱票Roll()。

4-5. 屬于備選事件流(來自RUP的提法,事件流分為主事件流與備選事件流),在鬼投票結(jié)果不一致(有人按錯(cuò),或意見不統(tǒng)一)時(shí)發(fā)生,此時(shí)檢票官VoteManager會(huì)讓SpeakManager幫忙發(fā)布圣旨SystemSpeak(),告訴前臺(tái)ShowRecord(),讓鬼們趕緊統(tǒng)一意見并再次投票。

6-7. 當(dāng)鬼的投票一致時(shí),檢票官可算松了口氣,趕緊把接力棒交給LoopManager,讓其記錄本輪開始,并讓SpeakManager來設(shè)定允許發(fā)言的鬼投出來的首輪發(fā)言人。什么叫“允許發(fā)言的”——如果非SpeakManager官方允許SetSpeaker()的玩家,無論他們說什么都不予記錄在案,當(dāng)然也就不會(huì)ShowRecord()給別人看,也就是“不許場外”,這個(gè)“允許誰說話”的職責(zé),肯定要落到SpeakManager的身上。

(5)所有角色玩家發(fā)言順序圖

Player Speak Diagram

與鬼發(fā)言不同的是,玩家發(fā)言要按順序,且每人發(fā)言后LoopManager都會(huì)不厭其煩的看一眼本輪是否結(jié)束。具體過程我就不贅述了。

(6)所有角色玩家投票順序圖

Player Vote Diagram

1-5. 正常投票,不贅述。

6-7. 屬于備選事件流,用于投票結(jié)果出現(xiàn)相同票數(shù)時(shí)的PK發(fā)言環(huán)節(jié)。顯示投票官將同票者們交給LoopManager,讓其決定誰先說SetLoopStarter(),別忘了要告訴SpeakManager允許記錄他的話SetSpeaker(),說完后就會(huì)回到1-5步驟,繼續(xù)投票。當(dāng)然,如系列中的游戲流程介紹篇所言,PK臺(tái)上的人是不能進(jìn)行他們自己的投票的,這一點(diǎn)在順序圖中不體現(xiàn),在實(shí)際代碼中可以通過Player的是否有投票權(quán)屬性來標(biāo)識(shí)(暫時(shí)性剝奪投票權(quán)利法治制度的趕腳哈哈)。

8-9. 無論如何,每輪結(jié)束肯定得有人被檢票官VoteManager交給死神DeathManager,并由死神執(zhí)行死刑SetPlayerDie()——舊版中是玩家自殺(SetDie的方法在玩家對象中),新版是劊子手處決,感覺更合理了吧~每次有人升天,WinManager大仙都會(huì)探出頭看看凡間這桌的這個(gè)游戲(Table.Game)是否結(jié)束,結(jié)束的標(biāo)準(zhǔn)是鬼是否勝利IsGhostWin()。

10-11. 如果游戲還沒結(jié)束,那么游戲的指揮棒再次回到VoteManager手中(畢竟整個(gè)都是投票環(huán)節(jié)產(chǎn)生的一系列互動(dòng),讓其他任何Manager接棒都不合適),檢票官會(huì)通知LoopManager開始新的一輪玩家發(fā)言,當(dāng)然別忘了經(jīng)過SpeakManager允許的SetSpeaker(),才能言論自由喔~

 

四、總結(jié)此篇步驟

本篇末尾特此增加一節(jié),來講述上述那一堆(我自認(rèn)為還算是比較)清晰的類職責(zé)劃分與流程,是如何在舊版思維潛移默化根植的情況下建立出來的。先上圖:

為了讓大家看清筆記,我就不縮略了。

這是我設(shè)計(jì)時(shí)考慮的第一張圖,可以看到左上角,當(dāng)時(shí)還是沿用的三層繼承的方式處理各個(gè)角色,因?yàn)橐粫r(shí)沒想通,就不希望在此環(huán)節(jié)卡殼,就繼續(xù)了對Table和Game的職責(zé)進(jìn)行分離。看左下角,最初的PlayerManager還只是一個(gè)孩子(PlayerList,一個(gè)屬性而已),針對的是繼承于Audience的Player抽象類(但仍然沒解決三層繼承的問題,且Audience思維根深蒂固)。在看到圖中間Game分出來的職責(zé),重新招聘新員工后,將這些職責(zé)分配了他們,他們最初的名字還是Roler、Speaker、LoopChecker、Voter、WinChecker、Death、StartChecker(最后通過職責(zé)分析,更應(yīng)該被分到Setting中,才有了如今花名IsFull()的方法,從此遠(yuǎn)離塵世,隱退江湖&hellip;…)。各個(gè)類之間的大體順序可在圖中右側(cè)1-13的序號(hào)查看,眼尖的朋友可能看出了判斷Y/N邏輯,哈哈~

這第二幅,是為了專門解決各角色間的關(guān)系問題所畫的。可以看到,這時(shí)候已經(jīng)誕生了PlayerManager類,并和Game類平起平坐被Table大哥掌管。圖中凌亂不堪的筆記是雨落邕城的日子里思緒糾纏的痕跡,細(xì)心的讀者也許看到了枚舉Role:Enum,是的,當(dāng)時(shí)我是想Player類繼承自Audience類,這樣就化三層繼承為兩層繼承,所有角色以枚舉類型的Role屬性來區(qū)分,但此時(shí)因考慮到開放封閉原則(為擴(kuò)展開放,為修改封閉),不適用于枚舉的增加——如:如果有一天游戲升級,規(guī)則中加入了華佗角色,可以起死復(fù)生(有點(diǎn)像殺人游戲的升級版),難道還要進(jìn)入枚舉中進(jìn)行修改嗎?為何不通過增加一個(gè)新類的方式來解決呢,因此就有了圖中Person類的框框,其他角色繼承自Person——沒錯(cuò),那這么一來不就又回到舊版本的三層繼承?不,雖然多層繼承問題還沒解決,但至少解決了一個(gè)重要問題:非is-a關(guān)系不能用繼承——Civilian與Ghost不再是繼承關(guān)系了!這點(diǎn)太重要了。請大家記住,如果只是為了方法調(diào)用方便,完全可以通過模板模式解決,再不行代理、外觀模式也成啊,反正繼承關(guān)系真是不到“是一個(gè)”(is-a)關(guān)系的時(shí)候,就不要考慮,否則可能出現(xiàn)龐大的繼承樹問題,或者像舊版一樣陷入父子類頻繁轉(zhuǎn)換漩渦當(dāng)中,也不利于對繼承樹中的某個(gè)環(huán)節(jié)進(jìn)行額外增加職責(zé)或標(biāo)簽(方法或?qū)傩裕?/p>

觀察力強(qiáng)的朋友們也許注意到了右上角圍著桌子做的玩家座位圖。沒錯(cuò),當(dāng)時(shí)是覺得前臺(tái)界面不但要略微優(yōu)化,還要解決Audience類的問題,就萌生了類似德州撲克那樣“圓桌會(huì)議+坐下按鈕”的方式,以此代替原來報(bào)名/旁觀的按鈕。拜德州撲克所賜,忽然間覺得Audience這類人真的對游戲貢獻(xiàn)很不大。好像你去澳門賭場,你也許只關(guān)心同桌競技的對手是何人是何心理,而一點(diǎn)不關(guān)心圍桌站起的旁觀者(不要腦補(bǔ)賭神的作弊旁觀者啊~),甚至連旁觀者的名字都不想知道,頂多知道圍著大概多少人就行了(通過cookie統(tǒng)計(jì)數(shù)字即可,且不需要即時(shí)更新,定較長的時(shí)間更新都不影響,還可節(jié)省流量)。

因此我認(rèn)為界面應(yīng)該重新稍微布局一下,順便理順第一張草稿圖中的主要順序,因此有了第三張圖:

哈哈,第一眼都看圖去了吧,好像除了列出圓桌也沒啥區(qū)別,好吧……我承認(rèn)的確是的。

圖中右側(cè)形如大括號(hào)、箭頭的,就是順序圖中的信息流箭頭。是不是發(fā)現(xiàn)很粗糙,甚至整個(gè)流程(順序圖)那么多,怎么幾行就搞定了:畫到第三張圖時(shí),我覺得混沌的思路已經(jīng)打開,職責(zé)劃分、流程優(yōu)化、對象關(guān)系等主要問題已經(jīng)基本迎刃而解,只剩下規(guī)規(guī)整整的列出一份能見世面的圖紙罷了——即,草圖整理思路的環(huán)節(jié)已告破,可進(jìn)入?yún)R總思路、整理文檔的環(huán)節(jié),進(jìn)而我就轉(zhuǎn)入了上述第三節(jié)類圖、順序圖的繪制過程。

如果你一定要問上述三張圖都是什么表示法,那我只能拍腦袋隨便起個(gè)毫無意義的名兒了——不要局限于手中的繪圖工具(rational rose或visio或vs的modeling項(xiàng)目),一開始是無法對著如此工整的電腦軟件將大腦中思維跳躍、混亂待整的腦電波表現(xiàn)出來的,個(gè)人建議還是在草稿紙上進(jìn)行,框框線線、粗糙標(biāo)記,以最快速度記下所想所悟,別忘了,軟件再高級也是為人類服務(wù)的,相信自己的大腦與握筆的手吧!

如果一定要說順序,那請參照RUP(統(tǒng)一軟件開發(fā)過程),多了解OOAD(面向?qū)ο蠓治雠c設(shè)計(jì)),結(jié)合SOLID原則(單一職責(zé)、開放封閉、里氏替換、接口隔離、依賴倒轉(zhuǎn))在整個(gè)設(shè)計(jì)、代碼編寫過程不斷迭代審視,最終做到perfect——不禁想起我的一位高齡素描老師,趙晉,趙老師熱愛畫油畫,有一副描繪了大榕樹下的農(nóng)民生活的油畫他花了很多年,今天釣魚回來添幾筆,明年大年初一高興又添幾筆,如此反復(fù)……

Coder們加油,我們要做的事情還有很多,即便不在技術(shù)的道路上走,也能交交朋友,從代碼中看到態(tài)度、領(lǐng)悟世事,不要枉費(fèi)曾在IT之路走了這一遭

PS:也許會(huì)有讀者疑問,怎么設(shè)計(jì)的結(jié)果沒體現(xiàn)具體設(shè)計(jì)模式?因筆者考慮到,設(shè)計(jì)模式不能離開代碼,且設(shè)計(jì)模式是思路、是建議,而非終極目標(biāo),能在設(shè)計(jì)環(huán)節(jié)考慮到、思考到,待到代碼實(shí)現(xiàn)環(huán)節(jié)再寫出其內(nèi)涵與精髓,甚至模式變形,也比陷入設(shè)計(jì)過度要好。


發(fā)表評論 共有條評論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 吐鲁番市| 乳源| 广州市| 康平县| 遂宁市| 兴山县| 丹巴县| 开江县| 汪清县| 会同县| 北辰区| 白玉县| 石泉县| 措美县| 潞西市| 读书| 石景山区| 泉州市| 闽清县| 清水河县| 广水市| 抚顺市| 忻城县| 古交市| 湘潭市| 宁夏| 塔河县| 会理县| 福建省| 禹城市| 无极县| 承德市| 嵊州市| 罗源县| 河北省| 义马市| 玉龙| 大余县| 鄯善县| 新郑市| 舞钢市|