JavaScript の絶妙なスネーク実装プロセス

JavaScript の絶妙なスネーク実装プロセス

この記事は簡単ではありません! !

今日、ブロガーは小さなスネークゲームを書くために一生懸命取り組みました。ゼロから始めるプロセス全体がただただスリリングでした。

次回は、このブロガーがこのプロセスについて詳しく説明します。 !

では、早速、最終プレゼンテーションを見てみましょう。

見て初めて作戦の意味が分かりました。まさに伝説的です! !

次は自慢せずに実際の操作についてお話ししましょう!

まず第一に、いわゆるヘビはテーブルの上を歩く色に過ぎないことを知っておく必要があります。初期効果は以下のとおりです

もちろん、ここでの操作には配列が使用され、カプセル化にはコンストラクターが使用されます。

ここでは、食べ物、ヘビ、メディエーターの Game.js ファイルを書き込むために使用される 3 つの js ファイルがカプセル化されています。

先ほど言ったように、スネークの作成はゼロからのプロセスなので、最初は index.html に何もなく、div ボックスだけがあり、他のテーブル、スネーク、食べ物はすべて関数を使用して後で作成されました。

1. HTML構造を作成する

以下は、本体の初期コードです。

<本文>
    <div id="アプリ">
    </div>
    <script src="js/Snake.js"></script>
    <script src="js/Food.js"></script>
    <script src="js/Game.js"></script>
    <スクリプト>
        var ゲーム = 新しいゲーム();
    </スクリプト>
</本文>

2. テーブルを作成する

もちろん、最初から始める最初のステップは、まずページにテーブルを追加することです。そのため、一般的なフレームワークが必要です。 !このようにして、上の写真のような表が表示されます。これを見ると、次のステップはすべて価値があるように思えます。

関数ゲーム() {
    this.row = 25; //行数 this.col = 25; //列数 this.init(); //ノードを初期化する }
Game.prototype.init = 関数(){
    this.dom = document.createElement('table'); // テーブルを作成します var tr, td;
    // 行と列を走査する for (var i = 0; i < this.row; i++) {
        tr = document.createElement('tr'); // 行を作成する for (var j = 0; j < this.col; j++) {
            td = document.createElement('td'); // 列を作成します tr.appendChild(td); // 行に列を追加します }
        this.dom.appendChild(tr); // テーブルに行を追加します}
    document.querySelector('#app').appendChild(this.dom); // テーブルを div に追加します}

3. ヘビの頭と体を作る

無から有への第2段階、蛇の頭、蛇の頭、蛇の頭、蛇の体、蛇の体、蛇の体!これを見て、学ぶこと、知ることがいかに大切かを実感しました。

関数Snake() {
    // スネークの初期化本体 this.body = [
        { '行': 3, '列': 5 },
        { '行': 3, '列': 4 },
        { '行': 3, '列': 3 },
        { '行': 3、 '列': 2 }
    ];
}
Snake.prototype.render = 関数 () {
    // ヘビの頭のレンダリング game.setColorHead(this.body[0].row, this.body[0].col);
    // ヘビの体のレンダリング for (var i = 1; i < this.body.length; i++) {
        game.setColor(this.body[i].row, this.body[i].col, '#649c49')
    }
}

Snake はメディエーターのゲーム プロトタイプ オブジェクトのプロパティを呼び出します。

Game.prototype.setColor = 関数 (行、列、色) {
    this.dom.getElementsByTagName('tr')[row].getElementsByTagName('td')[col].style.background = color;
}

4. 食べ物を作る

何もない状態から何かを生み出す第 3 ステップは、食べ物、食べ物、食べ物です。これを見ると、基本的な形式がすべて揃っています。

