20行のコードは何ができますか?

4779 ワード

csdnの上で1人の大神が20行のコードを使って1つの食いしん坊の蛇の小さいゲームを書き出したことを見て、びっくりさせられたことを感じて、このコードを読んでみて、過程の中で絶えず作者の書き方の巧みさのために絶叫して、その中で私は自分が演算子の優先度といくつかjsの技巧に対してとても明らかではないことを発見して、だから見終わった後に考えを分かち合うことを決定します.私と同じ白で勉強しやすいです.


                 

    
       ,        canvas    
    
        var snake = [41, 40],
            //snake      ,          
            direction = 1,      
            //1    ,-1    ,20    ,-20    
            food = 43,          
            //     
            n,                  
            //          
            box = document.getElementById('can').getContext('2d');                                    
            // 0 399  box [0~19]*[0~19]     , 20px    
        function draw(seat, color) {
            box.fillStyle = color;
            box.fillRect(seat % 20 *20 + 1, ~~(seat / 20) * 20 + 1, 18, 18);                                    
            // color      ,       x,y  ,         。
        }        
        document.onkeydown = function(evt) {    
            //               direction
            direction = snake[1] - snake[0] == (n = [-1, -20, 1, 20][(evt || event).keyCode - 37] || direction) ? direction : n;
        };
       !function() {
            snake.unshift(n = snake[0] + direction);    
            //   n          ,n    
            if(snake.indexOf(n, 1) > 0 || n < 0 || n > 399 || direction == 1 && n % 20 == 0 || direction == -1 && n % 20 == 19) {                                    //if                 ,     ,    
                return alert("GAME OVER!");
            }
            draw(n, "lime");    
            //           
            if(n == food) {     
            //       ,             ,      
                while (snake.indexOf(food = ~~(Math.random() * 400)) > 0);
                draw(food, "yellow");
            } else {            
            //           ,     
                draw(snake.pop(),"black");
            }
            setTimeout(arguments.callee, 150);      
            //  0.15       ,        
        }();    
    

コードを少し修正しました.
いくつかのコメントを追加しました.分かりやすいです.
まず、蛇を食べるために一番大切なことは何ですか?蛇の活動をする場所とどうやって蛇を動かしますか?
まず蛇の活動の場所を見ます.
   すみません、あなたのブラウザはcanvasをサポートしていません.
box=document.getElementById('can').get Conttext('2 d')
これは400 px*400 pxのcanvasで、考え方は20 px*20 pxを一つの格子にして、20行の20列の四角い陣を構成して、全部で400 gです.そして緑色の塗りつぶした格子は蛇の体を表して、黄色で食べ物を表します.この400個の格子は数字0~399と一対一に対応し、対応する方式は20を基数とし、n/20をさらに整理して何行目を表し、n%20を第数列とします.行数も列数も0~19で表します.
蛇は一次元配列で表しています.各値はこの400個の数の中の一つで、var snake=[41,40]を使います.この蛇を初期化して、索引の0は蛇の頭です.foodは食べ物の位置を表し、directionは蛇の次の運動の方向を表します.蛇の動きは配列要素の追加と削除で実現され、毎回蛇頭を描き、蛇尾を取り除き、循環的に蛇を動かす.
以下は関数の運転の開始から見ます.
!function(){}
何の鬼ですか?これはすぐに関数IIIIFEを実行する別の書き方です.続けて見れば、蛇の頭にノードnを追加し、その値は現在の蛇の頭の値にディレクションの値を加えると、なぜ20で下を表し、-20で上を表しているのかが分かります.
次の行はif文で、注意すべきは&& 優先度が𞓜|より高いということです.この文は、出現する蛇の頭が蛇の胴かどうか判断したり、boxの外に走ったりします.もし死亡していないなら、この蛇頭を描いてください.次は絵のコードを見てみます.
function draw(seat、カラー)
   box.fillSteyle=カラー;
   box.fillrect(seat%20*20+1、~(seat/20)*20+1,18,18)
)
18*18ピクセルを塗りつぶし、1 pxの枠を残します.fillrect()の最初のパラメータは、描画する長方形のx座標seat%20*20+1であり、描画する矩形ブロックの正方形陣中の位置を先に得ることである.~(seat/20)行、第seat%20列、更に*20+1をピクセルポイントに具体化する.
これは~ちょっと分かりにくいかもしれませんが、ここではMath.flor()と同じように、浮動小数点型の数を逆手に取って逆をとるべきだと思います.得られた数は小数位を除く整数です.
前に戻って、また判断文です.次の蛇の頭の位置は現在の食べ物と同じ位置にあるかどうかを判断します.同じ場合、次の食べ物を生成します.食べ物の位置は乱数ですが、この点は現在の蛇に現れないかを判断して、食べ物を描きます.
食べ物が食べられなかったら、つまり蛇は正常に運動する時に、前の回に、蛇の尾を弾いて、その戻り値を利用してこの点を黒に描き直します.
最後のsetTimeoutは、現在の関数を循環的に実行し、実行周期を設定して蛇の移動速度を調整します.
ここに来て、私達はこの蛇がもう動くことができることを発見しました.キーボードの操作を加えて完成しました.
document.onkeydown=function(evt){   
   direction=snake[1]-snake[0]=(n=[-1,20,1,20][(evt|event).keyCode-37]?ディレクション)?ディレクション:n;
この関数をキーボードイベントに結びつけると、evt𞓜eventの使い方の原因がここで詳細に説明されています.ieに適合するためです.
三項演算子前の判定文はまた二つの部分に分けられます.
snake[1]-snake[0]の値は-directionであるべきです.ここで「direction」と書くのは本来の効果であるはずですが、なぜこのようにしていないのですか?このように書くと、ユーザーは1つの関数周期でdirectionの値を何度も変えて、最後にdirectionと現在の本格的な運動方向が一致しなくなり、ゲームが崩壊する可能性があります.
==の後、[-1,-20,1,20][(evt𞓜event).keyCode-37]の前の[]は1つの配列で、後の[]はインデックスを取り、左上右下の4つのキーのkeyCodeはそれぞれ37,38,39,40で、計算後のインデックスは0,1,2,3で、方向キーのdiction値に対応します.ここの巧妙なところは、押すボタンが矢印キーではない場合、配列中に対応する値が得られず、undefineに戻ることです.このとき、その後の𞓜𞓜演算子により、nはdirectionの元の値を取る.
三つの演算子で判断します.ボタンの方向が反対方向でなければ、directionの値を更新します.