您的位置:首页 > Web前端 > JavaScript

JS实现——俄罗斯方块

2015-11-07 20:48 639 查看
把以下代码保存成Tetris.html文件,使用Google或360浏览器打开

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 4.0 Transitional//EN">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta name="charset-8"/>
<title> new document </title>
</head>

<body>
<div id="space"></div>
<div id="debug" style="position:relative;top:-600px;left:330px"></div>
</body>

<script>
//定义按键
var KEY_LEFT = 37;
var KEY_RIGHT = 39;
var KEY_ROTATE = 38;
var KEY_ACCELERATE = 40;
var KEY_PAUSE = 13;
var KEY_ONE_STOP = 32;

//定义地图大小
var MAP_R = 18;
var MAP_C = 10;

//定义方块大小
var BLOCK_R = 4;
var BLOCK_C = 4;
//定义各种方块
var BLOCKS = [
//I
[
[[1,1,1,1],
[0,0,0,0],
[0,0,0,0],
[0,0,0,0]],
[[0,1,0,0],
[0,1,0,0],
[0,1,0,0],
[0,1,0,0]],
[[1,1,1,1],
[0,0,0,0],
[0,0,0,0],
[0,0,0,0]],
[[0,1,0,0],
[0,1,0,0],
[0,1,0,0],
[0,1,0,0]]
],

//L
[
[[1,0,0,0],
[1,1,1,0],
[0,0,0,0],
[0,0,0,0]],
[[1,1,0,0],
[1,0,0,0],
[1,0,0,0],
[0,0,0,0]],
[[1,1,1,0],
[0,0,1,0],
[0,0,0,0],
[0,0,0,0]],
[[1,0,0,0],
[1,0,0,0],
[1,1,0,0],
[0,0,0,0]]
],

//J
[
[[1,1,1,0],
[1,0,0,0],
[0,0,0,0],
[0,0,0,0]],
[[1,1,0,0],
[0,1,0,0],
[0,1,0,0],
[0,0,0,0]],
[[0,0,1,0],
[1,1,1,0],
[0,0,0,0],
[0,0,0,0]],
[[1,0,0,0],
[1,0,0,0],
[1,1,0,0],
[0,0,0,0]]
],

//O
[
[[0,1,1,0],
[0,1,1,0],
[0,0,0,0],
[0,0,0,0]],
[[0,1,1,0],
[0,1,1,0],
[0,0,0,0],
[0,0,0,0]],
[[0,1,1,0],
[0,1,1,0],
[0,0,0,0],
[0,0,0,0]],
[[0,1,1,0],
[0,1,1,0],
[0,0,0,0],
[0,0,0,0]]
],

//S
[
[[0,1,1,0],
[1,1,0,0],
[0,0,0,0],
[0,0,0,0]],
[[0,1,0,0],
[0,1,1,0],
[0,0,1,0],
[0,0,0,0]],
[[0,1,1,0],
[1,1,0,0],
[0,0,0,0],
[0,0,0,0]],
[[0,1,0,0],
[0,1,1,0],
[0,0,1,0],
[0,0,0,0]]
],

//T
[
[[0,1,0,0],
[1,1,1,0],
[0,0,0,0],
[0,0,0,0]],
[[0,1,0,0],
[0,1,1,0],
[0,1,0,0],
[0,0,0,0]],
[[0,0,0,0],
[1,1,1,0],
[0,1,0,0],
[0,0,0,0]],
[[0,1,0,0],
[1,1,0,0],
[0,1,0,0],
[0,0,0,0]]
],

//Z
[
[[1,1,0,0],
[0,1,1,0],
[0,0,0,0],
[0,0,0,0]],
[[0,1,0,0],
[1,1,0,0],
[1,0,0,0],
[0,0,0,0]],
[[1,1,0,0],
[0,1,1,0],
[0,0,0,0],
[0,0,0,0]],
[[0,1,0,0],
[1,1,0,0],
[1,0,0,0],
[0,0,0,0]]
]
];