関数 Food(gameSnake) {
    var self = this;
    // 次の do-while ループ ステートメントは、最初に行と列を作成し、次に行と列がスネーク上にあるかどうかを判断するために使用されます。do {
        // 食べ物の場所 this.row = parseInt(Math.random() * gameSnake.row)
        this.col = parseInt(Math.random() * gameSnake.col)
    } while ((関数 () {
        // ヘビの行と列を走査し、それが新しくランダムに生成された食べ物の行と列と重なるかどうかを確認します for (var i = 0; i < gameSnake.snake.body.length; i++) {
            self.row == gameSnake.snake.body[i].row && self.col == gameSnake.snake.body[i].col) の場合 {
                true を返します。
            }
        }
        false を返します。
    })());
}
Food.prototype.render = 関数(){
    game.setHTML(this.row, this.col);
}

5. ヘビを動かす

何もないところから何かを生み出す第 4 ステップ: 動き出す、動く、動く!ここで配列の先頭、末尾、削除を使用すると、完璧な一致が得られます。

// スネークの動きSnake.prototype.update = function () {
    this.direction = this.willDirection;
    スイッチ(this.direction) {
        case 'R': //右 this.body.unshift({ 'row': this.body[0].row, 'col': this.body[0].col + 1 });
            壊す;
        case 'D': //次に this.body.unshift({ 'row': this.body[0].row + 1, 'col': this.body[0].col });
            壊す;
        case 'L': //左 this.body.unshift({ 'row': this.body[0].row, 'col': this.body[0].col - 1 });
            壊す;
        case 'U': //上へ this.body.unshift({ 'row': this.body[0].row - 1, 'col': this.body[0].col });
            壊す;
    }
    // テーブルの端を超えた部分の死の判定 if (this.body[0].col > game.col - 1 || this.body[0].col < 0 || this.body[0].row > game.row - 1 || this.body[0].row < 0) {
        alert('壁にぶつかりました。合計で ' + game.score + 'イチゴ' を食べました);
        this.body.shift();
        ゲームのタイマーをクリアします。
        場所を再読み込みします。
    }
    // 自分を殴ると、死んだと判断されます (var i = 1; i < this.body.length; i++) {
        // 現在のヘビの頭の行と列と体の特定の部分が完全に重なっている場合 if (this.body[0].row == this.body[i].row && this.body[0].col == this.body[i].col) {
            alert('自分自身にぶつかって食べてしまった' + game.score + 'イチゴ');
            this.body.shift();
            ゲームのタイマーをクリアします。
            場所を再読み込みします。
        }
    }
    // 餌を食べているヘビ // 現在のヘビの頭が餌と重なっていなければ、現時点で餌を食べていないことを意味します。このとき、尻尾は削除されます。重なっていれば、遅れていることを意味します。このとき、尻尾は削除しません if (this.body[0].row == game.food.row && this.body[0].col == game.food.col) {
        // この時点では頭のみが追加され、尻尾は削除されません。 game.food = new Food(game); // 新しい食べ物を作成します。 game.score++;
        ゲーム.f = 0;
    } それ以外 {
        this.body.pop(); //配列の最後の要素を削除します}
}

6. ヘビの方向を制御する

何もないところから何かあるところへの第 5 ステップは、蛇の方向です。ここまで来て、過去のすべてのステップを振り返ると、それらはすべてただ浮かんでいる雲です。 !

// レンダリング前に蛇が向きを変えないように蛇の方向を変更します Snake.prototype.changeDirection = function (d) {
    this.willDirection = d;
}
// キーボードイベント監視を設定する Game.prototype.bindEvent = function () {
    var self = this;
    document.addEventListener('keydown', 関数(e) {
        // ASCII コード値を使用してキーボードの方向スイッチを決定します (e.keyCode) {
            case 37: //leftif (self.snake.direction == 'R') return; // まず、現在の方向が右に移動している場合、この時点で左ボタンを押すことはできません。self.snake.changeDirection('L');
                自己.d = 'L';
                壊す;
            case 38: //上 if (self.snake.direction == 'D') return; // まず判断します。現在の方向が下向きの場合、この時点では上キーを押すことはできません。self.snake.changeDirection('U');
                自己.d = 'U';
                壊す;
            case 39: //rightif (self.snake.direction == 'L') return; // まず判断を下します。現在の方向が左に移動している場合、この時点では右ボタンを押すことはできません。self.snake.changeDirection('R');
                自己.d = 'R';
                壊す;
            case 40: //Nextif (self.snake.direction == 'U') return; // まず、現在の方向が上向きの場合、この時点ではキーを押すことはできません。self.snake.changeDirection('D');
                自己.d = 'D';
                壊す;
        }
    })
}

