テトリスは非常に古典的な小さなゲームで、私もそれを書いてみました。しかし、できるだけ簡潔で論理的なコードで実装したいと思っています。落下するブロックのモデルを記録したり、落下する各ブロックの x と y を記録したりするのに、あまり多くのコードは必要ありません。次のようなアイデアについて考えてみたところ、このように書くのが非常に簡潔であることがわかりました。 テトリスには 7 つの基本モデルがあります。 これらのモデルを記録する方法は、相対位置の記録、各ブロックの x、y 座標の記録など、多数あります。これら 7 つのモデルを記録するというアイデアを思いつきました。左シフト、右シフト、回転関数を記述するときに非常に簡潔で使いやすいです。次の配列はこれらのモデルを記録します。 var cubeArr=[[6,7,12,13],[7,8,11,12],[6,7,11,12],[7,12,17,8],[7,12,16,17],[7,12,17,22],[7,11,12,13]]; アイデア:0 から始まる番号が付けられた 5*5 のテーブル。 12番の点が中心点です。各モデルはラベルとともに記録されます。たとえば、最初のモデルは [6,7,12,13] です。 表の左上隅を参照点とすると、次のような規則があります。表内の数字を値とすると、値を 5 で割った余りが参照点に対する点の x オフセットとなり、値を 5 で割った整数部分が参照点に対する点の y オフセットとなります。回転もとても簡単です。中心の12を中心に回転することで、いくつかのパターンを見つけることもできます。 var movex=cubeNow[i]%5; var movey=Math.floor(cubeNow[i]/5); ループ付きのモデルを描く 関数drawEle(color) { ctx.fillStyle=色; ctx.strokeStyle='#fff'; (var i=0;i<4;i++) の場合 { var movex=downInfor.cubeNow[i]%5; var movey=Math.floor(downInfor.cubeNow[i]/5); ctx.fillRect(cubeW*(downInfor.point[0]+movex),cubeW*(downInfor.point[1]+movey),cubeW,cubeW); ctx.strokeRect(cubeW*(downInfor.point[0]+movex),cubeW*(downInfor.point[1]+movey),cubeW,cubeW) } } モデルを回転します。 この配列を通じて、モデルを回転させることにより、現在の位置と次の回転位置の関係を簡単に実現できます。たとえば、位置が 0 で時計回りに回転する場合、次の位置は 4 になります。位置番号が 6 の場合、次の位置は 8 です。次の配列は、前の位置から次の位置を見つけることができます。 var rotateArr=[4,9,14,19,24,3,8,13,18,23,2,7,12,17,22,1,6,11,16,21,0,5,10,15,20]; コード: <!DOCTYPE html> <html lang="ja"> <ヘッド> <メタ文字セット="UTF-8"> <title>テトリス</title> </head> <本文> <div> <div style="display:inline-block"> <canvas id="can" height="480" width="300" style="border:3px solid black;"></canvas> </div> <div id="info" style="display:inline-block;height:600px;vertical-align: top;font-family: tmb; font-size:14pt; color:green;"> <span>スコア:</span><span id="score">0</span> </div> </div> <script type="text/javascript"> var キューブW = 20; var cubeArr=[[6,7,12,13],[7,8,11,12],[6,7,11,12],[7,12,17,8],[7,12,16,17],[7,12,17,22],[7,11,12,13]]; var colorArr=['#ffc0cb','#dda0dd','#9370db','#6495ed','#fa8072','#ff8c00','#008000']; var rotateArr=[4,9,14,19,24,3,8,13,18,23,2,7,12,17,22,1,6,11,16,21,0,5,10,15,20]; var キャンバス = document.getElementById('can'); var ctx = canvas.getContext('2d'); var スコア = document.getElementById('スコア'); var canWidth=canvas.width; var canHeight=canvas.height; var downInfor = {}、staticCube = []; var myinter; window.initialize = function() //初期化{ 線を引く(); (var i=0;i<(canWidth/cubeW);i++) の場合 { 静的キューブ[i] = []; (var j=0;j<(canHeight/cubeW);j++) の場合 { 静的キューブ[i][j] = 0; } } Cube を初期化します。 myinter=setInterval('movedown()',200); //最初のパラメータは引用符で囲む必要があります} 関数drawline() { ctx.lineWidth=1; ctx.strokeStyle='#ddd'; (var i=0;i<(canWidth/cubeW);i++) の場合 { ctx.moveTo(キューブW*i,0); ctx.lineTo(cubeW*i,canHeight); } ctx.stroke(); (var j=0;j<(canHeight/cubeW);j++) の場合 { ctx.moveTo(0,cubeW*j); ctx.lineTo(canHeight,cubeW*j); } ctx.stroke(); } 関数 initCube() { var index=Math.floor(Math.random()*cubeArr.length);//ランダムに生成 downInfor.cubeNow=cubeArr[index].concat(); downInfor.index=インデックス; downInfor.prepoint=[5,-1]; ダウンインフォメーションポイント=[5,-1]; 要素を描画します(colorArr[downInfor.index]); } 関数movedown() { //次の位置が妥当かどうかを判断しますvar length,isempty=true,px,py,movex,movey,max=0; (var i=0;i<4;i++) の場合 { 最大値<downInfor.cubeNow[i]の場合 最大値 = downInfor.cubeNow[i]; } 長さ=Math.ceil(max/5); (var i=0;i<4;i++) の場合 { px=downInfor.point[0]+downInfor.cubeNow[i]%5; py=downInfor.point[1]+1+Math.floor(downInfor.cubeNow[i]/5); 静的キューブ[px][py]==1の場合 { isempty=false; 壊す; } } if((downInfor.point[1]+length)<(canHeight/cubeW)&&isempty) { downInfor.prepoint=downInfor.point.concat(); //参照型に注意してください downInfor.point[1]=downInfor.point[1]+1; クリアエレメント(); 要素を描画します(colorArr[downInfor.index]); } else // 移動できない場合 { (var i=0;i<4;i++) の場合 { px=downInfor.point[0]+downInfor.cubeNow[i]%5; py=downInfor.point[1]+Math.floor(downInfor.cubeNow[i]/5); 静的キューブ[px][py]=1; } 描画エレメント('#555') チェックフルライン(); } } 関数moveLeft() { var leftroom=4,isempty=true,px,py,movex,movey; (var i=0;i<4;i++) の場合 { px=downInfor.point[0]-1+downInfor.cubeNow[i]%5; py=downInfor.point[1]+Math.floor(downInfor.cubeNow[i]/5); if((downInfor.cubeNow[i]%5)<leftroom) 左の部屋=downInfor.cubeNow[i]%5; 静的キューブ[px][py]==1の場合 { isempty=false; 壊す; } } if((downInfor.point[0]+leftroom)>=0&&isempty) { downInfor.prepoint=downInfor.point.concat(); ダウンインフォメーションポイント[0]=ダウンインフォメーションポイント[0]-1; クリアエレメント(); 要素を描画します(colorArr[downInfor.index]); } } 関数moveRight() { var rightroom=0,isempty=true,px,py,movex,movey; (var i=0;i<4;i++) の場合 { px=downInfor.point[0]+1+downInfor.cubeNow[i]%5; py=downInfor.point[1]+Math.floor(downInfor.cubeNow[i]/5); if((downInfor.cubeNow[i]%5)>右の部屋) 右の部屋=downInfor.cubeNow[i]%5; 静的キューブ[px][py]==1の場合 { isempty=false; 壊す; } } if((downInfor.point[0]+rightroom+1)<(canWidth/cubeW)&&isempty) { downInfor.prepoint=downInfor.point.concat(); ダウンインフォメーションポイント[0]=ダウンインフォメーションポイント[0]+1; クリアエレメント(); 要素を描画します(colorArr[downInfor.index]); } } function moverotate()//回転処理 { var isempty=true,px,py,movex,movey, tempRotate=[0,0,0,0]; (var i=0;i<4;i++) の場合 { tempRotate[i] = rotateArr[downInfor.cubeNow[i]]; } (var i=0;i<4;i++) の場合 { px=downInfor.point[0]+tempRotate[i]%3; py=downInfor.point[1]+Math.floor(tempRotate[i]/3); 静的キューブ[px][py]==1の場合 { isempty=false; 壊す; } } if(空) { downInfor.prepoint=downInfor.point.concat(); クリアエレメント(); downInfor.cubeNow = tempRotate.concat(); 要素を描画します(colorArr[downInfor.index]); } } 関数drawEle(color) { ctx.fillStyle=色; ctx.strokeStyle='#fff'; (var i=0;i<4;i++) の場合 { var movex=downInfor.cubeNow[i]%5; var movey=Math.floor(downInfor.cubeNow[i]/5); ctx.fillRect(cubeW*(downInfor.point[0]+movex),cubeW*(downInfor.point[1]+movey),cubeW,cubeW); ctx.strokeRect(cubeW*(downInfor.point[0]+movex),cubeW*(downInfor.point[1]+movey),cubeW,cubeW) } } 関数 clearEle() { ctx.lineWidth=1; ctx.strokeStyle='#ddd'; (var i=0;i<4;i++) の場合 { var movex=downInfor.cubeNow[i]%5; var movey=Math.floor(downInfor.cubeNow[i]/5); ctx.clearRect(cubeW*(downInfor.prepoint[0]+movex),cubeW*(downInfor.prepoint[1]+movey),cubeW,cubeW); ctx.strokeRect(cubeW*(downInfor.prepoint[0]+movex),cubeW*(downInfor.prepoint[1]+movey),cubeW,cubeW) } } function checkfullLine()// 行が完全かどうかをチェックする { var isFullLine=true、index=0、changeScore=false; for(var i=0;i<canWidth/cubeW;i++) { 静的キューブ[i][0]==1の場合 { alert('ゲームオーバー!'); クリア間隔(myinterval); 戻る; } } (var i=canHeight/cubeW-1;i>=0;i--) の場合 { フルラインかどうかをチェックします。 (var j=0;j<(canWidth/cubeW);j++) の場合 { 静的キューブ[j][i]==0の場合 { isFullLine = false; } } if(isFullLine)// 1点追加 { score.innerHTML = parseInt(score.innerText) + 1; スコアを変更します。 (var s=i;s>=0;s--) { (var j = 0; j < (canWidth / cubeW); j++) { (s- 1) >= 0 ? staticCube[j][s] = staticCube[j][s - 1] : staticCube[j][s] = 0; } } } } if(スコア変更) { ctx.clearRect(0,0,canWidth,canHeight); 線を引く(); ctx.fillStyle='555'; ctx.strokeStyle='#fff'; (var i=0;i<(canWidth/cubeW);i++) の場合 { (var j=0;j<(canHeight/cubeW);j++) の場合 { 静的キューブ[i][j]==1の場合 { ctx.fillRect(cubeW*i,cubeW*j,cubeW,cubeW); ctx.strokeRect(cubeW*i,cubeW*j,cubeW,cubeW); } } } } Cube を初期化します。 } window.onkeydown=関数 (evt) { スイッチ(evt.keyCode) { ケース 37: //leftmoveLeft(); 壊す; ケース 38: //moverotate(); 壊す; ケース 39: //右へ moveRight(); 壊す; ケース 40: //movedown(); 壊す; } } </スクリプト> </本文> </html> 効果: 以上がこの記事の全内容です。皆様の勉強のお役に立てれば幸いです。また、123WORDPRESS.COM を応援していただければ幸いです。 以下もご興味があるかもしれません:
|
<<: Docker ベースの MySQL マスタースレーブレプリケーション環境を構築するための実装手順
>>: win2008 で mysql8.0.11 を mysql8.0.17 にアップグレードする詳細な手順
FRAME プロパティを使用して、表の境界線のスタイル タイプを制御します。基本的な構文<T...
フロントエンドとバックエンドを分離し、nginxを使用してクロスドメインの問題を解決するフロントエン...
目次背景メインコンテンツ1. コンポーネントの比較2. 実装のアイデア3. キーメソッドソースコード...
注意: 計画、設計、開発のいずれの場合でも、これらの間違いは避けなければなりません。 1. ナビゲー...
1.インストールしたい場所に解凍し、my.iniファイルを作成します。 my.iniの内容は次のと...
目次概要機能性と読みやすさ空白括弧セミコロンインデント身元大文字と小文字を区別予約キーワード概要すべ...
最近、 Ubuntu 20.04でkazamを使用して録音しているときに、問題が見つかりました。シス...
目次背景なぜエラー処理が必要なのでしょうか? async await より適切なエラー処理まとめ要約...
目次序文分析するデータ合計繰り返し率どこにあるかと持っているかの違い要約する序文私はソフトウェアの導...
この記事では、IDEA が MySQL データベースに接続できない問題に対する 6 つの解決策を主に...
(I)ウェブページのカラーマッチングの基本概念(1)白黒の言葉は永遠のテーマです。誰もそれを悪く言う...
フロートはWebページのレイアウトでよく使用されますが、フローティングブロックレベル要素は標準のドキ...
目次序文1. システムサービス制御1. システムctl 2. ターゲット3. 共通システムサービス4...
更新: MySQL の公式 Web サイトにアクセスして MySQL インストーラーをインストールし...
1. 公式ウェブサイトアドレス公式サイトではインストールの参考手順が紹介されています。公式サイトを見...