テトリスは非常に古典的な小さなゲームで、私もそれを書いてみました。しかし、できるだけ簡潔で論理的なコードで実装したいと思っています。落下するブロックのモデルを記録したり、落下する各ブロックの 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 にアップグレードする詳細な手順
Centos6.4 で mysql5.7.18 をインストールするための具体的な手順が全員に共有され...
1. Dockerをインストールする yumでdockerをインストール #サービスを開始する sy...
現在、新しいアプリプロジェクトを開発中です。私にとっても初めてのアプリ開発です。チームで調査と検討を...
WeChatアプレットuniappは左スワイプで削除効果を実現成果を達成する1. スワイプしてリス...
広告業は人間であることに似ていると言う人がいます。これは本当です。優れた広告には、優れた人間と同じよ...
公式ドキュメント: https://nginx.org/en/linux_packages.html...
序文元のプロジェクトは、パブリックネットワークgitlabに配置されていました。セキュリティ上の理由...
データベースでは、UNION キーワードと UNION ALL キーワードの両方が 2 つの結果セッ...
操作効果: html <!-- この要素は表示されません。DOM は JavaScript に...
今日私が書こうとしている内容では、プログラムは 7 時間近く実行され、データベースに 1,000 万...
最近、同社はitpubを皮切りに、コーポレートウェブサイト傘下の全サイトの評価を開始した。そのために...
インストールユーザーにインストール権限があることを確認してくださいルートスイッチなしsuルート(su...
最近、nginx-ingress-controller のアプリケーションについて説明した公開アカウ...
序文: Linux ホストは、エージェント プログラムをインストールする場合でも、SNMP を使用す...
シェルで変数が空かどうかを判断する方法シェルプログラミングでは、パラメータのエラーチェック項目に、変...