最後に、好きなスタイルを設定するだけです。ここでは、お気に入りのピンクに合わせて対応する色を設定し、好きな食べ物を挿入します。 !

7. 完全なコード

インデックス.html

<!DOCTYPE html>
<html lang="ja">
 
<ヘッド>
    <メタ文字セット="UTF-8">
    <meta http-equiv="X-UA-compatible" content="IE=edge">
    <meta name="viewport" content="width=デバイス幅、初期スケール=1.0">
    <title>ヘビ</title>
    <スタイル>
        * {
            パディング: 0;
            マージン: 0;
        }
 
        #アプリ {
            位置: 相対的;
            境界線: 20px 実線 #f8bbd0;
            背景色: #fce4ec;
            幅: 500ピクセル;
            高さ: 500px;
            マージン: 15px 自動;
        }
 
        テーブル {
            境界線の折りたたみ: 折りたたみ;
            背景色: #fce4ec;
        }
 
        td {
            位置: 相対的;
            背景サイズ: 100% 100%;
            境界線の半径: 50%;
            幅: 20px;
            高さ: 20px;
            テキスト配置: 中央;
            /* 背景色: #fce4ec; */
            /* 境界線: 1px 実線 #aaa; */
        }
 
        td .snake {
            位置: 絶対;
            上: 0;
            左: 0;
            幅: 100%;
            高さ: 100%;
        }
 
        。始める、
        。つるす {
            カーソル: ポインタ;
            位置: 絶対;
            幅: 150ピクセル;
            上位: 50%;
            左: 50%;
            変換: translate(-50%, -50%);
        }
 
        。つるす {
            表示: なし;
            zインデックス: 2;
        }
    </スタイル>
</head>
 
<本文>
    <!-- <h3 id="f">フレーム番号: 0</h3>
    <h3 id="score">スコア: 0</h3> -->
    <div id="アプリ">
        <img src="images/start.gif" alt="" class="start">
        <img src="images/suspended.png" alt="" class="suspend">
    </div>
    <!-- <script src="js/last.js"></script> -->
    <script src="js/Snake.js"></script>
    <script src="js/Food.js"></script>
    <script src="js/Game.js"></script>
    <スクリプト>
        var ゲーム = null;
        var フラグ = true;
        var suspend = document.querySelector('.suspend');
        document.querySelector('.start').addEventListener('click', 関数 () {
            // document.querySelector('#app').style.backgroundColor='white';
            this.style.display = 'なし';
            ゲーム = 新しいゲーム();
            document.querySelector('table').addEventListener('click', 関数 () {
                ゲームのタイマーをクリアします。
                suspend.style.display = 'ブロック';
 
            })
            suspend.addEventListener('click', 関数() {
                suspend.style.display = 'なし';
                game.timer = setInterval(関数() {
                    ゲーム.f++;
                    // document.getElementById('f').innerHTML = 'フレーム番号:' + game.f;
                    // document.getElementById('score').innerHTML = 'スコア:' + game.score;
                    // 画面をクリアします game.clear();
                    // ヘビの動き(更新)
                    // ヘビの速度を更新します。ヘビが長くなったら、速度を上げます。var during = game.snake.body.length < 30 ? 30 - game.snake.body.length : 1;
                    game.f % during == 0 && game.snake.update();
 
                    // game.snake.update();
                    // ヘビをレンダリングします game.snake.render();
                    // 食べ物をレンダリングする game.food.render();
                }, 10)
            })
        })
    </スクリプト>
