Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 亚洲欧洲一区二区三区在线,国产欧美日韩在线播放,91久久精品国产亚洲

          整合營銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢熱線:

          前端開發(fā)-JavaScript DOM動態(tài)生成文本框

          前端開發(fā)-JavaScript DOM動態(tài)生成文本框

          近教學(xué)過程中需要實(shí)現(xiàn)form表單中的input文本框在用戶點(diǎn)擊按鈕時(shí)自動生成新的文本框,在完成數(shù)據(jù)填寫之后通過ajax批量將填寫的信息存儲到數(shù)據(jù)庫中。每一行文本框?qū)?yīng)數(shù)據(jù)庫表中的記錄。初始狀態(tài)如下圖:

          文本框組合(行)

          如上圖,前端用戶需要借助文本框批量提交數(shù)據(jù),每一行有5個(gè)文本框,對應(yīng)后臺表中的一條記錄。用戶可填寫數(shù)據(jù),完成填寫后點(diǎn)擊添加,頁面自動添加新的一行文本框。效果如下:

          動態(tài)文本框行添加生成效果

          上圖給出了點(diǎn)擊添加之后的新效果,整個(gè)文檔HTML代碼描述如下:

          表單代碼

          代碼描述如上,文本框以label標(biāo)簽為基礎(chǔ)進(jìn)行分組,每5個(gè)為一行,所有的input文本框具有相同的class名稱。


          解決措施:

          針對待解決的問題,設(shè)計(jì)采用JavaScript DOM文檔對象模型提供的方法,將表單看成結(jié)點(diǎn),調(diào)用附加結(jié)點(diǎn)方法實(shí)現(xiàn)動態(tài)結(jié)點(diǎn)的添加。主要涉及使用到的方法函數(shù)如下:

          (1) getElementById()方法

          獲取元素(結(jié)點(diǎn))函數(shù),通過使用HTML標(biāo)記對應(yīng)的ID標(biāo)簽值獲取該元素,返回元素對象,可進(jìn)一步執(zhí)行元素的操作。

          (2) createElement()方法

          創(chuàng)建結(jié)點(diǎn)元素方法,該方法用于實(shí)現(xiàn)動態(tài)創(chuàng)建新結(jié)點(diǎn)元素,為下一步添加新結(jié)點(diǎn)奠定基礎(chǔ)。

          (3) setAttribute()方法

          該方法主要用于實(shí)現(xiàn)結(jié)點(diǎn)屬性的設(shè)置,函數(shù)需要提供兩個(gè)參數(shù),分別為屬性名稱與屬性值。

          (4) appendChild()方法

          附加結(jié)點(diǎn)方法,該方法主要用于將新創(chuàng)建結(jié)點(diǎn)附加到指定結(jié)點(diǎn)的尾部。

          (5) getElementsByClassName()方法

          該方法主要用于返回HTML文檔中具有相同Class名字的一組元素的集合,并可通過下標(biāo)訪問其中的每一個(gè)元素。

          為將前端表單文本框組合與數(shù)據(jù)表中行對應(yīng),涉及采用插入數(shù)據(jù)類insetv實(shí)現(xiàn)對每一行文本框數(shù)據(jù)進(jìn)行存儲。該類設(shè)計(jì)描述如下:

          行數(shù)據(jù)(記錄)類

          每一行使用實(shí)例化的insetv進(jìn)行數(shù)據(jù)存儲,針對多行的情況,設(shè)計(jì)采用數(shù)組對每一行進(jìn)行存儲。即數(shù)組的每一個(gè)元素都是insetv對象。最終實(shí)現(xiàn)數(shù)組按照數(shù)據(jù)行對填寫信息進(jìn)行存儲。然后自定義兩個(gè)按鈕的onclick消息響應(yīng)函數(shù),實(shí)現(xiàn)存儲數(shù)據(jù)與動態(tài)表格生成。其中addRow用于生成新的行,該函數(shù)實(shí)現(xiàn)代碼描述如下:

          添加文本框(行)函數(shù)

          定義insert方法用于獲取表單所有文本框填寫的信息,并采用數(shù)組對獲取的信息進(jìn)行存儲,數(shù)組每一個(gè)元素為insetv對象,對應(yīng)每一條記錄。Insert方法實(shí)現(xiàn)描述如下圖所示:

          插入數(shù)據(jù)操作函數(shù)

          本例所有的文本框行都是JS編碼實(shí)現(xiàn),因此需要在window對象的onload實(shí)踐中調(diào)用addRows方法實(shí)現(xiàn)初始化時(shí)生成第一行。實(shí)現(xiàn)代碼如下:

          初始化首行函數(shù)

          為方便測試演示與展示,我們將獲取的數(shù)據(jù)直接在本頁面進(jìn)行展示,實(shí)際測試過程描述如下動圖所示:

          動態(tài)實(shí)現(xiàn)效果展示

          在插入操作過程我們使用console.log()對輸入數(shù)據(jù)對應(yīng)數(shù)組進(jìn)行了控制臺的輸出。輸出結(jié)果如下:

          數(shù)據(jù)獲取存儲結(jié)果


          本頭條號長期關(guān)注編程資訊分享;編程課程、素材、代碼分享及編程培訓(xùn)。如果您對以上方面有興趣或代碼錯(cuò)誤、建議與意見,可以聯(lián)系作者,共同探討。期待大家關(guān)注!如需案例完整代碼請關(guān)注并私信,該案例相關(guān)文章鏈接如下:

          前端開發(fā)-拼圖游戲(N數(shù)碼問題)A*算法智能求解效果展示

          前端設(shè)計(jì)-JavaScript美女拼圖游戲開發(fā)實(shí)例

          前端設(shè)計(jì)-教你如何快速繪制HTML5動畫

          在本文中,我們將與大家分享 10個(gè)最佳的極簡 CSS 框架,它們能夠?yàn)槟闾峁┙ㄕ颈貍涞慕M件,幫助你節(jié)省時(shí)間。

          希望對大家有所幫助!

          一、Spectre(一個(gè)輕量級、響應(yīng)式的現(xiàn)代 CSS 框架,用于快速建站和擴(kuò)展程序的開發(fā)。它通過最佳編碼實(shí)踐和一致性的設(shè)計(jì)語言,為排版與元素、基于 Flexbox 的響應(yīng)布局系統(tǒng)、CSS 組件提供了基本樣式。)

          二、Milligram(提供了極簡樣式設(shè)置,便于你快速、簡潔的開啟建站之旅。雖然它不是一個(gè) UI 框架,但它的設(shè)計(jì)理念卻是以提供優(yōu)秀的性能、高效的開發(fā)效率以及最少的屬性重置而構(gòu)建的。同時(shí),它也是輕量的)

          三、Mobi(是一個(gè)輕量級、可擴(kuò)展、移動優(yōu)先的 CSS 框架。它專注于細(xì)節(jié),對于內(nèi)容豐富的網(wǎng)頁能夠提供優(yōu)質(zhì)的用戶體驗(yàn)。雖然,它專注移動端,但桌面客戶端的體驗(yàn)也是很棒的。)

          四、Mini(作為一個(gè) Gzip 壓縮后不到 7KB 大小的極簡框架,它具備響應(yīng)式、易用性和定制性等特性,旨在為你提供盡可能多的功能。由于它是輕量框架,不僅讓你創(chuàng)建的網(wǎng)站和應(yīng)用程序具備更快的加載速度,而且它所提供的組件可以滿足基本的開發(fā)要求。)

          五、 Siimple(是一個(gè)助你打造扁平化網(wǎng)站風(fēng)格的輕量、響應(yīng)式的開源框架。它內(nèi)置了 SASS / SCSS,為你的網(wǎng)頁設(shè)計(jì)提供了簡潔的開始。)

          六、Base(一個(gè)穩(wěn)固的響應(yīng)式 HTML 與 CSS 框架。)

          七、Scooter(專注為 Dropbox 提供基礎(chǔ)樣式、CSS 組件以及快速靜態(tài)原型的 SCSS 框架。)

          八、Responsive(一個(gè)功能強(qiáng)大、對開發(fā)人員友好的,用于構(gòu)建響應(yīng)式網(wǎng)站的輕量級前端框架。)

          九、 拼圖 Pintuer (國內(nèi)優(yōu)秀的HTML、CSS、JS跨屏響應(yīng)式開源前端框架,使用最新瀏覽器技術(shù),為快速的前端開發(fā)提供一系統(tǒng)的文本、圖標(biāo)、媒體、表格、表單、按鈕、菜單、網(wǎng)格系統(tǒng)等樣式工具包,占用資源小,使用拼圖可以快速構(gòu)建簡潔、優(yōu)雅而且自動適應(yīng)手機(jī)、平板、桌面電腦等設(shè)備的前端界面,讓前端開發(fā)像玩游戲一下快樂而輕松。)

          十、 BluCSS (是一個(gè)簡便易記的CSS框架。可輕松應(yīng)用在項(xiàng)目中。)

          相信大家都會自己心中最喜歡的工具,如果本文沒有列舉出來,歡迎大家在評論區(qū)留下自己心目中最喜歡、最有價(jià)值的工具~~

          切圖 qietu(.com)

          學(xué)lufylegend.js之日,我用lufylegend.js開發(fā)了第一個(gè)HTML5小游戲——拼圖游戲,還寫了篇博文來炫耀一下:HTML5小游戲《智力大拼圖》發(fā)布,挑戰(zhàn)你的思維風(fēng)暴。不過當(dāng)時(shí)初學(xué)游戲開發(fā),經(jīng)驗(yàn)淺薄,所以沒有好好專研游戲里的算法和代碼的缺陷,導(dǎo)致游戲出現(xiàn)了很多bug,甚至拼圖打亂后很可能無法復(fù)原。最近經(jīng)常有朋友問起這個(gè)游戲,希望我能把代碼里的bug改一下方便初學(xué)者學(xué)習(xí),順便我也打算測試一下自己寫這種小游戲的速度,所以就抽出了一些時(shí)間將這個(gè)游戲從頭到尾重新寫了一遍,計(jì)算了一下用時(shí),從準(zhǔn)備、修改素材到最后完成游戲,一共用了大約2h的時(shí)間。

          以下是游戲地址:

          由于頭條禁止在文章頁面加入鏈接,大家私信我“拼圖”即可獲取下載地址。

          這是我的游戲記錄,歡迎各位挑戰(zhàn):

          接下來就來講講如何開發(fā)完成這款游戲的。(按“編年體”)

          準(zhǔn)備階段

          準(zhǔn)備lufylegend游戲引擎,大家可以去官方網(wǎng)站下載:

          由于頭條禁止在文章頁面加入鏈接,大家私信我“拼圖”即可獲取下載地址。

          引擎文檔地址:

          由于頭條禁止在文章頁面加入鏈接,大家私信我“拼圖”即可獲取下載地址。

          可以說,如果沒有強(qiáng)大的lufylegend引擎,這種html5小游戲用原生canvas制作,少說要一天呢。

          0~30min

          準(zhǔn)備素材(10min) + 修改素材(20min)。由于在下實(shí)在手殘,不善于P圖,修改圖片用了大約20min,囧……

          30~50min

          開發(fā)開始界面。游戲不能沒有開始界面所以我們首先實(shí)現(xiàn)這部分代碼。在此之前是index.html里的代碼,代碼如下:

          <!DOCTYPE html>

          <html>

          <head>

          <title>Puzzle</title>

          <meta charset="utf-8">

          <meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">

          <script type="text/javascript" src="./lib/lufylegend-1.10.1.simple.min.js"></script>

          <script type="text/javascript" src="./js/Main.js"></script>

          </head>

          <body style="margin: 0px; font-size: 0px; background: #F2F2F2;">

          <div id="mygame"></div>

          </body>

          </html>

          主要是引入一些js文件,不多說。然后準(zhǔn)備一個(gè)Main.js文件,在這個(gè)文件里添加初始化界面和加載資源的代碼:

          /** 初始化游戲 */

          LInit(60, "mygame", 390, 580, main);

          var imgBmpd;

          /** 游戲?qū)?*/

          var stageLayer, gameLayer, overLayer;

          /** 拼圖塊列表 */

          var blockList;

          /** 是否游戲結(jié)束 */

          var isGameOver;

          /** 用時(shí) */

          var startTime, time, timeTxt;

          /** 步數(shù) */

          var steps, stepsTxt;

          function main () {

          /** 全屏設(shè)置 */

          if (LGlobal.mobile) {

          LGlobal.stageScale=LStageScaleMode.SHOW_ALL;

          }

          LGlobal.screen(LGlobal.FULL_SCREEN);

          /** 添加加載提示 */

          var loadingHint=new LTextField();

          loadingHint.text="資源加載中……";

          loadingHint.size=20;

          loadingHint.x=(LGlobal.width - loadingHint.getWidth()) / 2;

          loadingHint.y=(LGlobal.height - loadingHint.getHeight()) / 2;

          addChild(loadingHint);

          /** 加載圖片 */

          LLoadManage.load(

          [

          {path : "./js/Block.js"},

          {name : "img", path : "./images/img.jpg"}

          ],

          null,

          function (result) {

          /** 移除加載提示 */

          loadingHint.remove();

          /** 保存位圖數(shù)據(jù),方便后續(xù)使用 */

          imgBmpd=new LBitmapData(result["img"]);

          gameInit();

          }

          );

          }

          function gameInit (e) {

          /** 初始化舞臺層 */

          stageLayer=new LSprite();

          stageLayer.graphics.drawRect(0, "", [0, 0, LGlobal.width, LGlobal.height], true, "#EFEFEF");

          addChild(stageLayer);

          /** 初始化游戲?qū)?*/

          gameLayer=new LSprite();

          stageLayer.addChild(gameLayer);

          /** 初始化最上層 */

          overLayer=new LSprite();

          stageLayer.addChild(overLayer);

          /** 添加開始界面 */

          addBeginningUI();

          }

          以上代碼有詳細(xì)注釋,大家可以對照引擎文檔和注釋進(jìn)行閱讀。有些全局變量會在以后的代碼中使用,大家可以先忽略。接下來是addBeginningUI函數(shù)里的代碼,用于實(shí)現(xiàn)開始界面:

          function addBeginningUI () {

          var beginningLayer=new LSprite();

          beginningLayer.graphics.drawRect(0, "", [0, 0, LGlobal.width, LGlobal.height], true, "#EDEDED");

          stageLayer.addChild(beginningLayer);

          /** 游戲標(biāo)題 */

          var title=new LTextField();

          title.text="拼圖游戲";

          title.size=50;

          title.weight="bold";

          title.x=(LGlobal.width - title.getWidth()) / 2;

          title.y=160;

          title.color="#FFFFFF";

          title.lineWidth=5;

          title.lineColor="#000000";

          title.stroke=true;

          beginningLayer.addChild(title);

          /** 開始游戲提示 */

          var hint=new LTextField();

          hint.text="- 點(diǎn)擊屏幕開始游戲 -";

          hint.size=25;

          hint.x=(LGlobal.width - hint.getWidth()) / 2;

          hint.y=370;

          beginningLayer.addChild(hint);

          /** 開始游戲 */

          beginningLayer.addEventListener(LMouseEvent.MOUSE_UP, function () {

          beginningLayer.remove();

          startGame();

          });

          }

          到此,運(yùn)行代碼,得到我們的開始界面:

          看到這個(gè)畫面,其實(shí)我自己都想吐槽一下實(shí)在是太“樸素”了,囧……

          不過我這次圖個(gè)制作速度,所以還望各位看官海量。

          50~90min

          這40分鐘的時(shí)間,是最關(guān)鍵時(shí)期,期間我們要完成整個(gè)游戲的主體部分。首先,我們需要用代碼來實(shí)現(xiàn)以下過程:

          初始化游戲界面數(shù)據(jù)(如游戲時(shí)間、所用步數(shù))和顯示一些UI部件(如圖樣)

          |

          -> 獲取隨機(jī)的拼圖塊位置

          |

          -> 顯示打亂后的拼圖塊

          我們將這些步驟做成一個(gè)個(gè)的函數(shù)方便我們統(tǒng)一調(diào)用:

          function startGame () {

          isGameOver=false;

          /** 初始化時(shí)間和步數(shù) */

          startTime=(new Date()).getTime();

          time=0;

          steps=0;

          /** 初始化拼圖塊列表 */

          initBlockList();

          /** 打亂拼圖 */

          getRandomBlockList();

          /** 顯示拼圖 */

          showBlock();

          /** 顯示縮略圖 */

          showThumbnail();

          /** 顯示時(shí)間 */

          addTimeTxt();

          /** 顯示步數(shù) */

          addStepsTxt();

          stageLayer.addEventListener(LEvent.ENTER_FRAME, onFrame);

          }

          函數(shù)一開始,我們把isGameOver變量設(shè)定為false代表游戲未結(jié)束,在后期的代碼里,我們會看到這個(gè)變量的作用。接著我們初始化了用于表示時(shí)間和步數(shù)的time和steps這兩個(gè)全局變量,另外初始化變量startTime的值用于后面計(jì)算游戲時(shí)間。

          接下來,我們就要開始初始化拼圖塊了。見initBlockList里的代碼:

          function initBlockList () {

          blockList=new Array();

          for (var i=0; i < 9; i++) {

          /** 根據(jù)序號計(jì)算拼圖塊圖片顯示位置 */

          var y=(i / 3) >>> 0, x=i % 3;

          blockList.push(new Block(i, x, y));

          }

          }

          這里我們使用了一個(gè)Block類,這個(gè)類用于顯示拼圖塊和儲存拼圖塊的數(shù)據(jù),并提供了一些方法來操控拼圖塊,下面是其構(gòu)造器的代碼:

          function Block (index, x, y) {

          LExtends(this, LSprite, []);

          var bmpd=imgBmpd.clone();

          bmpd.setProperties(x * 130, y * 130, 130, 130);

          this.bmp=new LBitmap(bmpd);

          this.addChild(this.bmp);

          var border=new LShape();

          border.graphics.drawRect(3, "#CCCCCC", [0, 0, 130, 130]);

          this.addChild(border);

          this.index=index;

          this.addEventListener(LMouseEvent.MOUSE_UP, this.onClick);

          }

          Block類繼承自LSprite,屬于一個(gè)顯示對象,所以我們在這個(gè)類中添加了一個(gè)位圖對象用于顯示拼圖塊對應(yīng)的圖片。除此之外,我們還為拼圖塊添加了一個(gè)邊框,在顯示時(shí)用于隔開周圍的拼圖塊。Block類有一個(gè)index屬性,代表拼圖塊在拼圖塊列表blockList中的正確位置。最后,我們?yōu)榇祟愄砑恿艘粋€(gè)鼠標(biāo)按下事件,用于處理鼠標(biāo)按下后移動圖塊操作。

          接下來我們還要介紹這個(gè)類的一個(gè)方法setLocation:

          Block.prototype.setLocation=function (x, y) {

          this.locationX=x;

          this.locationY=y;

          this.x=x * 130;

          this.y=y * 130;

          };

          這個(gè)方法用于設(shè)置拼圖塊對象的顯示位置以及保存拼圖塊的“數(shù)組位置”。什么是“數(shù)組位置”呢?各位看官可以通過下面的圖片加以了解:

          可以看到,“數(shù)組位置”就類似于二維數(shù)組中的元素下標(biāo)。儲存這個(gè)位置的作用在于可以很方便地從blockList中獲取到附近的其他拼圖塊。這個(gè)方法在我們顯示拼圖時(shí)有調(diào)用到,在顯示拼圖之前,我們得先打亂拼圖,見如下代碼:

          function getRandomBlockList () {

          /** 隨機(jī)打亂拼圖 */

          blockList.sort(function () {

          return 0.5 - Math.random();

          });

          /** 計(jì)算逆序和 */

          var reverseAmount=0;

          for (var i=0, l=blockList.length; i < l; i++) {

          var currentBlock=blockList[i];

          for (var j=i + 1; j < l; j++) {

          var comparedBlock=blockList[j];

          if (comparedBlock.index < currentBlock.index) {

          reverseAmount++;

          }

          }

          }

          /** 檢測打亂后是否可還原 */

          if (reverseAmount % 2 !=0) {

          /** 不合格,重新打亂 */

          getRandomBlockList();

          }

          }

          打亂拼圖部分直接用數(shù)組的sort方法進(jìn)行隨機(jī)打亂:

          blockList.sort(function () {

          return 0.5 - Math.random();

          });

          其實(shí)打亂算法有很多種,我這里采用最粗暴的方法,也就是隨機(jī)打亂。這種算法簡單是簡單,壞在可能出現(xiàn)無法復(fù)原的現(xiàn)象。針對這個(gè)問題,就有配套的檢測打亂后是否可還原的算法,具體的算法理論我借用lufy大神的評論:

          此類游戲能否還原關(guān)鍵是看它打亂后的逆序次數(shù)之和是否為偶數(shù)

          假設(shè)你打亂后的數(shù)組中的每一個(gè)小圖塊為obj0,obj1,obj2,…它們打亂之前的序號分別為obj0.num,obj1.num…

          接下來循環(huán)數(shù)組,如果前面元素的序號比此元素后某個(gè)元素的序號大,如obj0.num > obj1.num或者obj2.num > obj4.num就表示一個(gè)逆序

          當(dāng)全部的逆序之和為奇數(shù)時(shí)表示不可還原,重新打亂即可,打亂后重新檢測,直到逆序之和為偶數(shù)為止

          舉個(gè)例子,如果有一個(gè)數(shù)組為[3, 4, 2, 1],那么里面3 2, 3 1, 2 4, 4 1, 2 1是逆序的,所以逆序數(shù)是5。

          上面我給出的getRandomBlockList里的代碼就是在實(shí)現(xiàn)打亂算法和檢測是否可還原算法。

          還有一種打亂方式,大家可以嘗試嘗試:和復(fù)原拼圖一樣,將空白塊一步一步地與周圍的拼圖隨機(jī)交換順序。這個(gè)打亂算法較上一種而言,不會出現(xiàn)無法復(fù)原的現(xiàn)象,而且可以根據(jù)打亂的步數(shù)設(shè)定游戲難度。

          在完成打亂拼圖塊后,如期而至的是顯示拼圖塊:

          function showBlock() {

          for (var i=0, l=blockList.length; i < l; i++) {

          var b=blockList[i];

          /** 根據(jù)序號計(jì)算拼圖塊位置 */

          var y=(i / 3) >>> 0, x=i % 3;

          b.setLocation(x, y);

          gameLayer.addChild(b);

          }

          }

          顯示了拼圖塊后,我們要做的就是添加操作拼圖塊的功能。于是需要拓展Block類,為其添加事件監(jiān)聽器onClick方法:

          Block.prototype.onClick=function (e) {

          var self=e.currentTarget;

          if (isGameOver) {

          return;

          }

          var checkList=new Array();

          /** 判斷右側(cè)是否有方塊 */

          if (self.locationX > 0) {

          checkList.push(Block.getBlock(self.locationX - 1, self.locationY));

          }

          /** 判斷左側(cè)是否有方塊 */

          if (self.locationX < 2) {

          checkList.push(Block.getBlock(self.locationX + 1, self.locationY));

          }

          /** 判斷上方是否有方塊 */

          if (self.locationY > 0) {

          checkList.push(Block.getBlock(self.locationX, self.locationY - 1));

          }

          /** 判斷下方是否有方塊 */

          if (self.locationY < 2) {

          checkList.push(Block.getBlock(self.locationX, self.locationY + 1));

          }

          for (var i=0, l=checkList.length; i < l; i++) {

          var checkO=checkList[i];

          /** 判斷是否是空白拼圖塊 */

          if (checkO.index==8) {

          steps++;

          updateStepsTxt();

          Block.exchangePosition(self, checkO);

          break;

          }

          }

          };

          首先,我們在這里看到了isGameOver全局變量的作用,即在游戲結(jié)束后,阻斷點(diǎn)擊拼圖塊后的操作。

          在點(diǎn)擊了拼圖塊后,我們先獲取該拼圖塊周圍的拼圖塊,并將它們裝入checkList,再遍歷checkList,當(dāng)判斷到周圍有空白拼圖塊后,即周圍有index屬性等于8的拼圖塊后,先更新操作步數(shù),然后將這兩個(gè)拼圖塊交換位置。具體交換拼圖塊位置的方法詳見如下代碼:

          Block.exchangePosition=function (b1, b2) {

          var b1x=b1.locationX, b1y=b1.locationY,

          b2x=b2.locationX, b2y=b2.locationY,

          b1Index=b1y * 3 + b1x,

          b2Index=b2y * 3 + b2x;

          /** 在地圖塊數(shù)組中交換兩者位置 */

          blockList.splice(b1Index, 1, b2);

          blockList.splice(b2Index, 1, b1);

          /** 交換兩者顯示位置 */

          b1.setLocation(b2x, b2y);

          b2.setLocation(b1x, b1y);

          /** 判斷游戲是否結(jié)束 */

          Block.isGameOver();

          };

          還有就是Block.getBlock靜態(tài)方法,用于獲取給定的“數(shù)組位置”下的拼圖塊:

          Block.getBlock=function (x, y) {

          return blockList[y * 3 + x];

          };

          在Block.exchangePosition中,我們通過Block.isGameOver判斷玩家是否已將拼圖復(fù)原:

          Block.isGameOver=function () {

          var reductionAmount=0, l=blockList.length;

          /** 計(jì)算還原度 */

          for (var i=0; i < l; i++) {

          var b=blockList[i];

          if (b.index==i) {

          reductionAmount++;

          }

          }

          /** 計(jì)算是否完全還原 */

          if (reductionAmount==l) {

          /** 游戲結(jié)束 */

          gameOver();

          }

          };

          到這里,我們就實(shí)現(xiàn)了打亂和操作拼圖塊部分。

          90~120min

          最后30min用于細(xì)枝末節(jié)上的處理,如顯示拼圖縮略圖、顯示&更新時(shí)間和步數(shù),以及添加游戲結(jié)束畫面,這些就交給如下冗長而簡單的代碼來完成吧:

          function showThumbnail() {

          var thumbnail=new LBitmap(imgBmpd);

          thumbnail.scaleX=130 / imgBmpd.width;

          thumbnail.scaleY=130 / imgBmpd.height;

          thumbnail.x=(LGlobal.width - 100) /2;

          thumbnail.y=410;

          overLayer.addChild(thumbnail);

          }

          function addTimeTxt () {

          timeTxt=new LTextField();

          timeTxt.stroke=true;

          timeTxt.lineWidth=3;

          timeTxt.lineColor="#54D9EF";

          timeTxt.color="#FFFFFF";

          timeTxt.size=18;

          timeTxt.x=20;

          timeTxt.y=450;

          overLayer.addChild(timeTxt);

          updateTimeTxt();

          }

          function updateTimeTxt () {

          timeTxt.text="時(shí)間:" + getTimeTxt(time);

          }

          function getTimeTxt () {

          var d=new Date(time);

          return d.getMinutes() + " : " + d.getSeconds();

          };

          function addStepsTxt () {

          stepsTxt=new LTextField();

          stepsTxt.stroke=true;

          stepsTxt.lineWidth=3;

          stepsTxt.lineColor="#54D9EF";

          stepsTxt.color="#FFFFFF";

          stepsTxt.size=18;

          stepsTxt.y=450;

          overLayer.addChild(stepsTxt);

          updateStepsTxt();

          }

          function updateStepsTxt () {

          stepsTxt.text="步數(shù):" + steps;

          stepsTxt.x=LGlobal.width - stepsTxt.getWidth() - 20;

          }

          function onFrame () {

          if (isGameOver) {

          return;

          }

          /** 獲取當(dāng)前時(shí)間 */

          var currentTime=(new Date()).getTime();

          /** 計(jì)算使用的時(shí)間并更新時(shí)間顯示 */

          time=currentTime - startTime;

          updateTimeTxt();

          }

          function gameOver () {

          isGameOver=true;

          var resultLayer=new LSprite();

          resultLayer.filters=[new LDropShadowFilter()];

          resultLayer.graphics.drawRoundRect(3, "#BBBBBB", [0, 0, 350, 350, 5], true,"#DDDDDD");

          resultLayer.x=(LGlobal.width - resultLayer.getWidth()) / 2;

          resultLayer.y=LGlobal.height / 2;

          resultLayer.alpha=0;

          overLayer.addChild(resultLayer);

          var title=new LTextField();

          title.text="游戲通關(guān)"

          title.weight="bold";

          title.stroke=true;

          title.lineWidth=3;

          title.lineColor="#555555";

          title.size=30;

          title.color="#FFFFFF";

          title.x=(resultLayer.getWidth() - title.getWidth()) / 2;

          title.y=30;

          resultLayer.addChild(title);

          var usedTimeTxt=new LTextField();

          usedTimeTxt.text="游戲用時(shí):" + getTimeTxt(time);

          usedTimeTxt.size=20;

          usedTimeTxt.stroke=true;

          usedTimeTxt.lineWidth=2;

          usedTimeTxt.lineColor="#555555";

          usedTimeTxt.color="#FFFFFF";

          usedTimeTxt.x=(resultLayer.getWidth() - usedTimeTxt.getWidth()) / 2;

          usedTimeTxt.y=130;

          resultLayer.addChild(usedTimeTxt);

          var usedStepsTxt=new LTextField();

          usedStepsTxt.text="所用步數(shù):" + steps;

          usedStepsTxt.size=20;

          usedStepsTxt.stroke=true;

          usedStepsTxt.lineWidth=2;

          usedStepsTxt.lineColor="#555555";

          usedStepsTxt.color="#FFFFFF";

          usedStepsTxt.x=usedTimeTxt.x;

          usedStepsTxt.y=180;

          resultLayer.addChild(usedStepsTxt);

          var hintTxt=new LTextField();

          hintTxt.text="- 點(diǎn)擊屏幕重新開始 -";

          hintTxt.size=23;

          hintTxt.stroke=true;

          hintTxt.lineWidth=2;

          hintTxt.lineColor="#888888";

          hintTxt.color="#FFFFFF";

          hintTxt.x=(resultLayer.getWidth() - hintTxt.getWidth()) / 2;

          hintTxt.y=260;

          resultLayer.addChild(hintTxt);

          LTweenLite.to(resultLayer, 0.5, {

          alpha : 0.7,

          y : (LGlobal.height - resultLayer.getHeight()) / 2,

          onComplete : function () {

          /** 點(diǎn)擊界面重新開始游戲 */

          stageLayer.addEventListener(LMouseEvent.MOUSE_UP, function () {

          gameLayer.removeAllChild();

          overLayer.removeAllChild();

          stageLayer.removeAllEventListener();

          startGame();

          });

          }

          });

          }

          Ok,2h下來,整個(gè)游戲就搞定咯~不得不表揚(yáng)一下lufylegend這個(gè)游戲引擎,實(shí)在是可以大幅提升開發(fā)效率。

          源代碼下載

          最后奉上源代碼:

          由于頭條禁止在文章頁面加入鏈接,大家私信我“拼圖”即可獲取下載地址。

          致謝與反思

          這篇博文在最初寫成的時(shí)候,我沒有對逆序算法進(jìn)行深入研究,再加上我的測試不仔細(xì),我沒有發(fā)現(xiàn)算法的錯(cuò)誤之處。因此,在博文發(fā)布后,不少讀者發(fā)現(xiàn)游戲無解現(xiàn)象并將此問題反饋給了我,經(jīng)過網(wǎng)友熱心幫助,我才找到了問題所在,并更正了算法。在此對這些熱心的網(wǎng)友表示真心的感謝,也為我學(xué)習(xí)不深入,以及誤導(dǎo)了不少讀者而感到十分內(nèi)疚自責(zé)。

          如果大家對本文有任何意見或不解,歡迎留言~


          主站蜘蛛池模板: 一区二区三区四区视频在线| 国产精品日韩一区二区三区| 亚洲AV乱码一区二区三区林ゆな| 亚洲av无码一区二区三区不卡| 亚洲色一区二区三区四区| 一区二区三区视频观看| 中文字幕精品一区二区2021年| 亚洲中文字幕无码一区二区三区 | 福利电影一区二区| 日本伊人精品一区二区三区| 三上悠亚一区二区观看| 亚洲第一区在线观看| 国产成人久久一区二区三区| 91在线一区二区| 人妻无码一区二区不卡无码av| 亚洲一区无码中文字幕| 中文字幕亚洲一区| 成人区精品人妻一区二区不卡| 精品人体无码一区二区三区| 亚洲中文字幕丝袜制服一区| 无码人妻精品一区二| 日韩精品一区在线| 黑人一区二区三区中文字幕| 精彩视频一区二区| 国产免费伦精品一区二区三区| 久久亚洲中文字幕精品一区四| 亚洲视频在线一区二区| 国产一区麻豆剧传媒果冻精品| 国产一区二区三区在线观看精品| 中文字幕一区二区三| 亚洲国产成人一区二区精品区| 亚洲国产成人一区二区精品区 | 国语对白一区二区三区| 亚洲AV无码国产一区二区三区| 欧美人妻一区黄a片| 春暖花开亚洲性无区一区二区| 国产精品一区二区久久沈樵| 一区二区在线播放视频| 亚洲国产精品一区二区成人片国内| 久久久久人妻一区精品色| 国产午夜精品一区二区三区极品 |