var map = [];
for(var r = 0; r < MAP_R; r++) {
map.push([]);
for(var c = 0; c < MAP_C; c++) {
map[r][c] = {};
map[r][c].b = 0;
}
}

var colors = ['darkorange','darkviolet','mediumblue','red','lightseagreen','yellow','lime'];

var enableShadow = true;
var shadow = {};

var currR, currC; //方格当前在Space的左顶点位置
var currType; //当前正在落下方块的种类
var currDir = 0; //当前正在落下方块的方向
var pause = false;

//可以落下
function canFall(currR, currC) {
for(var c = 0; c < BLOCK_C; c++)
for(var r = BLOCK_R - 1; r >= 0; r--) {
if(!BLOCKS[currType][currDir][r][c])
continue;
if(currR + r + 1 > MAP_R - 1)
return false;
if(map[currR + r + 1][currC + c].b)
return false;
}
return true;
}

//找方块的投影坐标
function makeShadow() {
shadow.r = currR;
shadow.c = currC;
while(canFall(shadow.r, shadow.c)) {
shadow.r++;
}
}

//落下状态设置到map
function fall(block) {
for(var r = 0; r < BLOCK_R; r++)
for(var c = 0; c < BLOCK_C; c++)
if(BLOCKS[currType][currDir][r][c]) {
map[currR + r][currC + c].b = BLOCKS[currType][currDir][r][c];
map[currR + r][currC + c].c = currType;
}
}

//可以左移
function canLeft() {
for(var r = 0; r < BLOCK_R; r++)
for(var c = 0; c < BLOCK_C; c++) {
if(!BLOCKS[currType][currDir][r][c])
continue;
if(currC + c - 1 < 0)
return false;
if(map[currR + r][currC + c - 1].b)
return false;
}
return true;
}

//可以右移
function canRight() {
for(var r = 0; r < BLOCK_R; r++)
for(var c = BLOCK_C - 1; c >= 0; c--) {
if(!BLOCKS[currType][currDir][r][c])
continue;
if(currC + c + 1 > MAP_C - 1)
return false;
if(map[currR + r][currC + c + 1].b)
return false;
}
return true;
}

//可以旋转
function canRotate() {
return true;
}

//获得满行的行位置
function checkFullRows() {
var rows = [];
var full;
for(var r = currR; r < MAP_R; r++) {
full = true;
for(var c = 0; full && c < MAP_C; c++)
full = map[r][c].b;
if(full)
rows.push(r);
}
return rows;
}

function showPop(rows) {
for(var i = 0; i < rows.length; i++)
for(var c = 0; c < MAP_C; c++)
$(rows[i] + '-' + c).style.backgroundColor = 'transparent';
}

//在map消除指定行位置的行
function popRows(rows) {
for(var i = 0; i < rows.length; i++)
for(var r = rows[i] - 1; r >= 0; r--)
for(var c = 0; c < MAP_C; c++) {
map[r + 1][c].b = map[r][c].b;
map[r + 1][c].c = map[r][c].c;
}
}

document.onkeydown = function(event) {
var keyCode = window .event?event.keyCode:event.which;

if(keyCode == KEY_LEFT ||  keyCode == KEY_RIGHT) {
easeBlock();
if(enableShadow)
easeShadow();
if(keyCode == KEY_LEFT) {
if(canLeft())
--currC;
} else if(keyCode == KEY_RIGHT) {
if(canRight())
++currC;
}
drawBlock();
if(enableShadow) {
makeShadow();
drawShadow();
}
} else if(keyCode == KEY_ROTATE) {
if(canRotate()) {
easeBlock();
if(enableShadow)
easeShadow();
currDir = [1,2,3,0][currDir];
drawBlock();
if(enableShadow) {
makeShadow();
drawShadow();
}
}
} else if(keyCode == KEY_ACCELERATE) {
loop();
} else if(keyCode == KEY_PAUSE) {
pause = !pause;
if(pause)
clearInterval(timer);
else
timer = setInterval(loop, 300);
} else if(keyCode == KEY_ONE_STOP) {
easeBlock();
makeShadow();
currR = shadow.r;
currC = shadow.c;
drawBlock();
}

//printMapState();
}