</本文>
 
</html>

ゲーム

関数ゲーム() {
    this.row = 25; //行数this.col = 25; //列数this.score = 0; //スコアthis.init(); //ノードを初期化this.snake = new Snake(); //スネーククラスをインスタンス化this.food = new Food(this); //foodを初期化// this.last = new Last();
    this.start(); // タイマータスクを実行 this.bindEvent(); // キーボードイベントを監視 this.d = 'R';
}
Game.prototype.init = 関数() {
    this.dom = document.createElement('table'); // テーブルを作成します var tr, td;
    // 行と列を走査する for (var i = 0; i < this.row; i++) {
        tr = document.createElement('tr'); // 行を作成する for (var j = 0; j < this.col; j++) {
            td = document.createElement('td'); // 列を作成します tr.appendChild(td); // 行に列を追加します }
        this.dom.appendChild(tr); // テーブルに行を追加します}
    document.querySelector('#app').appendChild(this.dom); // テーブルを div に追加します}
// テーブルをトラバースしてテーブル上の色をクリアします。Game.prototype.clear = function () {
    (var i = 0; i < this.row; i++) の場合 {
        (var j = 0; j < this.col; j++) の場合 {
            this.dom.getElementsByTagName('tr')[i].getElementsByTagName('td')[j].style.background = '';
            this.dom.getElementsByTagName('tr')[i].getElementsByTagName('td')[j].innerHTML = '';
        }
    }
}
// テーブルの行と列の色を設定する方法 Game.prototype.setColor = function (row, col, color) {
    this.dom.getElementsByTagName('tr')[row].getElementsByTagName('td')[col].style.background = color;
}
// ヘビの頭を設定します Game.prototype.setColorHead = function (row, col) {
    var img = document.createElement('img');
    画像を拡大
    img.className = 'ヘビ';
    this.dom.getElementsByTagName('tr')[行].getElementsByTagName('td')[列].appendChild(img);
    // this.dom.getElementsByTagName('tr')[row].getElementsByTagName('td')[col].style.backgroundColor='transparent'
    スイッチ (this.d) {
        case 'R': //右ブレーク;
        case 'D': //次へ img.style.transform = 'rotate(90deg)';
                壊す;
        case 'L': //左 img.style.transform = 'rotate(180deg)';
                壊す;
        case 'U': //上 img.style.transform = 'rotate(-90deg)';
                壊す;
    }
}
// 食べ物のレンダリング Game.prototype.setHTML = function (row, col) {
    this.dom.getElementsByTagName('tr')[row].getElementsByTagName('td')[col].style.backgroundImage = 'url(./images/food.png)';
}
// キーボードイベント監視を設定する Game.prototype.bindEvent = function () {
    var self = this;
    document.addEventListener('keydown', 関数(e) {
        // ASCII コード値を使用してキーボードの方向スイッチを決定します (e.keyCode) {
            case 37: //leftif (self.snake.direction == 'R') return; // まず、現在の方向が右に移動している場合、この時点で左ボタンを押すことはできません。self.snake.changeDirection('L');
                自己.d = 'L';
                壊す;
            case 38: //上 if (self.snake.direction == 'D') return; // まず判断します。現在の方向が下向きの場合、この時点では上キーを押すことはできません。self.snake.changeDirection('U');
                自己.d = 'U';
                壊す;
            case 39: //rightif (self.snake.direction == 'L') return; // まず判断を下します。現在の方向が左に移動している場合、この時点では右ボタンを押すことはできません。self.snake.changeDirection('R');
                自己.d = 'R';
                壊す;
            case 40: //Nextif (self.snake.direction == 'U') return; // まず、現在の方向が上向きの場合、この時点ではキーを押すことはできません。self.snake.changeDirection('D');
                自己.d = 'D';
                壊す;
        }
    })
}
Game.prototype.start = 関数() {
    // フレーム番号 this.f = 0;
    // タイマーの核はゲームレンダリングの本質です: 画面をクリア - 更新 - レンダリング this.timer = setInterval(function () {
        ゲーム.f++;
        // document.getElementById('f').innerHTML = 'フレーム番号:' + game.f;
        // document.getElementById('score').innerHTML = 'スコア:' + game.score;
        // 画面をクリアします game.clear();
        // ヘビの動き(更新)
        // ヘビの速度を更新します。ヘビが長くなったら、速度を上げます。var during = game.snake.body.length < 30 ? 30 - game.snake.body.length : 1;
        game.f % during == 0 && game.snake.update();
        // game.snake.update();
        // ヘビをレンダリングします game.snake.render();
        // 食べ物をレンダリングする game.food.render();
    }, 10)
}

スネーク

関数Snake() {
    // スネークの初期化本体 this.body = [
        { '行': 3, '列': 5 },
        { '行': 3, '列': 4 },
        { '行': 3, '列': 3 },
        { '行': 3、 '列': 2 }
    ];
    this.direction = 'R'; //セマフォ、移動方向を設定します this.willDirection = 'R'; //変更する方向はその場でUターンすることです}
Snake.prototype.render = 関数 () {
    // ヘビの頭のレンダリング game.setColorHead(this.body[0].row, this.body[0].col);
    // ヘビの体のレンダリング for (var i = 1; i < this.body.length; i++) {
        game.setColor(this.body[i].row, this.body[i].col, '#649c49')
    }
}
// スネークの動きSnake.prototype.update = function () {
    this.direction = this.willDirection;
    スイッチ(this.direction) {
        case 'R': //右 this.body.unshift({ 'row': this.body[0].row, 'col': this.body[0].col + 1 });
            壊す;
        case 'D': //次に this.body.unshift({ 'row': this.body[0].row + 1, 'col': this.body[0].col });
            壊す;
        case 'L': //左 this.body.unshift({ 'row': this.body[0].row, 'col': this.body[0].col - 1 });
            壊す;
        case 'U': //上へ this.body.unshift({ 'row': this.body[0].row - 1, 'col': this.body[0].col });
            壊す;
    }
    // テーブルの端を超えた部分の死の判定 if (this.body[0].col > game.col - 1 || this.body[0].col < 0 || this.body[0].row > game.row - 1 || this.body[0].row < 0) {
        alert('壁にぶつかりました。合計で ' + game.score + 'イチゴ' を食べました);
        this.body.shift();
        ゲームのタイマーをクリアします。
        場所を再読み込みします。
    }
    // 自分を殴ると、死んだと判断されます (var i = 1; i < this.body.length; i++) {
        // 現在のヘビの頭の行と列と体の特定の部分が完全に重なっている場合 if (this.body[0].row == this.body[i].row && this.body[0].col == this.body[i].col) {
            alert('自分にぶつかって食べてしまった' + game.score + 'イチゴ');
            this.body.shift();
            ゲームのタイマーをクリアします。
            場所を再読み込みします。
        }
    }
    // 餌を食べているヘビ // 現在のヘビの頭が餌と重なっていなければ、現時点で餌を食べていないことを意味します。このとき、尻尾は削除されます。重なっていれば、遅れていることを意味します。このとき、尻尾は削除しません if (this.body[0].row == game.food.row && this.body[0].col == game.food.col) {
        // この時点では頭のみが追加され、尻尾は削除されません。 game.food = new Food(game); // 新しい食べ物を作成します。 game.score++;
        ゲーム.f = 0;
    } それ以外 {
        this.body.pop(); //配列の最後の要素を削除します}
}
// レンダリング前に蛇が向きを変えないように蛇の方向を変更します Snake.prototype.changeDirection = function (d) {
    this.willDirection = d;
}

フード.js

