




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
1、luoyang normal university 2013屆本科畢業(yè)設計基于android的飛機大戰(zhàn)游戲設計與開發(fā)院(系)名稱信息技術學院專 業(yè) 名 稱 軟件工程 學生姓名學號指導教師xxx副教授完 成 時 間2013年5月摘要相信android(安卓)已經為人們熟知,經過2011年的洗禮,android智能手機火速上位,甚至說現在手機系統(tǒng)由ios和android平分也不為過。隨著android智能手機在中國內地的風靡,基于android平臺的應用開發(fā)也逐漸成為it開發(fā)的一大熱門。游戲是智能機不可或缺的應用之一,“水果忍者”、“憤怒的小鳥”等android游戲應用的成功,讓人看到手機游戲在a
2、ndroid平臺上的巨大發(fā)展空間?;诖耍捎胑clipse和android adt作為集成開發(fā)平臺,開發(fā)本android游戲app。本應用為android飛機大戰(zhàn)游戲,主要有6個操作界面分別為開始界面,游戲界面,設置界面,得分界面,win界面,lose界面。玩家可以選擇自己進入設置界面對游戲進行設置,或進入的分界面查看自己本次操作是否在前六名等操作。作為游戲背景音樂的存在是不可或缺的,本應用在不同的操作界面演奏不同的背景音樂,玩家還可以在設置界面設置背景音樂的大小。由于android控件activity的生命周期的特點,本應用會在被點擊“exit”按鈕的activity中發(fā)送一個exit的廣
3、播,所有的本應用的activity收到廣播后會自動結束,使得本應用能夠完全的退出系統(tǒng)。本應用采用android的surfaceview繪制游戲界面,游戲的主界面美觀,賞心悅目,以提高玩家對游戲的興趣。游戲的控制模塊應該做到易懂、易操作,以給玩家一個很好的游戲環(huán)境。關鍵詞:android開發(fā);手機游戲;java;sqliteabstractandroid has been known for people, after 2011 years of baptism, android smartphone developing fast . android occupies a large shar
4、e in the market . android game application is successful, it make a person see that mobile games on the android platform of the huge development space. based on this,we using eclipse and android adt as integrated development platform, to develop the android game application.this application for andr
5、oid plane war games include six operating interface, respectively as the start screen, the game interface and set interface, win interface, lose interface. players can choose interface to play the game. as the mobile phone game background music is indispensable, the application play different backgr
6、ound music in different interface, players can also set the size of the background music in setting interface.this application using the android surfaceview to draw game interface, game interface pleasing to the eye by people to play. i n order to give players a good game environment , the control m
7、odule of game should be simple, easy to operate.keywords : android programing; mobile phone games ; java programing ;sqlite目 錄第1章 緒論11.1 系統(tǒng)開發(fā)背景11.2 系統(tǒng)研究目的和意義11.3 可行性分析1第2章 系統(tǒng)需求分析22.1 用戶功能需求分析22.2 系統(tǒng)性能要求32.3 業(yè)務流程分析3第3章 系統(tǒng)總體設計43.1 系統(tǒng)功能模塊分析43.1.1系統(tǒng)管理43.1.2 app應用設置43.1.3 玩家信息管理43.2 系統(tǒng)類關系圖43.3 系統(tǒng)總體設計6第4章
8、 系統(tǒng)詳細設計84.1 開發(fā)工具簡介84.2 數據庫設計84.2.1 dao(數據庫訪問對象)94.2.2 sqlite數據庫124.3 游戲界面設計124.3.1開始界面124.3.2游戲界面194.3.3設置界面264.3.4 得分界面344.3.5 win界面414.3.6 lose界面46第5章 軟件測試和調試515.1 白盒測試法515.2 黑盒測試法52第6章 工作總結和展望53參考文獻54致 謝55第1章 緒論1.1 系統(tǒng)開發(fā)背景 隨著科技的發(fā)展,現在手機的功能已不僅僅是簡單的接打電話、收發(fā)短信了。更多的手機用戶希望在工作、學習之余通過方便靈巧可隨身攜帶的儀器休閑娛樂。因此,為了
9、迎合眾多用戶的需求并適應現在手機的規(guī)模,我們開發(fā)出一套適合各階層人士的具有很強的娛樂性和交互性的飛機小游戲。雖然現在市面上存在著各種各樣的游戲版本,可是飛機游戲其市場還是相當大的。因為它的特殊在于人們在玩游戲的時候的過程中使愛不釋手。隨著游戲關卡不斷提高,其難度也更大,刺激性也更強??梢哉f該游戲的優(yōu)勢在于它的簡單易行,不論是手機,還是小游戲機,都能很快順利的運行。對于在外忙碌的人,不可能花費大量時間在娛樂上,大型游戲是行不通的。這樣的小游戲剛好迎合了他們的需求。1.2 系統(tǒng)研究目的和意義在如今社會,人們的工作學習壓力逐漸增大,生活節(jié)奏逐漸加快,大多數人沒有足夠的時間去休閑娛樂,放松自己。這款小
10、型的手機游戲,可以讓我們隨時隨地都能享受游戲,從繁重的日常生活中解脫出來。游戲的主界面應該力求美觀,賞心悅目,以提高玩家對游戲的興趣。游戲的控制模塊應該做到易懂、易操作,以給玩家一個很好的游戲環(huán)境。1.3 可行性分析該系統(tǒng)采用eclipse集成android adt為開發(fā)平臺進行app開發(fā)。eclipse是一個開放的源代碼的、基于java的可擴展開發(fā)平臺。就其本身而言,它只是一個框架和一組服務,用于通過插件組件構建開發(fā)環(huán)境。雖然大都數用戶很樂于eclipse當作java集成開發(fā)環(huán)境(ide)來使用,但eclipse的目標卻不僅限于此。eclipse還包括插件開發(fā)環(huán)境,這個組件主要針對希望擴展e
11、clipse的軟件開發(fā)人員,因為它允許他們構建與eclipse環(huán)境無縫集成的工具。由于eclipse中的每樣東西都是插件,對于eclipse中的每樣東西都是插件,對于給eclipse提供插件,以及給用戶提供一致和統(tǒng)一的集成開發(fā)環(huán)境而言,所有工具開發(fā)人員都具有同等的發(fā)揮場所。基于eclipse的應用程序的插件開發(fā)諸如siemens公司的plm產品teamcenter的插件級開發(fā)。android專門針對eclipse開發(fā)做了adt(android developer tools)開發(fā)插件,因此該應用使用eclipse開發(fā)完全可行。第2章 系統(tǒng)需求分析2.1 用戶功能需求分析由于本程序簡單易操作,交
12、互性好,對用戶沒什么特別要求。一般用戶經過幾分鐘練系都可以熟悉本游戲的規(guī)則。 圖2-1 功能界面示例圖 圖2-2 游戲界面示例圖2.2 系統(tǒng)性能要求1.實時性本應用為手機游戲因此對于用戶的操作必須做出立即響應,否則本游戲即為失敗。2.易操作性單機手機游戲的最大特點即為易操作性,用戶在不看說明的情況下也能夠玩,并且在玩過幾遍之后即熟悉本游戲的規(guī)則。這是本應用對于操作性的要求。2.3 業(yè)務流程分析依據系統(tǒng)的需求分析,得到系統(tǒng)的流程圖如圖2-3所示:圖2-3 系統(tǒng)流程圖第3章 系統(tǒng)總體設計3.1 系統(tǒng)功能模塊分析當前應用使用的surfaceview來繪制的頁面因此相對來說大部分邏輯都是由activi
13、ty來做處理的。本系統(tǒng)的功能模塊也根據activity的不同來劃分成6個功能模塊。3.1.1系統(tǒng)管理 各個操作界面布局適當,顏色搭配等要美觀。各個activity之間的切換要快速(ps:它們各自的背景音樂也要隨之切換,給用戶以順暢、自然的感覺)。用戶在任何一個activity點擊“exit”按鈕或contextmenu中的“退出”都要成功的將當前應用掛起的多個acitivity和當前android虛擬機顯示的activity順利的停止,并銷毀。3.1.2 app應用設置設置應用系統(tǒng)背景音樂聲音大小和游戲難度。使用seekbar來控制系統(tǒng)音量,使用radiogroup來控制飛機難度。3.1.3
14、玩家信息管理在游戲結束時對于玩家的名稱和得分進行記錄,并在玩家查看排名情況時,以倒序形式顯示前六名玩家的得分和姓名等信息。3.2 系統(tǒng)類關系圖系統(tǒng)實體類、邊界類、控制類之間的關系如圖3-1所示:圖3-1 實體類、控制類、邊界類之間的關系各個界面類之間的關系如圖3-2所示:圖3-2 app邊界類關系3.3 系統(tǒng)總體設計系統(tǒng)的中只有玩家一種用戶,不必向其他的網站或者是教務系統(tǒng)一樣進行身份驗證等操作。玩家點擊應用圖標直接進入應用的開始界面。用戶的操作總體可以歸并成如3-3玩家用例圖所顯示的內容,子彈的用例圖如圖3-4所示,飛機的用例圖如圖3-5所示。用戶的操作基本可以劃分為“開始游戲”,“設置游戲”
15、,“玩游戲”,“查看分數”,“退出游戲”這五個用例。圖3-3 玩家用例圖圖3-4 子彈用例圖圖3-5 飛機用例圖第4章 系統(tǒng)詳細設計4.1 開發(fā)工具簡介android開發(fā)工具(adt)是一個插件的eclipse ide,目的是給開發(fā)人員提供一個強大的、集成的環(huán)境中構建android應用程序。擴展能力的eclipse adt讓你迅速建立新的android項目,創(chuàng)建一個應用程序的用戶界面,添加基于安卓框架的api,調試您的應用程序使用android sdk工具,生成apk文件在使用eclipse運行android應用的時候eclipse會自動的將生成的apk文件自動的注冊到android虛擬機中。
16、在eclipse adt發(fā)展與高度推薦,是一種最快的方式開始。與引導項目設置它提供,以及工具集成、定制xml編輯器和調試輸出窗格,adt給了你極大的提高在發(fā)展中android應用程序。使用eclipse集成android adt做android應用開發(fā)是目前企業(yè)中常用的android應用開發(fā)方式。本項目在開發(fā)環(huán)境:l jdk 1.7 l eclipse 3.7.0l android adt4.03 4.2 數據庫設計本應用使用的是android虛擬機做開發(fā),因此使用的為android虛擬機中自帶的數據庫sqlite。本應用只是在針對用戶得分及用戶姓名等基本信息進行存儲,因此數據庫非常簡單,僅僅
17、是設計了一個用來存儲用戶排名信息的表結構。用來存儲用戶基本信息的compositor_table的字段信息如圖4-1所示。create table compositor_table (id integer primary key,name varchar(40) not null,score integer not null)圖4-1 compositor表android中自帶的sqliteopenhelper 作用:一個幫助類,幫助創(chuàng)建數據庫和數據庫版本管理。本應用直接創(chuàng)建一個skygamedatabasehelper類繼承android自帶的數據庫操作類sqliteopenhelper。在
18、oncreate()方法中創(chuàng)建表compositor_table。public void oncreate(sqlitedatabase db) / todo auto-generated method stubstring create_table = this.context.getresources().getstring(r.string.create_compos_table);/ create table compositor_table (id integer primary key,name varchar(40) not null,score integer not null
19、);db.execsql(create_table);4.2.1 dao(數據庫訪問對象)本應用中的數據庫訪問對象skygamedatabasedao采用了單例模式,以保證當前應用中只存在一個dao數據庫訪問對象。使用了最簡單的單例,并未從線程安全的角度進行進一步的限制,原因在于考慮到當前應用中只有3個activity使用了dao,由圖4-2可知activity之間的切換類似于進程對于cpu的占用一樣,當前顯示在界面上的activity是活動狀態(tài)而其他activity則是掛起狀態(tài),因此不必擔心它們的線程同時去創(chuàng)建dao對象以引起當前系統(tǒng)中多個dao對象的狀況。public class skyg
20、amedatabasedao private static skygamedatabasedao instance = null;private sqlitedatabase database = null;private context context = null;private skygamedatabasehelper helper = null;public static skygamedatabasedao getinstance (context context)if(instance = null)instance = new skygamedatabasedao(contex
21、t);return instance;private skygamedatabasedao(context context)this.context = context;helper = new skygamedatabasehelper(context,1);while(this.database = helper.getwritabledatabase()=null);public void insertplayer(skygameplayer player)string sql = context.getresources().getstring(r.pos_tabl
22、e);contentvalues values = new contentvalues();values.put(score,player.getscore();values.put(name, player.getname();if(!this.database.isopen()this.helper.onopen(this.database);try this.database.begintransaction();this.database.insert(sql, null, values);this.database.settransactionsuccessful(); catch
23、(exception e) / todo auto-generated catch blocke.printstacktrace();finallythis.database.endtransaction();public arraylist getplayers()arraylist players = new arraylist();string sql = context.getresources().getstring(r.string.select_form_compos_table_count);cursor cursor = database.rawquery(sql, null
24、);cursor.movetofirst();if(cursor.getcount() 0)int count = 0;count+;players.add(new skygameplayer(count,cursor.getstring(1),cursor.getint(2);while(cursor.movetonext()count +;players.add(new skygameplayer(count,cursor.getstring(1),cursor.getint(2);return players;public void delete()string sql = contex
25、t.getresources().getstring(r.string.delete_from_compos_table);if(!this.database.isopen()this.helper.onopen(this.database);try this.database.begintransaction();this.database.execsql(sql);this.database.settransactionsuccessful(); catch (sqlexception e) / todo auto-generated catch blocke.printstacktrac
26、e();finallythis.database.endtransaction();public void close()if(this.database.isopen()this.database.close();圖4-2android中activity生命周期狀態(tài)圖4.2.2 sqlite數據庫sqlite,是一款輕量級的關系型數據庫。由于它占用的資源非常少,所以在很多嵌入式設備都是用sqlite來存儲數據。android作為目前主流的移動操作系統(tǒng),完全符合sqlite占用資源少的優(yōu)勢,故在android平臺上,集成了一個嵌入式關系型數據庫sqlite。由于sqlite是輕量級的關系型數據
27、庫,它支持的sql語句也是有限的,在使用sql語句獲得前6名玩家的信息時直接使用了sqlite不支持的top語句引起了異常。在查閱相關資料后才發(fā)現sqlite不支持top語句,因此使用語句desc limit來代替top達到了自己想要的只獲得表compositor_table中的score字段值最大的前六個記錄信息。select * from compositor_table order by score desc limit 64.3 游戲界面設計4.3.1開始界面使用surfaceview將圖4-3中的未被按下的按鈕和圖4-5游戲開始界面背景圖片繪制成游戲開始界面圖4-6。圖4-3 未被按
28、下的按鈕圖標集圖4-4 被按下的按鈕圖標集圖4-5 開始界面背景圖片圖4-6 開始界面 androidmanifest.xmlandroid應用程序中,并沒有像c+和java這樣有main函數來作為應用程序的入口。android應用程序提供的是入口activity,而非入口函數。androidmanifest.xml文件中定義了整個android應用所包含的activity.在androidmanifest.xml中將skygamestartactivity設置為當前skygame啟動時,默認加載的activity,代碼如下: activity中注冊layout在
29、skygamestartactivity的oncreate方法中設置要顯示的layout,方法如下所示:protected void oncreate(bundle savedinstancestate) / todo auto-generated method stubsuper.oncreate(savedinstancestate);setcontentview(r.layout.sky_game_start_layout);/設置當前activity調用的layout/其他操作 broadcastreceiver由于本應用是有多個activity為了解決多個activit
30、y在其中任意一個activity結束時都會相應一起退出系統(tǒng),因此針對每一個activity設置一個broadcastreceiver來接收廣播,一旦接收到廣播當前activity自動退出。activity接收到廣播后退出的代碼如下所示:private broadcastreceiver exitreceiver = new broadcastreceiver()overridepublic void onreceive(context context, intent intent) / todo auto-generated method stubskygamescreenrollactivi
31、ty.this.finish(); 發(fā)送廣播而當前activity在被按下“exit”或者“退出”按鈕時,會向外界發(fā)送一個廣播,之后結束自己:activity activity = (activity)context;intent intent = new intent(exit);intent.setaction(exit);activity.sendbroadcast(intent);activity.finish(); mediaplayer(媒體播放器)本應用使用android的mediaplayer來演奏每一個頁面的背景音樂。背景音樂可以存放在兩個位置,一
32、個是當前工程的/res/raw目錄下,如果是存放在該目錄下的話,在install當前android工程時,需要耗費非常的時間將此類音頻文件上傳到android虛擬機中。另一個存放位置是直接將音頻文件上傳到ddms的/mnt/sdcard/music文件夾下,這相當于將該音頻文件放入到了android手機的sd卡上了,相對于存放位置一來說,該方法在加載android工程時消耗的時間比較少。具體向虛擬機中上傳文件如圖4-7所示:圖4-7 ddms向android虛擬機中上傳文件mediaplayer使用方法:private mediaplayer startsound = null;startso
33、und = new mediaplayer();try /* * 從sdcard中獲得音頻文件的路徑 */startsound.setdatasource(/mnt/sdcard/music/start.mp3);startsound.prepare(); catch (illegalargumentexception e) / todo auto-generated catch blocke.printstacktrace(); catch (securityexception e) / todo auto-generated catch blocke.printstacktrace();
34、catch (illegalstateexception e) / todo auto-generated catch blocke.printstacktrace(); catch (ioexception e) / todo auto-generated catch blocke.printstacktrace();startsound.setlooping(true) ;/設置循環(huán)由于當前應用針對不同的顯示界面(activity)有不同的背景音樂,因此當前activity掛起時,對應的背景音樂也要掛起(startsound.pause())。而在當前activity銷毀(destory)
35、時,需要對背景音樂進行停止(startsound.stop())和回收(startsound.release())操作。 layout中調用surfaceview普通的layout設置與直接調用surfaceview的layout有所不同,一下列出調用surfaceview的layout的格式: 此處使用自定義surfaceview的絕對路徑來編寫開始頁面的layout文件,使得開始頁面直接使用該surfaceview繪制的bitmap作為背景圖片來顯示。surfaceview所需要設置下它的surfaceholder 和monitor(實現callback接口)屬性holder
36、 = getholder();monitor = new monitor();holder.addcallback(monitor);monitor類的方法:方法surfacecreated(surfaceholder holder)的主要作用是:在surfaceview創(chuàng)建的繪制surfaceview的內容。方法surfacedestroyed(surfaceholder holder)的主要作用是:在surfaceview銷毀時對于當前surfaceview中的一些對象做銷毀處理。surfaceview的方法:ontouchevent(motionevent event)可以捕獲鼠標對于屏
37、幕的觸碰事件,在該方法中對于鼠標觸碰的區(qū)域做出判斷如果點擊的為按鈕圖片的位置則會調用圖4-4中對應的被按下按鈕來顯示,如此顯示使用戶有一個可感受的按鈕被按下的動態(tài)即視感,用戶體驗更好。public boolean ontouchevent(motionevent event) / todo auto-generated method stubint action = event.getaction();float eventx = event.getx();float eventy = event.gety();if(eventx = start_x)&(eventx = start_y)&(
38、eventy = option_x)&(eventx = option_y)&(eventy = score_x)&(eventx = score_y)&(eventy = exit_x)&(eventx = exit_y)&(eventy = exit_y + exitbutton.getheight()if(action = motionevent.action_down)scorebutton = bitmapfactory.decoderesource(getresources(), r.drawable.exit_button_2);drawexitbutton();if(actio
39、n = motionevent.action_up)scorebutton = bitmapfactory.decoderesource(getresources(), r.drawable.exit_button_1);drawexitbutton();activity activity = (activity)context;intent intent = new intent(exit);intent.setaction(exit);activity.sendbroadcast(intent);activity.finish();return true;4.3.2游戲界面本界面與開始界面
40、都是使用surfaceview繪制的界面,由于本界面相對于開始界面更加復雜在主線程外創(chuàng)建了子線程來負責對于surfaceview的繪制工作,主線程負責對于各類對象的控制計算等計算工作。由于游戲界面涉及到的類比較多,且邏輯復雜,所以在這里只介紹下使用的空間、技術以及業(yè)務邏輯,粘貼部分技術代碼。繪制的游戲界面如圖4-8所示:圖4-8游戲界面 activity中注冊surfaceview游戲界面并沒有像開始界面那樣注冊surfaceview,而是直接在oncreate方法中使用代碼注冊的自定義surfaceview,如下:private skygamescreenrollview sr
41、 = null;/自定義surfaceviewprotected void oncreate(bundle savedinstancestate) / todo auto-generated method stubsuper.oncreate(savedinstancestate);sr = new skygamescreenrollview(this);sr.setlayoutparams(new layoutparams(layoutparams.match_parent, layoutparams.match_parent);sr.setid(0x000101);setcontentvi
42、ew(sr); contextmenu控件游戲界面使用了android的contextmenu,contextmenu顯示的具體效果見圖4-9。圖4-9 contextmenu效果contextmenu針對某個控件,一旦為某個控件設置了contextmenu,那么程序員將不能再實現該控件的長按事件處理了。contextmenu的使用步驟:1. contextmenu針對的是控件而不是窗體,構建完contextmenu后需要與一個控件實施綁定。綁定的代碼為:super.registerforcontextmenu(控件對象)。2.構建contextmenu的方法如下:a.創(chuàng)建一個r
43、es/menu/*_context.xml的菜單(當前應用使用的該方法)。b.重寫oncreatecontextmenu()回調函數。c.super.registerforcontextmenu(控件對象)。3.為每個菜單項編寫事件。具體操作方法重寫oncreatemenuitemselected回調函數。游戲界面的contextmenu的playing_game_option_menu.xml內容如下: 在游戲界面的skygamescreenrollactivity的方法oncreateoptionsmenu(menu menu)中注冊playing_game_option_menu.xml
44、文件,具體方法如下所示:public boolean oncreateoptionsmenu(menu menu) / todo auto-generated method stubmenuinflater inflater = new menuinflater(this);inflater.inflate(r.menu.playing_game_option_menu, menu);return true;在游戲界面的skygamescreenrollactivity的方法onoptionsitemselected(menuitem item)中為每個菜單選項編寫響應事件,具體使用方法如下所
45、示:public boolean onoptionsitemselected(menuitem item) / todo auto-generated method stubintent intent = null;switch(item.getitemid()case r.id.pg_option_exit:intent = new intent();intent.setaction(exit);this.sendbroadcast(intent);this.finish();break;case r.id.pg_option_option:intent = new intent(skygamescreenrollactivity.this,sky
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2024年文化產業(yè)研究試題及答案解讀
- 沙漠干冰測試題及答案
- 寧波港口報關合同協議
- 專利無效宣告程序探討試題及答案
- 深度剖析育嬰師考試的法律法規(guī)知識要求試題及答案
- 廢船收購合同協議
- 文化產業(yè)管理考試潛在考題試題及答案
- 激光保護措施試題及答案解析
- 家庭住房裝修合同協議
- 安保服務補充合同協議
- 日本語句型辭典
- 社會網絡分析法-詳細講解
- 急診科護士的急救質量管理與評估
- 手術室中的緊急事件處理和救助措施
- 華為經營管理-華為經營管理華為的IPD(6版)
- 供應商年度評價內容及評分表
- 土地經濟學(黑龍江聯盟)智慧樹知到課后章節(jié)答案2023年下東北農業(yè)大學
- 實驗六.二組分金屬相圖
- 汽車發(fā)動機氣缸體氣缸蓋平面度測量教學實訓任務
- 教學課件:《數據結構》陳越
- 梁長虹解讀碘對比劑使用指南第二(呼和浩特)
評論
0/150
提交評論