function nextBlock() {
function randInt(n, m) {
return Math.floor(Math.random() * (m - n)) + n;
}

currR = 0;
currC = MAP_C / 2 - BLOCK_C / 2;
currType = randInt(0, BLOCKS.length);
currDir = randInt(0, 4);
}

function printMapState() {
var debug = $('debug');
var html = '';
for(var r = 0; r < MAP_R; r++) {
for(var c = 0; c < MAP_C; c++)
html += map[r][c].b;
html += '</br>';
}
debug.innerHTML = html;
}

onload = function() {
init();
nextBlock();
drawBlock();
makeShadow();
drawShadow();

timer = setInterval(loop, 300);
};

function loop() {
if(canFall(currR, currC)) {
easeBlock();
++currR;
drawBlock();
} else {
fall();
if(currR == 0) {
drawBlock();
clearInterval(timer);
alert('Game Over');
return;
}
var rows = checkFullRows();
if(rows.length > 0) {
showPop(rows);
popRows(rows);
setTimeout(function(){
drawMap();
}, 100);
}
if(enableShadow)
easeShadow();
nextBlock();
drawBlock();
if(enableShadow) {
makeShadow();
drawShadow();
}
}
}

function drawMap() {
for(var r = 0; r < MAP_R; r++)
for(var c = 0; c < MAP_C; c++) {
var div = $(r + '-' + c);
if(map[r][c].b) {
div.style.backgroundColor = colors[map[r][c].c];
} else {
div.style.backgroundColor = 'transparent';
}
}
}

function drawBlock() {
for(var r = 0; r < BLOCK_R; r++)
for(var c = 0; c < BLOCK_C; c++) {
if(BLOCKS[currType][currDir][r][c]) {
var div = $((currR + r) + '-' + (currC + c));
div.style.backgroundColor = colors[currType];
div.style.border = '1px solid ' + colors[currType];
}
}
}

function easeBlock() {
for(var r = 0; r < BLOCK_R; r++)
for(var c = 0; c < BLOCK_C; c++) {
if(BLOCKS[currType][currDir][r][c]) {
var div = $((currR + r) + '-' + (currC + c));
div.style.backgroundColor = 'transparent';
div.style.border = '1px solid ' + 'transparent';
}
}
}

function drawShadow() {
for(var r = 0; r < BLOCK_R; r++)
for(var c = 0; c < BLOCK_C; c++) {
if(BLOCKS[currType][currDir][r][c]) {
var div = $((shadow.r + r) + '-' + (shadow.c + c));
div.style.border = '1px solid blue';
}
}
}

function easeShadow() {
for(var r = 0; r < BLOCK_R; r++)
for(var c = 0; c < BLOCK_C; c++) {
if(BLOCKS[currType][currDir][r][c]) {
var div = $((shadow.r + r) + '-' + (shadow.c + c));
div.style.border = '1px solid ' + 'transparent';
}
}
}

function init() {
var size = 28;

var space = $('space');
space.style.position = 'relative';
space.style.width = size * MAP_C + (MAP_C + 1) * 3 + 1 + 'px';
space.style.height = size * MAP_R + (MAP_R + 1) * 3 + 1 + 'px';
//space.style.backgroundColor = 'lavender';
space.style.border = '2px solid black';

for(var r = 0; r < MAP_R; r++) {
for(var c = 0; c < MAP_C; c++) {
var div = document.createElement('div');
div.id = r + '-' + c;
div.style.position = 'absolute';
div.style.top = size * r + (r + 1) * 3 + 'px';
div.style.left = size * c + (c + 1) * 3 + 'px';
div.style.width = size + 'px';
div.style.height = size + 'px';
space.appendChild(div);
}
}
}

function $(id) {
return document.getElementById(id);
}
</script>
</html>


出处:qq群--编程算法&思想 459909287
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: