用JS寫一個拼圖游戲

思路:

  1. 上傳一張自己的本地的圖片
  2. 將圖片分割成若干行若干列
+ 給每一個小格子,添加上自己的索引
+ 把索引存入一個數(shù)組中,方便最后判斷是否完成
  1. 分割的每一個小格子上都顯示完整圖片對應(yīng)的一部分
  2. 點擊開始游戲按鈕,打亂圖片的位置
+ 創(chuàng)建一個新數(shù)組敬肚,將原數(shù)組打亂之后存到新數(shù)組中
+ 讓每一個小格子根據(jù)打亂后的數(shù)組進行定位
  1. 點擊兩個不同的小格,讓其交換位置。
+ 小格子位置交換完成后郁妈,需要將打亂的數(shù)組對應(yīng)的兩個值也交換位置。
  1. 判斷交換后的亂序數(shù)組和原來的數(shù)組是否相等认臊,如果相等即表示游戲完成圃庭。

難點:

  1. 如何上傳本地圖片讓其顯示的
  2. 如何將一張圖片切割成多個小格子
  3. 如果根據(jù)亂序的數(shù)組來計算當前的行數(shù)和列數(shù)

解決辦法:

  1. 針對于如何上傳一張本體圖片,看之前的一篇關(guān)于瀏覽器如何在頁面上顯示準備上傳的圖片的問題失晴,下面是傳送門剧腻。
+ <a target = "_blank" href="http://www.reibang.com/p/9e4a1ee03089">關(guān)于瀏覽器如何在頁面上顯示準備上傳的圖片的問題</a>
  1. 針對如何切割一張圖片的問題,事實上也并不能說是切割涂屁,且聽我細細道來书在。
+ 首先我們利用兩個for循環(huán),外層代表行數(shù)拆又,里面代表列數(shù)儒旬,然后動態(tài)創(chuàng)建div來表示每一個小方格。
+ 然后我們分隔好了小方格帖族,我們也知道小方格的寬和高栈源,并且知道每行每列各有多少個小方格。
+ 之后我們給每一個小方格都設(shè)置一個`background-image`屬性竖般,讓每一個方格都有一個完整的圖甚垦。所以說這里并不是一張背景圖,而是有多少個小方格就有多少張圖片。
+ 再之后根據(jù)行數(shù)和列數(shù)的數(shù)量來設(shè)置`background-size`艰亮,比如只有一個格子闭翩,`background-size`的值就是 100% ,同理迄埃,兩個值就是200%
+ 最后根據(jù)當前第幾行疗韵,第幾列,每一個小格子的寬度和高度來計算出偏移量侄非,即left值和top值蕉汪。再利用`background-position`來進行定位即可實現(xiàn)。
  1. 針對根據(jù)亂序數(shù)組來計算當前的行數(shù)和列數(shù)彩库。這里其實也并不難肤无,只是我個人卡在這里卡了一會兒。骇钦。宛渐。。
+ 首先我們的亂序數(shù)組是根據(jù)原來的數(shù)組打亂順序而來眯搭,所以里面的數(shù)值除了順序應(yīng)該就是一樣的窥翩。
+ 當我們點擊圖片的時候能夠獲取到圖片所在的div的索引。
+ 因為原數(shù)組是按照0,1,2,3,4.....這樣排列的鳞仙,所以這個索引在亂序數(shù)組中對應(yīng)的值就是打亂后的圖片是從0開始數(shù)的第多少張圖片寇蚊。
+ 知道了這張圖片此時是屬于第幾張,我們就能根據(jù)這個值來計算出這張圖片此時對應(yīng)的行數(shù)和列數(shù)棍好。   
  - 當前是第幾張圖片 / 一行多少列 然后取整 就是當前屬于第幾行
  - 當前是第幾張圖片 % 一行多少列 然后取余 就是當前屬于第幾列

這里我用一張動圖來表示如果切割圖片的

如何把一張圖切割成多塊.gif

