• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            Merlin

            Life was like a box of chocolates. You never know what you're gonna get.

               :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
              34 隨筆 :: 0 文章 :: 40 評論 :: 0 Trackbacks
            有可能在閃躲炮彈和執(zhí)行精確攻擊的演練中學會繼承、多態(tài)性、事件處理以及內(nèi)部類這些內(nèi)容嗎?Robocode 這個游戲即將為全世界的 Java 開發(fā)者實現(xiàn)這個愿望,它把游戲風潮變成了教學工具,人們對它的上癮程度令人吃驚。請跟隨 Sing Li 一起拆解 Robocode,同時著手建造屬于自己的、定制的、小而精悍的戰(zhàn)斗機器。

            Robocode 是一個很容易使用的機器人戰(zhàn)斗仿真器,可以在所有支持 Java 2 的平臺上運行。您創(chuàng)建一個機器人,把它放到戰(zhàn)場上,然后讓它同其他開發(fā)者們創(chuàng)建的機器人對手拼死戰(zhàn)斗到底。Robocode 里有一些預先做好的機器人對手讓你入門,但一旦您不再需要它們,就可以把您自己創(chuàng)建的機器人加入到正在世界范圍內(nèi)形成的某個聯(lián)盟里去和世界最強手對陣。

            每個 Robocode 參加者都要利用 Java 語言元素創(chuàng)建他或她的機器人,這樣就使從初學者到高級黑客的廣大開發(fā)者都可以參與這一娛樂活動。初級的 Java 的開發(fā)者們可以學習一些基礎(chǔ)知識:調(diào)用 API 代碼、閱讀 Javadoc、繼承、內(nèi)部類、事件處理等等。高級開發(fā)者們可以在構(gòu)建“最優(yōu)品種”的軟件機器人全球競賽中提高他們的編程技巧。在本文中,我們將介紹 Robocode,并指導您從構(gòu)建您平生第一個 Robocode 機器人開始征服世界。我們還將看一下迷人的“后臺”機制,正是它使得 Robocode 起作用。

            下載并安裝 Robocode

            Robocode 是 Mathew Nelson 的智慧之作,他是 IBM Internet 部門 Advanced Technology 的軟件工程師。請首先訪問 IBM alphaWorks Robocode 頁面。在這個頁面上,您可以找到 Robocode 系統(tǒng)最新的可執(zhí)行文件。這個分發(fā)包是一個自包含的安裝文件,在下載該分發(fā)包之后,您就可以使用下面的命令行在您的系統(tǒng)上安裝這個軟件包(當然,我們假定您的機器上已經(jīng)預安裝了 Java VM(JDK 1.3.x)):

            java -jar robocode-setup.jar

            ?在安裝過程中,Robocode 將問您是否要使用這個外部的 Java VM 來編譯機器人。您也可以選擇使用作為 Robocode 分發(fā)包一部分而提供的 Jikes 編譯器。

            安裝完成后,您可以通過 shell 腳本(robocode.sh)、批處理文件(robocode.bat)或桌面上的圖標來啟動 Robocode 系統(tǒng)。此時,戰(zhàn)場將會出現(xiàn)。在此,您可以通過菜單調(diào)用 Robot Editor 和 compiler。





            回頁首


            Robocode 系統(tǒng)組件

            當您激活 Robocode 時,將看到兩個相關(guān)的 GUI 窗口,這兩個窗口構(gòu)成了 Robocode 的 IDE:

            • 戰(zhàn)場
            • Robot Editor

            圖 1 展示了處于工作狀態(tài)的戰(zhàn)場和 Robot Editor。


            圖 1. Robocode IDE
            Robocode IDE

            戰(zhàn)場是機器人之間進行戰(zhàn)斗直至分出勝負的場地。主要的仿真引擎被置于其中,并且允許您在這里創(chuàng)建戰(zhàn)斗、保存戰(zhàn)斗以及打開新建的或現(xiàn)有的戰(zhàn)斗。通過界面區(qū)域內(nèi)的控件,您可以暫停或繼續(xù)戰(zhàn)斗、終止戰(zhàn)斗、消滅任何機器人個體或獲取任何機器人的統(tǒng)計數(shù)據(jù)。此外,您可以在此屏幕上激活 Robot Editor。

            Robot Editor 是一個定制的文本編輯器,它可以用于編輯生成機器人的 Java 源文件。在它的菜單里集成了 Java 編譯器(用于編譯機器人代碼)以及定制的 Robot 打包器。由 Robot Editor 創(chuàng)建并成功編譯的所有機器人都會處于戰(zhàn)場上一個部署就緒的位置。

            Robocode 里的每個機器人都由一個或多個 Java 類構(gòu)成。這些類可以被壓縮成一個 JAR 包。為此,Robocode 的最新版本提供了一個可以在戰(zhàn)場 GUI 窗口中激活的“Robot Packager”。





            回頁首


            對 Robocode 機器人的詳細分析

            在寫這篇文章時,Robocode 機器人是一個圖形化的坦克。圖 2 是一個典型的 Robocode 機器人的圖解。


            圖 2. 對 Robocode 機器人的詳細分析
            Robocode 機器人

            請注意,機器人有一門可以旋轉(zhuǎn)的炮,炮上面的雷達也是可以旋轉(zhuǎn)的。機器人坦克車(Vehicle)、炮(Gun)以及雷達(Radar)都可以單獨旋轉(zhuǎn),也就是說,在任何時刻,機器人坦克車、炮以及雷達都可以轉(zhuǎn)向不同的方向。缺省情況下,這些方向是一致的,都指向坦克車運動的方向。





            回頁首


            Robot 命令

            Robocode 機器人的命令集都收錄在 Robocode API Javadoc 中。您將會發(fā)現(xiàn)這些命令都是 robocode.Robot 類的公共方法。在這一部分,我們將分類討論每個可用的命令。

            移動機器人、炮和雷達

            讓我們從移動機器人及其裝備的基本命令開始:

            • turnRight(double degree)turnLeft(double degree) 使機器人轉(zhuǎn)過一個指定的角度。
            • ahead(double distance)back(double distance) 使機器人移動指定的像素點距離;這兩個方法在機器人碰到墻或另外一個機器人時即告完成。
            • turnGunRight(double degree)turnGunLeft(double degree) 使炮可以獨立于坦克車的方向轉(zhuǎn)動。
            • turnRadarRight(double degree)turnRadarLeft(double degree) 使炮上面的雷達轉(zhuǎn)動,轉(zhuǎn)動的方向也獨立于炮的方向(以及坦克車的方向)。

            這些命令都是在執(zhí)行完畢后才把控制權(quán)交還給程序。此外,轉(zhuǎn)動坦克車的時候,除非通過調(diào)用下列方法分別指明炮(和雷達)的方向,否則炮(和雷達)的指向也將移動。

            • setAdjustGunForRobotTurn(boolean flag) :如果 flag 被設(shè)置成 true,那么坦克車轉(zhuǎn)動時,炮保持原來的方向。
            • setAdjustRadarForRobotTurn(boolean flag) :如果 flag 被設(shè)置成 true,那么坦克車(和炮)轉(zhuǎn)動時,雷達會保持原來的方向。
            • setAdjustRadarForGunTurn(boolean flag) :如果 flag 被設(shè)置成 true,那么炮轉(zhuǎn)動時,雷達會保持原來的方向。而且,它執(zhí)行的動作如同調(diào)用了 setAdjustRadarForRobotTurn(true)

            獲取關(guān)于機器人的信息

            有許多方法可以得到關(guān)于機器人的信息。下面簡單列舉了常用的方法調(diào)用:

            • getX()getY() 可以捕捉到機器人當前的坐標。
            • getHeading()getGunHeading()getRadarHeading() 可以得出坦克車、炮或雷達當前的方向,該方向是以角度表示的。
            • getBattleFieldWidth()getBattleFieldHeight() 可以得到當前這一回合的戰(zhàn)場尺寸。

            射擊命令

            一旦您掌握了移動機器人以及相關(guān)的武器裝備的方法,您就該考慮射擊和控制損害的任務(wù)了。每個機器人在開始時都有一個缺省的“能量級別”,當它的能量級別減小到零的時候,我們就認為這個機器人已經(jīng)被消滅了。射擊的時候,機器人最多可以用掉三個能量單位。提供給炮彈的能量越多,對目標機器人所造成的損害也就越大。 fire(double power)fireBullet(double power) 用來發(fā)射指定能量(火力)的炮彈。調(diào)用的 fireBullet() 版本返回 robocode.Bullet 對象的一個引用,該引用可以用于高級機器人。

            事件

            每當機器人在移動或轉(zhuǎn)動時,雷達一直處于激活狀態(tài),如果雷達檢測到有機器人在它的范圍內(nèi),就會觸發(fā)一個事件。作為機器人創(chuàng)建者,您有權(quán)選擇處理可能在戰(zhàn)斗中發(fā)生的各類事件。基本的 Robot 類中包括了所有這些事件的缺省處理程序。但是,您可以覆蓋其中任何一個“什么也不做的”缺省處理程序,然后實現(xiàn)您自己的定制行為。下面是一些較為常用的事件:

            • ScannedRobotEvent 。通過覆蓋 onScannedRobot() 方法來處理 ScannedRobotEvent ;當雷達檢測到機器人時,就調(diào)用該方法。
            • HitByBulletEvent 。通過覆蓋 onHitByBullet() 方法來處理 HitByBulletEvent ;當機器人被炮彈擊中時,就調(diào)用該方法。
            • HitRobotEvent 。通過覆蓋 onHitRobot() 方法來處理 HitRobotEvent ;當您的機器人擊中另外一個機器人時,就調(diào)用該方法。
            • HitWallEvent 。通過覆蓋 onHitWall() 方法來處理 HitWallEvent ;當您的機器人撞到墻時,就調(diào)用該方法。

            我們只需要知道這些就可以創(chuàng)建一些相當復雜的機器人了。您可以通過戰(zhàn)場的幫助菜單或 Robot Editor 的幫助菜單訪問 Javadoc 中其余的 Robocode API。

            現(xiàn)在,我們該把學到的知識付諸實踐了。





            回頁首


            創(chuàng)建機器人

            要創(chuàng)建一個新的機器人,請啟動 Robot Editor 并選擇 File-> New-> Robot。系統(tǒng)將會提示您輸入機器人的名稱,這個名稱將成為 Java 類名。請您在提示符處輸入 DWStraight。接下來,系統(tǒng)還會提示您輸入一個獨一無二的包前綴,它將用作存放機器人(還可能有相關(guān)的 Java 文件)的包的名稱。請在該提示符處輸入 dw

            Robot Editor 就會顯示您要控制這個機器人需要編寫的 Java 代碼。清單 1 是您將會看到的代碼的一個示例:


            清單 1. Robocode 生成的 Robot 代碼
            												
            														package dw;
            import robocode.*;
            
            /**
             * DWStraight - a robot by (developerWorks)
             */
            public class DWStraight extends Robot
            {
                ...  // <<Area 1>>
                /**
                 * run: DWStraight's default behavior
                 */
                public void run() {
                    ... // <<Area 2>>
                    while(true) {
                    ... // <<Area 3>>
                    }
                }
                  ... // <<Area 4>>
                public void onScannedRobot(ScannedRobotEvent e) {
                    fire(1);
                }
            }
            
            												
            										

            突出顯示的區(qū)域就是我們添加控制機器人的代碼的地方:

            Area 1
            我們可以在這片空白里聲明類作用域變量并設(shè)置這些變量的值。這些變量可以在機器人的 run() 方法內(nèi)以及其他一些您可能創(chuàng)建的助手方法內(nèi)使用。

            Area 2
            戰(zhàn)斗管理器調(diào)用 run() 方法激活機器人。典型情況下,run() 方法包括兩個區(qū)域(即在清單 1 中指出的 Area 2 和 Area 3),您可以在這兩塊空白里添加代碼。您在 Area 2 中加入的代碼每個機器人實例只運行一次。這部分代碼通常用于使機器人先處于一種預設(shè)狀態(tài)后再開始執(zhí)行重復行為。

            Area 3
            這是典型的 run() 方法實現(xiàn)的第二部分。在此,我們將在無限 while 循環(huán)內(nèi)對機器人可能執(zhí)行的重復行為進行編程。

            Area 4
            您可以在這一區(qū)域內(nèi)添加機器人在 run() 邏輯內(nèi)使用的助手方法。您也可以在此添加您想要覆蓋的任何事件處理程序。例如,清單 1 里的代碼處理 ScannedRobot 事件,每當雷達檢測到機器人的時候,只是直接向其發(fā)射炮彈。

            我們對第一個機器人(DWStraight)的代碼的更新如清單 2 中紅色標記所示。


            清單 2. DWStraight 機器人代碼的增加部分
            												
            														package dw;
            import robocode.*;
            
            public class DWStraight extends Robot
            {
                public void run() {
                    turnLeft(getHeading());
                    while(true) {
                        ahead(1000);
                        turnRight(90);
            
                    }
                }
                     public void onScannedRobot(ScannedRobotEvent e) {
                    fire(1);
                }
                public void onHitByBullet(HitByBulletEvent e) {
                    turnLeft(180);
                }
                  
            }
            
            												
            										

            下面我們逐區(qū)地描述這個第一個機器人將做些什么:

            Area 1我們沒有在這個機器人的程序中指定任何類作用域變量。

            Area 2
            為了使機器人處于已知的狀態(tài),我們通過 turnLeft(getHeading()) 使它轉(zhuǎn)到 0 度的方向。

            Area 3
            在這個重復性的部分,我們使用語句 ahead(1000) 讓機器人盡其所能向前移動到最遠的地方。當機器人撞到墻或其他機器人時,就會停下來。接著,我們通過 turnRight(90) 使它向右轉(zhuǎn)。在重復執(zhí)行這一行為時,機器人基本上是在沿著墻按順時針方向移動。

            Area 4
            在此,除處理自動生成的 ScannedRobot 事件并向被發(fā)現(xiàn)的機器人直接射擊之外,我們還會檢測 HitByBullet 事件,并且讓機器人在被擊中的時候轉(zhuǎn)過 180 度(沿順時針方向或逆時針方向)。





            回頁首


            編譯以及測試機器人

            在 Robot Editor 菜單上選擇 Compiler-> Compile編譯您的機器人代碼。現(xiàn)在我們可以嘗試第一回合的戰(zhàn)斗了。切換回戰(zhàn)場并選擇菜單上的 Battle-> New,將會出現(xiàn)一個類似于圖 3 中所示的對話框。


            圖 3. New Battle 對話框
            New Battle 對話框

            請先將我們的機器人 dw.DWStraight 添加到戰(zhàn)斗中,然后再添加一個對手機器人,比如 sample.SittingDuck。單擊 Finish,戰(zhàn)斗就開始了。不可否認,同 SittingDuck 戰(zhàn)斗并不怎么有趣,但是您可以目睹這個叫做 DWStraight 的機器人在缺省情況下的行為。試試 sample 文件夾里的其他機器人,看看 DWStraight 同這些機器人的戰(zhàn)斗情況如何。

            當您準備開始研究另外一個機器人的代碼時,請先看看隨 參考資料 中的代碼分發(fā)包一起提供的 dw.DWRotater 這個機器人的代碼。在缺省情況下,這個機器人將會:

            • 移動到戰(zhàn)場中心
            • 一直轉(zhuǎn)動它的炮,直到檢測到機器人
            • 每次嘗試以不同的角度在離被檢測到的機器人前方不遠的地方射擊
            • 每當它被另外一個機器人擊中時,它都會迅速的來回移動

            這段代碼簡單易懂,所以我們在這里就不做分析了,但是我鼓勵您試驗一下。Robocode 中的 sample 包還提供了許多其他機器人的代碼。

            附加的機器人支持類

            隨著您設(shè)計機器人的水平的提高,機器人的代碼主體將充分增長。對這些代碼的一種模塊化處理方法是把代碼分解成獨立的 Java 類,然后通過打包器把這些 Java 類打包成一個單獨的包(JAR 文件),并將它包括在您的機器人分發(fā)包內(nèi)。Robocode 將自動在它的 robots 目錄下的包里找到 robot 類。

            其他 Robot 子類

            任何人都可以創(chuàng)建 Robot 子類并添加用于構(gòu)建機器人的新功能。Robocode 提供了一個叫做 AdvancedRobotRobot 子類,它允許異步 API 調(diào)用。雖然對 AdvancedRobot 類的描述超出了本文的范圍,但我鼓勵您在掌握了基本的 Robot 類的操作后,試驗一下這個高級類。

            設(shè)計 Robocode 的目的

            我碰見了 Robocode 的創(chuàng)建者 Mathew Nelson,向他請教創(chuàng)建 Robocode 最初的設(shè)計目的。Mat 所說的是:“編寫 Robocode 的一部分目的是為了向世界證明:象‘Java 比較慢’以及‘Java 不可以用來寫游戲’之類的論斷不再正確。我認為我證明了這一點。”





            回頁首


            戰(zhàn)斗仿真器的體系結(jié)構(gòu)

            通過“在后臺”對 Robocode 進行分析,我們發(fā)現(xiàn)復雜的仿真引擎既具高性能(為了以現(xiàn)實的速度生成戰(zhàn)斗)又具靈活性(使創(chuàng)建復雜的機器人邏輯不存在障礙)。特別感謝 Robocode 的創(chuàng)建者 Mathew Nelson 無私的提供了仿真引擎體系結(jié)構(gòu)的內(nèi)部信息。

            利用 Java 平臺進行設(shè)計

            圖 4 中所示的仿真引擎利用的是大多數(shù)現(xiàn)代的 Java VM 都提供的非搶占式線程技術(shù),并結(jié)合使用了 JDK GUI 和 2D 圖形庫提供的生成功能。


            圖 4. Robocode 仿真引擎體系結(jié)構(gòu)
            仿真引擎

            請注意,所仿真的每個機器人都在它自己的 Java 線程上,它可以在任何可適用的地方利用 VM 本地線程映射機制。戰(zhàn)斗管理器線程是系統(tǒng)的控制器:它安排仿真并驅(qū)動圖形化的生成子系統(tǒng)。圖形化的生成子系統(tǒng)本身是基于 Java 2D 和 AWT 的。

            松散的線程耦合

            為了減少共享資源可能帶來的問題(以及有可能隨之出現(xiàn)的死鎖或阻塞仿真引擎),戰(zhàn)斗管理器線程和機器人線程之間的耦合應(yīng)當非常松散。為了實現(xiàn)這種松散耦合,每個機器人線程都將有屬于自己的事件隊列。獲取及處理這些事件都是在每個機器人自己的線程內(nèi)進行。這種基于線程的隊列有效地消除了戰(zhàn)斗管理器線程和機器人線程之間(或機器人線程本身之間)可能存在的任何爭用。

            Robocode 內(nèi)部結(jié)構(gòu)

            您可以把 Robocode 仿真器引擎看作是一個仿真器程序,該程序在運行時會使用一些插件(定制機器人);這些插件可以利用已有的 API( robocode.Robot 類的方法)。實際上,每個機器人都是一個獨立的 Java 線程,同時 run() 方法內(nèi)包含了每個線程上將要執(zhí)行的邏輯。

            在任何時候,機器人線程都可以調(diào)用由它的父類 robocoode.Robot 類所提供的 API。典型情況下,這將通過調(diào)用 Object.wait() 阻塞機器人線程。

            戰(zhàn)斗管理器線程

            戰(zhàn)斗管理器線程管理機器人、炮彈及它們在戰(zhàn)場上的生成。仿真“時鐘”是根據(jù)戰(zhàn)場上生成的幀的數(shù)目來標記的。用戶可以調(diào)整真實的幀的速度。

            在一個典型的回合中,戰(zhàn)斗管理器線程喚醒每個機器人線程,然后等待機器人完成它的一輪戰(zhàn)斗(即,再次調(diào)用一個阻塞 API)。等待的間隔時間通常是幾十毫秒,即使是最復雜的機器人,使用現(xiàn)今典型的系統(tǒng)速度進行策略安排和計算,也只要 1 到 2 毫秒的時間。

            以下是戰(zhàn)斗管理器線程執(zhí)行的邏輯的偽代碼:


            清單 3. 戰(zhàn)斗管理器的邏輯的偽代碼
            												
            														while (round is not over) do
               call the rendering subsystem to draw robots, bullets, explosions
               for  each robot do
                   wake up the robot
                   wait for it to make a blocking call, up to a max time interval
               end for
               clear all robot event queue
               move bullets, and generate event into robots' event queue if applicable
               move robots, and generate event into robots' event queue if applicable
               do battle housekeeping and generate event into robots' event queue
                     if applicable
               delay for frame rate if necessary
            end do
            
            												
            										

            請注意,在 for 循環(huán)內(nèi)部,戰(zhàn)斗管理器線程的等待時間不會超過最大的時間間隔。如果機器人線程沒有及時調(diào)用阻塞 API(典型情況下是由于一些應(yīng)用程序邏輯錯誤或無限循環(huán)),那么,它將繼續(xù)進行戰(zhàn)斗。生成一個 SkippedTurnEvent 并將其加入機器人事件隊列中,用來通知高級機器人。

            可替換的生成子系統(tǒng)

            AWT 和 Java 2D 線程就是當前實現(xiàn)中的生成子系統(tǒng),它從戰(zhàn)斗管理器中獲取命令并生成戰(zhàn)場。它同系統(tǒng)的其余部分是完全分離的。我們可以預見到,在這個生成子系統(tǒng)將來的修訂版中,它可以被替換掉(比如,用 3-D 生成器)。在當前的實現(xiàn)中,只要 Robocode 應(yīng)用程序被最小化,生成就禁用了,這可以以更快的速度進行仿真。





            回頁首


            Robocode 的未來

            通過 alphaWorks Robocode 站點上的一個討論組(請參閱 參考資料 ),Mathew Nelson 可以同 Robocode 用戶社區(qū)保持緊密的反饋聯(lián)系。許多反饋都并入了真實的代碼中。Mathew 已計劃即將要進行的一些改進有:

            • 通過不同的物體和障礙來定制戰(zhàn)場地圖
            • 基于團隊的戰(zhàn)斗
            • 對聯(lián)賽或聯(lián)盟的集成支持
            • 用戶可選擇坦克車體/炮/雷達/武器的樣式




            回頁首


            擋不住的 Robocode 風潮

            對于一個從 2001 年 7 月 12 日出現(xiàn)在公眾面前的項目,Robocode 的出名簡直讓人吃驚。盡管最新的可用版本還不到 1.0(在寫這篇文章時是版本 0.98.2),但它已經(jīng)是全世界的大學校園以及公司的 PC 機上頗受歡迎的娛樂活動了。Robocode 聯(lián)盟(或 roboleagues)正如雨后春筍般出現(xiàn),在這些聯(lián)盟里,人們通過因特網(wǎng)讓自己定制的作品相互較量。大學教授們一直在挖掘 Robocode 的教育特性,并且已經(jīng)把它納入了大學里的計算機科學課程。在因特網(wǎng)上,Robocode 用戶組、討論列表、FAQ、教程和 Webring 隨處可見。

            顯然,Robocode 已經(jīng)填補了大眾化的寓教于樂領(lǐng)域的空白 ― 它為學生們和熬夜的工程師們提供簡便、有趣、非脅迫卻富競爭力的方式,釋放他們的創(chuàng)造力,而且有可能實現(xiàn)他們征服世界的夢想。

            posted on 2006-07-19 20:55 Merlin 閱讀(419) 評論(0)  編輯 收藏 引用 所屬分類: java基礎(chǔ)篇
            久久久这里有精品| 亚洲Av无码国产情品久久| 久久精品国产男包| 狠狠久久综合| 久久精品国产精品亚洲人人 | 久久综合一区二区无码| 中文精品久久久久国产网址| 精品综合久久久久久97超人| 7777久久亚洲中文字幕| 久久综合亚洲欧美成人| 青草国产精品久久久久久| 伊人久久精品无码av一区| 少妇内射兰兰久久| 狠狠狠色丁香婷婷综合久久五月| 69久久夜色精品国产69| 国产精品成人99久久久久| 精品久久久久久国产牛牛app| 久久久久久国产精品美女| 国产精品久久新婚兰兰| 亚洲精品午夜国产VA久久成人| 久久天堂AV综合合色蜜桃网| 欧美精品一区二区精品久久| 精品久久综合1区2区3区激情| 久久综合九色综合欧美就去吻| 久久久久久精品免费看SSS | 久久久久无码精品国产app| 久久91精品国产91久| 久久精品亚洲中文字幕无码麻豆| 国产精品久久久久久| 欧美久久一级内射wwwwww.| 色天使久久综合网天天| 高清免费久久午夜精品| 久久综合视频网站| …久久精品99久久香蕉国产| 久久久久国产| 日韩人妻无码精品久久免费一| 亚洲国产精久久久久久久| 亚洲AV无码1区2区久久 | 久久久中文字幕日本| 久久人爽人人爽人人片AV| 久久精品国产色蜜蜜麻豆|