関数 Food(gameSnake) {
    var self = this;
    // 次の do-while ループ ステートメントは、最初に行と列を作成し、次に行と列がスネーク上にあるかどうかを判断するために使用されます。do {
        // 食べ物の場所 this.row = parseInt(Math.random() * gameSnake.row)
        this.col = parseInt(Math.random() * gameSnake.col)
    } while ((関数 () {
        // ヘビの行と列を走査し、新しくランダムに生成された食べ物の行と列と重なるかどうかを確認します for (var i = 0; i < gameSnake.snake.body.length; i++) {
            self.row == gameSnake.snake.body[i].row && self.col == gameSnake.snake.body[i].col) の場合 {
                true を返します。
            }
        }
        false を返します。
    })());
}
Food.prototype.render = 関数(){
    game.setHTML(this.row, this.col);
}

8. 写真

次に使用した写真をここに載せておきますので、気に入った方はそのままお使いください!

IX. 結論

最後まで読んでくれた皆さん、実はとても簡単だと思いませんか?興味があれば、今すぐ試してみてください! !

JavaScript の絶妙なスネークの実装プロセスに関するこの記事はこれで終わりです。より関連性の高い JavaScript スネークのコンテンツについては、123WORDPRESS.COM の以前の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM を応援していただければ幸いです。

以下もご興味があるかもしれません:
  • JSはスネークゲームを実装する
  • スネークゲームのアイデアを実現するためのJavaScript
  • 古典的なスネークゲームの JavaScript 実装
  • JS 実用的なオブジェクト指向スネークゲームの例

<<:  Presto をインストールし、Docker で Hive を接続する詳細なプロセス

>>:  CSS で 3D ブック効果を実装するためのサンプル コード

推薦する

MySQLの結合クエリ、ユニオンクエリ、サブクエリの原理と使用例の詳細な説明

この記事では、例を使用して、MySQL の結合クエリ、結合クエリ、サブクエリの原理と使用方法を説明し...

セマンティック HTML 構造の利点は何ですか?

1つ: 1.セマンティック タグは単なる HTML であり、CSS にはセマンティクスはありません...

Vue で className として空の文字列を使用することはなぜ推奨されないのですか?

目次空の文字列 '' と null を比較するケース1: 空の文字列を使用する &#...

ボタンの 4 つのクリック応答方法の概要

ボタンは頻繁に使用されます。ここでは、イベント処理メソッドを整理し、実装方法が多数あることを発見しま...

いくつかの重要なMySQL変数

MySQL 変数は数多くありますが、その中には注目に値するものもあります。ここでは、参考までに、注目...

Docker が elasticsearch を起動するときのメモリ不足の問題と解決策

質問Docker が elasticsearch をインストールして起動するときにメモリが不足するシ...

MySQL 8.0.18 のインストールと設定方法のグラフィックチュートリアル

この記事は、参考のためにMySQL 8.0.18のインストールと設定のグラフィックチュートリアルを記...

CSSの4種類の配置の違いの詳細な説明

フロントエンド開発でよく使われるCSSの配置方法は、位置決めには、通常位置決め、相対位置決め、絶対位...

JSON.stringify を使用する際に発生する循環参照の問題を解決する方法の詳細な説明

プログラマーが日常的に TypeScript/JavaScript 開発を行う場合、複雑な Java...

mysql8.0.18 で winx64 をインストールするための詳細なチュートリアル (画像とテキスト付き)

MySQLデータベースをダウンロードするには、https://dev.mysql.com/down...

ファイル操作のためのLinuxシステムコール

目次1. ファイルを開くパラメータの紹介2. ファイルの読み取り3. ファイルを書き込む4. 閉じる...

docker を使用して minio と java sdk を構築するプロセスの詳細な説明

目次1minioはシンプル2 Dockerビルド minio 2.1 単一ノード2.2 マルチノード...

docker コマンド例外「権限が拒否されました」の解決方法

Linuxシステムでは、dockerを新しくインストールし、次のようなコマンドを入力します。dock...

データベースインデックスの知識ポイントの概要

目次ファーストルックインデックスインデックスの概念インデックスファイルの構成インデックスの役割SQL...