注意點:

  1. 打亂索引 的時候要注意仗岸,由于打亂的數(shù)組可能跟原數(shù)組還是一樣,所以需要控制一下借笙。
  2. 上傳的本地的圖片不要太大扒怖,不然讀取的速度那還真有點慢。业稼。盗痒。
  3. 上傳的圖片需要是個正方形的,實在沒有正方向的話低散,高度大于寬度的圖片也行俯邓,無非是下半部分被干掉了。熔号。
  4. 因為個人比較懶稽鞭。很多地方?jīng)]有寫兼容,所以打開小游戲請使用chrome瀏覽器

我們來看看關(guān)鍵代碼

  1. HTML部分
  <!-- 獲取圖片 -->
  <input type="file" id="file">
  <!-- 字體圖標 -->
  <div id="btn">
      <i class="iconfont icon-xiangji2"></i>      
  </div>
  <div id="gameArea">
      <!-- 游戲開始按鈕 -->
      <div id="gameStart">點擊開始</div>
      <!-- 圖片存放的區(qū)域 -->
      <div id="imgArea"></div>
  </div>
  1. CSS部分

css部分真沒啥好說的引镊,有興趣的話大家下載源碼朦蕴,一看就知道了

  1. JS部分
  • 切割圖片
      // 切割圖片
    imgSplit:function(){
        // 清空圖片存放區(qū)域
        this.imgArea.innerHTML = '';
        // 用來存方動態(tài)創(chuàng)建的div元素
        var _cell = '';
    
        // 行數(shù)
        for (var i = 0, l =this.leverArr[0]; i<l ;i++) {
            // 列數(shù)
            for (var j = 0,l =this.leverArr[1]; j<l ;j++) {
                // 給每張圖片一個索引值
                // 索引遞增規(guī)則為  從左到右  從上到下
                this.imgOrigArr.push(i*this.leverArr[0] + j);
                // 創(chuàng)建div
                _cell = document.createElement('div');
                // 給div添加id
                _cell.className = "imgCell";
                // 給每張一個索引吃嘿,方便后面點擊的時候進行判斷
                _cell.index = i*this.leverArr[0] + j;
                // 給div添加樣式
                _cell.style.width = this.cellWidth+'px';
                _cell.style.height = this.cellHeight+'px';
                _cell.style.left =  j*this.cellWidth+'px';
                _cell.style.top = i*this.cellHeight + 'px';
                _cell.style.backgroundImage= "url("+this.imgUrl+")";
                // 這里因為100%就讓背景圖的大小等于了一個小格子的大小
                // 而我們只需要原始圖的一部分,并不是想縮小原圖
                // 所以根據(jù)小格子的個數(shù)來放大圖片
                _cell.style.backgroundSize = this.leverArr[1]+'00%';
                // 移動背景圖梦重,行成最后切成的一塊塊的效果
                _cell.style.backgroundPosition = (-j)*this.cellWidth + 'px ' + (-i)*this.cellHeight+'px';
                // 讓背景圖從邊框開始平鋪
                _cell.style.backgroundOrigin = "border-box";
                this.imgArea.appendChild(_cell);
            }
        }
    
        // 獲取小格子的dom元素
        this.imgCells = document.querySelectorAll('.imgCell');
    
        //將選擇圖片的按鈕移動到可視區(qū)域外
        this.btnObj.style.left= -this.btnObj.offsetWidth+'px';
        // 將圖片移入可視區(qū)域
        // this.gameAreaObj.style.background = 'url('+this.imgUrl +')';
        this.gameAreaObj.style.left = '50%';
        this.gameAreaObj.style.transform= 'translate(-50%,-50%)';
    
        // 使按鈕綁定事件,點擊按鈕開始整個游戲
        this.gameStartBtnObj.onclick = this.clickHandle();
    }
    
  • 打亂圖片索引
      // 打亂圖片索引
    randomArr:function(){
        // 清空亂序數(shù)組
        this.imgRandomArr = [];
        // 判斷原來的數(shù)組是否和亂序數(shù)組一樣
        var _flag = true;
        // 遍歷原始索引
        for(var i=0,l=this.imgOrigArr.length;i<l;i++){
            // 獲取從0到數(shù)組長度之間的一個索引值
            var order = Math.floor(Math.random()*this.imgOrigArr.length);
            // 如果亂序數(shù)組中沒有值就直接添加
            // 否則就在這個亂序數(shù)組中找對應(yīng)的隨機數(shù)的索引亮瓷,找不到就添加,找到就繼續(xù)隨機
            if(this.imgRandomArr.length>0){
                while(this.imgRandomArr.indexOf(order) >-1){
                    order = Math.floor(Math.random()*this.imgOrigArr.length);
                }
            }
            this.imgRandomArr.push(order);
        }
    
        // 判斷亂序數(shù)組和原始數(shù)組是否一樣
        if(this.imgRandomArr.length === this.imgOrigArr.length){
            // 遍歷數(shù)組
            for(var i=0,l=this.imgOrigArr.length;i<l;i++){
                if(this.imgRandomArr[i] != this.imgOrigArr[i]){
                    _flag = false;
                    break;
                }else{
                    _flag = true;
                }
            }
        }else{
            _flag = true;
        }
    
        // 返回值為true的話 就代表原始數(shù)組和亂序數(shù)組一致琴拧,重新打亂數(shù)組
        if(_flag){
            this.randomArr();
        }
    }
    
  • 交換兩次點擊的圖片位置
      // 交換兩次點擊的圖片位置
    cellExchange:function(from,to){
        // 因為圖片此時的排序是根據(jù) 以圖片的索引值為索引
        // 在亂序的數(shù)組中根據(jù)相對應(yīng)的索引取出的值作為當前圖片的排序位置的
        // 因此根據(jù)from to這兩個值作為索引,就能在亂序數(shù)組中得到當前圖片是第幾張
    
        // 求出from的圖片 是第幾行第幾列
        // 當前是第幾張圖片 / 一行多少列 然后取整 就是當前屬于第幾行
        var _fromRow = Math.floor(this.imgRandomArr[from] / this.leverArr[1]);
        // 當前是第幾張圖片 % 一行多少列 然后取余 就是當前屬于第幾列
        var _fromCol = this.imgRandomArr[from] % this.leverArr[1];
        // 求出to的圖片 是第幾張第幾列
        var _toRow = Math.floor(this.imgRandomArr[to] / this.leverArr[1]);
        var _toCol = this.imgRandomArr[to] % this.leverArr[1];
    
        // 移動兩張圖片
        this.imgCells[from].style.left = _toCol*this.cellWidth + 'px';
        this.imgCells[from].style.top = _toRow*this.cellHeight + 'px';
    
        this.imgCells[to].style.left = _fromCol*this.cellWidth + 'px';
        this.imgCells[to].style.top = _fromRow*this.cellHeight + 'px';
    
        // 將亂序數(shù)組中的兩個值交換位置
        // 定義一個臨時變量來實現(xiàn)交換順序
        var _temp = this.imgRandomArr[from];
        this.imgRandomArr[from] = this.imgRandomArr[to];
        this.imgRandomArr[to] = _temp;
    
        //如果亂序數(shù)組和原數(shù)組一致嘱支,則表示拼圖已完成
        if(this.imgOrigArr.toString() === this.imgRandomArr.toString()){
            // 調(diào)用成功方法
            this.success();
        }
        
    }
    
源碼保存在了<a target = "_blank" >github</a>上蚓胸,有愛點擊github自取。
在線地址可以直接測試使用除师,<a target = "_blank" >拼圖小游戲</a>←點擊跳轉(zhuǎn)即可

總結(jié):

  1. 最近不知道怎么了沛膳,老是不在狀態(tài),腦袋反應(yīng)比較慢汛聚,一個簡單問題總是要想好久锹安。感覺整個人都魔怔了。倚舀。叹哭。。
  2. 本來我是想自動獲取圖片寬高來切成行列的痕貌,不過行數(shù)列數(shù)不相等的話风罩,好像有點麻煩。而且不是正方形也不好看啊舵稠。想了想還是不弄了超升。。想興趣的朋友自己弄弄吧哺徊。室琢。
  3. 順便一提,上面的動圖所用到的圖片唉工,畫師是P站的 METO@三日目東ミ24a
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末研乒,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子淋硝,更是在濱河造成了極大的恐慌雹熬,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,723評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件谣膳,死亡現(xiàn)場離奇詭異竿报,居然都是意外死亡,警方通過查閱死者的電腦和手機继谚,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評論 2 382
  • 文/潘曉璐 我一進店門烈菌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事芽世≈可蓿” “怎么了?”我有些...
    開封第一講書人閱讀 152,998評論 0 344
  • 文/不壞的土叔 我叫張陵济瓢,是天一觀的道長荠割。 經(jīng)常有香客問我,道長旺矾,這世上最難降的妖魔是什么蔑鹦? 我笑而不...
    開封第一講書人閱讀 55,323評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮箕宙,結(jié)果婚禮上嚎朽,老公的妹妹穿的比我還像新娘。我一直安慰自己柬帕,他們只是感情好哟忍,可當我...
    茶點故事閱讀 64,355評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著雕崩,像睡著了一般魁索。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上盼铁,一...
    開封第一講書人閱讀 49,079評論 1 285
  • 那天粗蔚,我揣著相機與錄音,去河邊找鬼饶火。 笑死鹏控,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的肤寝。 我是一名探鬼主播当辐,決...
    沈念sama閱讀 38,389評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼鲤看!你這毒婦竟也來了缘揪?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,019評論 0 259
  • 序言:老撾萬榮一對情侶失蹤义桂,失蹤者是張志新(化名)和其女友劉穎找筝,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體慷吊,經(jīng)...
    沈念sama閱讀 43,519評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡袖裕,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,971評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了溉瓶。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片急鳄。...
    茶點故事閱讀 38,100評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡谤民,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出疾宏,到底是詐尸還是另有隱情张足,我是刑警寧澤,帶...
    沈念sama閱讀 33,738評論 4 324
  • 正文 年R本政府宣布坎藐,位于F島的核電站兢榨,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏顺饮。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,293評論 3 307
  • 文/蒙蒙 一凌那、第九天 我趴在偏房一處隱蔽的房頂上張望兼雄。 院中可真熱鬧,春花似錦帽蝶、人聲如沸赦肋。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,289評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽佃乘。三九已至,卻和暖如春驹尼,著一層夾襖步出監(jiān)牢的瞬間趣避,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,517評論 1 262
  • 我被黑心中介騙來泰國打工新翎, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留程帕,地道東北人。 一個月前我還...
    沈念sama閱讀 45,547評論 2 354
  • 正文 我出身青樓地啰,卻偏偏與公主長得像愁拭,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子亏吝,可洞房花燭夜當晚...
    茶點故事閱讀 42,834評論 2 345

推薦閱讀更多精彩內(nèi)容

  • 工廠模式類似于現(xiàn)實生活中的工廠可以產(chǎn)生大量相似的商品岭埠,去做同樣的事情,實現(xiàn)同樣的效果;這時候需要使用工廠模式蔚鸥。簡單...
    舟漁行舟閱讀 7,718評論 2 17
  • 單例模式 適用場景:可能會在場景中使用到對象惜论,但只有一個實例,加載時并不主動創(chuàng)建株茶,需要時才創(chuàng)建 最常見的單例模式来涨,...
    Obeing閱讀 2,056評論 1 10
  • 《ijs》速成開發(fā)手冊3.0 官方用戶交流:iApp開發(fā)交流(1) 239547050iApp開發(fā)交流(2) 10...
    葉染柒丶閱讀 5,073評論 0 7
  • 以下是常用的代碼收集,學習用启盛。轉(zhuǎn)自豪情博客園 1. PC - js 返回指定范圍的隨機數(shù)(m-n之間)的公式 re...
    自由加咖啡閱讀 992評論 0 1
  • There are six kinds of coins in Canadian dollar, they are...
    懸崖上的小樹閱讀 347評論 3 6