转点关于俄罗斯方块的文章
[ 2008-06-19 17:27:37 | 作者: blueice ]
C++是游戏编程的首选语言,但我相信C++能做到的C#也能做到。
本篇介绍用C#编写一个俄罗斯方块程序的原理,以及在C#里面播放声音,保存游戏设置的方法。
游戏界面预览:
菜单预览:
自定义每个小方块颜色功能界面:
游戏主要有四部分组成:Square类,Block类,gameField类,游戏引擎
Square类:
这个类描述的对象是组成大方块中的每个小正方形实体。
类设计:
class Square
{
public Point location; //小方块的坐标
public Size size; //小方块大小
public Color foreColor; //小方块前景色
public Color backColor; //小方块背景色
public Square(Size initSize,Color initForeColor,Color initBackColor) //构造函数
{ ……}
public void Draw(System.IntPtr winHandle) //在指定设备上画方块
{ …… }
public void Erase(System.IntPtr winHandle)//擦除方块
{ …… }
}
Block类:
这个类描述的对象是某一个大方块的实体。每个大方块由四个小正方形组成,一共有7种组合方式。这个类需要实现一个大方块实体所有的属性和动作。包括:方块的形状,位置,方块左移,右移,下移,旋转等。
类设计:
class Block
{
public Square square1; //组成block的四个小方块
public Square square2;
public Square square3;
public Square square4;
private const int squareSize = GameField.SquareSize; //小方块的边长
public enum BlockTypes
{
undefined = 0,
square = 1,
line = 2,
J = 3,
L = 4,
T = 5,
Z = 6,
S = 7
};//一共有7种形状
public BlockTypes blockType; //方块的形状
//七个小方块的颜色数组
private Color foreColor;
private Color backColor;
//方块的方向
public enum RotateDirections
{
North = 1,
East = 2,
South = 3,
West = 4
};
public RotateDirections myRotation = RotateDirections.North;
public Block(Point thisLocation,BlockTypes bType)
{ ……}
//含有自定义颜色的重载
public Block(Point thisLocation, BlockTypes bType,Color fc,Color bc)
{ ……}
/*画方块*/
public void Draw(System.IntPtr winHandle)
{…… }
/*擦方块*/
public void Erase(System.IntPtr winHandle)
{…… }
/*移动*/
public bool down()
{……}
public bool left()
{……}
public bool right()
{……}
/*旋转block*/
public void Rotate()
{……}
/*检测是否到顶*/
public int Top()
{……}
}
GameField类:
这个类描述的对象是游戏场景实体,包括场景的背景色,大小,方块是否还可以移动,以及场景中填满一行的检测等。
类设计:
class GameField
{
public const int width = 20; //场景的宽,以方块个数为单位
public const int height = 30;
public const int SquareSize = 15; //每个四分之一小方块的边长
public static Color BackColor; //场景的背景色
public static System.IntPtr winHandle; //场景的handle
public static Color[] BlockForeColor ={ Color.Blue, Color.Beige, Color.DarkKhaki, Color.DarkMagenta, Color.DarkOliveGreen, Color.DarkOrange, Color.DarkRed };
public static Color[] BlockBackColor ={ Color.LightCyan, Color.DarkSeaGreen, Color.Beige, Color.Beige, Color.Beige, Color.Beige, Color.Beige };
public static bool isChanged=false; //设置是否被更改的标志位
public static SoundPlayer sound = new SoundPlayer(); //播放声音
public static Square[,] arriveBlock = new Square[width, height]; //保存已经不能再下落了的方块
public static int[] arrBitBlock=new int[height]; //位数组:当某个位置有方块时,该行的该位为1
private const int bitEmpty = 0x0; //0000 0000 0000 0000 0000
private const int bitFull = 0xFFFFF; //1111 1111 1111 1111 1111
/*检测某个位置是否为空*/
public static bool isEmpty(int x, int y)
{……}
/*将方块停住*/
public static void stopSquare(Square sq, int x, int y)
{……}
/*检测行是否满
* 返回:成功消除的行数和 (方便统计分数)
*/
public static int CheckLines()
{ ……}
/*播放声音*/
public static void PlaySound(string soundstr)
{……}
/*重画*/
public static void Redraw()
{ …… }
//结束
}
游戏引擎:
游戏引擎正如其名,就像一个发动机一样让游戏不间断运行。本游戏中就是让方块以一定的速度下落。并响应键盘事件,实行左右移动,和向下加速功能。(代码见源码)
声音播放:
音效是游戏不可缺少的一部分。在.Net2.0中已经提供了一个类来播放声音。在using System.Media;命名空间。
本游戏中播放声音的代码如下:(在 GameField类中)
using System.Media;
public static SoundPlayer sound = new SoundPlayer();
/*播放声音*/
public static void PlaySound(string soundstr)
{
switch (soundstr)
{
case "FinishOneLine": //消除一行的声音
if (!File.Exists("FinishOneLine.wav")) return;
sound.SoundLocation = "FinishOneLine.wav";
break;
case "CanNotDo": //当无法操作时
if (!File.Exists("CanNotDo.wav")) return;
sound.SoundLocation = "CanNotDo.wav";
break;
}
sound.Play();
}
要播放的时候调用PlaySound()方法即可。
其实步骤很简单,先引用System.Media空间,然后创建一个SoundPlayer 对象,用SoundLocation 属性设置声音文件的地址,然后调用Play()方法即可播放。不过注意,这个类可以播放的声音格式只有Wav文件。
保存游戏设置:
在游戏中经常要保存用户自定义的设置。本游戏通过写进ini文件来保存。
主要代码如:
/*加载窗体时从配置文件Setting.ini中读取游戏设置*/
private void getSettings()
{
if (!File.Exists("Setting.ini"))
return;
FileStream fs = new FileStream("Setting.ini", FileMode.OpenOrCreate, FileAccess.ReadWrite);
StreamReader sr = new StreamReader(fs);
string line1=sr.ReadLine();
string line2=sr.ReadLine();
string line3=sr.ReadLine();
if (line1 != null && line1.Split('=').Length > 1)
{
GameField.BackColor = Color.FromArgb(int.Parse(line1.Split('=')[1]));
picBackGround.BackColor = GameField.BackColor;
}
if (line2 != null && line2.Split('=').Length > 1)
GameField.BlockForeColor = strToColor(line2.Split('=')[1]);
if (line3 != null && line3.Split('=').Length > 1)
GameField.BlockBackColor = strToColor(line3.Split('=')[1]);
sr.Close();
fs.Close();
}
/*如果游戏设置被更改,将新的设置保存到Setting.ini*/
private void saveSettings()
{
FileStream fs = new FileStream("Setting.ini", FileMode.Create, FileAccess.ReadWrite);
StreamWriter sw = new StreamWriter(fs);
sw.WriteLine("GameFieldColor="+GameField.BackColor.ToArgb());
sw.WriteLine("BlockFroeColor=" + colorToStr(GameField.BlockForeColor));
sw.WriteLine("BlockBackColor=" + colorToStr(GameField.BlockBackColor));
sw.Flush();
sw.Close();
fs.Close();
}
麻雀虽小,五脏俱全,了解更多请看源码。
游戏源码下载: CODE
源文地址:http://www.cnblogs.com/tuyile006/archive/2007/05/16/748256.html
另有一个js版的俄罗斯方块
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE> 俄罗斯方块</TITLE>
<META NAME="Generator" CONTENT="EditPlus">
<META NAME="Author" CONTENT="">
<META NAME="Keywords" CONTENT="">
<META NAME="Description" CONTENT="">
<style>
span.btn
{
BORDER-RIGHT: #7b9ebd 1px solid; PADDING-RIGHT: 2px; BORDER-TOP: #7b9ebd 1px solid; PADDING-LEFT: 2px; FONT-SIZE: 12px; FILTER: progid:DXImageTransform.Microsoft.Gradient(GradientType=0, StartColorStr=#ffffff, EndColorStr=#cecfde); BORDER-LEFT: #7b9ebd 1px solid; CURSOR: hand; COLOR: black; PADDING-TOP: 2px; BORDER-BOTTOM: #7b9ebd 1px solid
}
</style>
<script language=javascript>
var grid=
[
[1,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,1],
[1,1,1,1,1,1,1,1,1,1,1]
];
var gridBuf=
[
[1,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,1],
[1,1,1,1,1,1,1,1,1,1,1]
];
var boxdata=
[
[
[1,1,1,1],
[0,0,0,0],
[0,0,0,0],
[0,0,0,0]
],
[
[1,1,1,0],
[1,0,0,0],
[0,0,0,0],
[0,0,0,0],
],
[
[1,1,1,0],
[0,1,0,0],
[0,0,0,0],
[0,0,0,0]
],
[
[1,1,1,0],
[0,0,1,0],
[0,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,1,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]
]
];
var colors=["black","#A0A0A0","red","green","yellow","pink"];
var gotLine=0;
var box;
var bGameOver=false;
function getHeight(arr)
{
var i,j;
for(i=3;i>=0;i--)
for(j=0;j<4;j++)
if(arr[i][j]) return i;
}
function getWidth(arr)
{
var i,j;
for(i=3;i>=0;i--)
for(j=0;j<4;j++)
if(arr[j][i]) return i;
}
function Box(x,y,arr,color)
{
this.arr=arr;
this.x=x;
this.y=y;
this.w=getWidth(arr);
this.h=getHeight(arr);
this.color=color;
this.active=true;
this.clearOldBox=function()
{
for(var j=0;j<=this.h;j++)
for(var i=0;i<=this.w;i++)
if(this.arr[j][i]>0) grid[this.y+j][this.x+i]=0;
}
this.putNewBox=function()
{
for(var j=0;j<=this.h;j++)
for(var i=0;i<=this.w;i++)
if(this.arr[j][i]>0) grid[this.y+j][this.x+i]=this.color;
}
this.moveLeft=function()
{
this.clearOldBox();
var _x=this.x-1;
if(this.canMove(_x,this.y)) this.x=_x;
this.putNewBox();
drawGrid();
}
this.moveRight=function()
{
this.clearOldBox();
var _x=this.x+1;
if(this.canMove(_x,this.y)) this.x=_x;
this.putNewBox();
drawGrid();
}
this.moveDown=function()
{
this.clearOldBox();
var _y=this.y+1;
if(this.canMove(this.x,_y))
{
this.y=_y;
this.putNewBox();
drawGrid();
}
else
{
this.putNewBox();
drawGrid();
checkLineFull();
return;
}
}
this.rotate=function()
{
var tmp=[[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]];
for(j=0;j<=this.h;j++)
for(i=0;i<=this.w;i++)
tmp[this.w-i][j]=this.arr[j][i];
var newBox=new Box(this.x,this.y,tmp,this.color);
this.clearOldBox();
if(! newBox.canMove(this.x,this.y)) this.putNewBox();
else
{
box=newBox;
box.putNewBox();
drawGrid();
}
}
this.canMove=function(x,y)
{
for(var j=0;j<=this.h;j++)
for(var i=0;i<=this.w;i++)
{
if(grid[y+j][x+i]!=0 && this.arr[j][i]!=0){ return false; }
}
return true;
}
}
function drawGrid()
{
for(var j=0;j<=15;j++)
for(var i=0;i<=10;i++)
{
if( grid[j][i]!=gridBuf[j][i])
{
paintCell(j,i,grid[j][i]);
}
gridBuf[j][i]=grid[j][i];
}
}
function paintCell(i,j,color)
{
var htmlGrid=document.getElementById("TetrisGrid").firstChild;
htmlGrid.childNodes[i].childNodes[j].style.backgroundColor=colors[color];
}
function init()
{
var html='<table id="TetrisGrid" cellspacing=1 style="background-color:green"><tbody>';
for(var i=0;i<=15;i++)
{
html+='<tr>';
for(var j=0;j<=10;j++)
{
html+='<td width="20" height="20" style="background-color:'+colors[grid[i][j]]+';"></td>';
}
html+='</tr> \r\n';
}
html+='</tbody></table>';
document.write(html);
}
function checkLineFull()
{
var full,i,j,i2;
var y3=box.y+box.h;
var y4=box.y;
for(i=y3;i>=y4;)
{
full=1;
for(j=1;j<10;j++)
if(grid[i][j]==0){full=0; break;}
if(full==0){ --i; continue;}
for(i2=i; i2>0;i2--)
for(j=1;j<10;j++)
grid[i2][j]=grid[i2-1][j];
drawGrid();
y4++;
gotLine++;
}
checkGameOver();
}
function checkGameOver()
{
var bOver=false;
for(var j=1;j<10;j++)
if(grid[1][j]>0){ bOver=true; break;}
if(!bOver){
box=new Box(1,1,boxdata[Math.floor(Math.random()*7)],Math.floor(Math.random()*5)+1);
box.putNewBox();
}
else
{
bGameOver=true;
msg.innerHTML="游戏结束! 您的得分为"+gotLine*100;
window.clearInterval();
}
}
function document_onkeydown()
{
if(bGameOver) return;
switch(event.keyCode)
{
case 37:
box.moveLeft();
break;
case 39:
box.moveRight();
break;
case 38:
box.rotate();
break;
case 40:
box.moveDown();
break;
}
}
function moveDownBox()
{
var interval=1000-10*(gotLine>80?80 :gotLine);
msg.innerHTML="等级:"+Math.floor(gotLine/10)+" 得分:"+gotLine*100;
box.moveDown();
window.setTimeout('moveDownBox()',interval);
}
function startGame()
{
init();
window.setTimeout('moveDownBox()',1000);
bGameOver=false;
box=new Box(1,1,boxdata[Math.floor(Math.random()*7)],Math.floor(Math.random()*5)+1);
box.putNewBox();
drawGrid();
}
</script>
<SCRIPT LANGUAGE=javascript FOR=document EVENT=onkeydown>
<!--
if (document.all)document_onkeydown()
//-->
</SCRIPT>
</HEAD>
<BODY LANGUAGE=javascript onLoad="window.focus()">
<span class="btn" style="width:254;background-color:#F0C0C0;color:#0000FF;text-align:center">sunnisdu 山东大学 <a href="javascript:window.location.reload();">开始</a></span><br/>
<span style="background-color:black;width:22"></span><span id="msg" style="width:232;background-color:black;color:#00FF00;">俄罗斯方块</span>
<script language=javascript>
startGame();
</script>
</BODY>
</HTML>
评论Feed: http://www.elfnest.com/blog/feed.asp?q=comment&id=162
本篇介绍用C#编写一个俄罗斯方块程序的原理,以及在C#里面播放声音,保存游戏设置的方法。
游戏界面预览:
菜单预览:
自定义每个小方块颜色功能界面:
游戏主要有四部分组成:Square类,Block类,gameField类,游戏引擎
Square类:
这个类描述的对象是组成大方块中的每个小正方形实体。
类设计:
class Square
{
public Point location; //小方块的坐标
public Size size; //小方块大小
public Color foreColor; //小方块前景色
public Color backColor; //小方块背景色
public Square(Size initSize,Color initForeColor,Color initBackColor) //构造函数
{ ……}
public void Draw(System.IntPtr winHandle) //在指定设备上画方块
{ …… }
public void Erase(System.IntPtr winHandle)//擦除方块
{ …… }
}
Block类:
这个类描述的对象是某一个大方块的实体。每个大方块由四个小正方形组成,一共有7种组合方式。这个类需要实现一个大方块实体所有的属性和动作。包括:方块的形状,位置,方块左移,右移,下移,旋转等。
类设计:
class Block
{
public Square square1; //组成block的四个小方块
public Square square2;
public Square square3;
public Square square4;
private const int squareSize = GameField.SquareSize; //小方块的边长
public enum BlockTypes
{
undefined = 0,
square = 1,
line = 2,
J = 3,
L = 4,
T = 5,
Z = 6,
S = 7
};//一共有7种形状
public BlockTypes blockType; //方块的形状
//七个小方块的颜色数组
private Color foreColor;
private Color backColor;
//方块的方向
public enum RotateDirections
{
North = 1,
East = 2,
South = 3,
West = 4
};
public RotateDirections myRotation = RotateDirections.North;
public Block(Point thisLocation,BlockTypes bType)
{ ……}
//含有自定义颜色的重载
public Block(Point thisLocation, BlockTypes bType,Color fc,Color bc)
{ ……}
/*画方块*/
public void Draw(System.IntPtr winHandle)
{…… }
/*擦方块*/
public void Erase(System.IntPtr winHandle)
{…… }
/*移动*/
public bool down()
{……}
public bool left()
{……}
public bool right()
{……}
/*旋转block*/
public void Rotate()
{……}
/*检测是否到顶*/
public int Top()
{……}
}
GameField类:
这个类描述的对象是游戏场景实体,包括场景的背景色,大小,方块是否还可以移动,以及场景中填满一行的检测等。
类设计:
class GameField
{
public const int width = 20; //场景的宽,以方块个数为单位
public const int height = 30;
public const int SquareSize = 15; //每个四分之一小方块的边长
public static Color BackColor; //场景的背景色
public static System.IntPtr winHandle; //场景的handle
public static Color[] BlockForeColor ={ Color.Blue, Color.Beige, Color.DarkKhaki, Color.DarkMagenta, Color.DarkOliveGreen, Color.DarkOrange, Color.DarkRed };
public static Color[] BlockBackColor ={ Color.LightCyan, Color.DarkSeaGreen, Color.Beige, Color.Beige, Color.Beige, Color.Beige, Color.Beige };
public static bool isChanged=false; //设置是否被更改的标志位
public static SoundPlayer sound = new SoundPlayer(); //播放声音
public static Square[,] arriveBlock = new Square[width, height]; //保存已经不能再下落了的方块
public static int[] arrBitBlock=new int[height]; //位数组:当某个位置有方块时,该行的该位为1
private const int bitEmpty = 0x0; //0000 0000 0000 0000 0000
private const int bitFull = 0xFFFFF; //1111 1111 1111 1111 1111
/*检测某个位置是否为空*/
public static bool isEmpty(int x, int y)
{……}
/*将方块停住*/
public static void stopSquare(Square sq, int x, int y)
{……}
/*检测行是否满
* 返回:成功消除的行数和 (方便统计分数)
*/
public static int CheckLines()
{ ……}
/*播放声音*/
public static void PlaySound(string soundstr)
{……}
/*重画*/
public static void Redraw()
{ …… }
//结束
}
游戏引擎:
游戏引擎正如其名,就像一个发动机一样让游戏不间断运行。本游戏中就是让方块以一定的速度下落。并响应键盘事件,实行左右移动,和向下加速功能。(代码见源码)
声音播放:
音效是游戏不可缺少的一部分。在.Net2.0中已经提供了一个类来播放声音。在using System.Media;命名空间。
本游戏中播放声音的代码如下:(在 GameField类中)
using System.Media;
public static SoundPlayer sound = new SoundPlayer();
/*播放声音*/
public static void PlaySound(string soundstr)
{
switch (soundstr)
{
case "FinishOneLine": //消除一行的声音
if (!File.Exists("FinishOneLine.wav")) return;
sound.SoundLocation = "FinishOneLine.wav";
break;
case "CanNotDo": //当无法操作时
if (!File.Exists("CanNotDo.wav")) return;
sound.SoundLocation = "CanNotDo.wav";
break;
}
sound.Play();
}
要播放的时候调用PlaySound()方法即可。
其实步骤很简单,先引用System.Media空间,然后创建一个SoundPlayer 对象,用SoundLocation 属性设置声音文件的地址,然后调用Play()方法即可播放。不过注意,这个类可以播放的声音格式只有Wav文件。
保存游戏设置:
在游戏中经常要保存用户自定义的设置。本游戏通过写进ini文件来保存。
主要代码如:
/*加载窗体时从配置文件Setting.ini中读取游戏设置*/
private void getSettings()
{
if (!File.Exists("Setting.ini"))
return;
FileStream fs = new FileStream("Setting.ini", FileMode.OpenOrCreate, FileAccess.ReadWrite);
StreamReader sr = new StreamReader(fs);
string line1=sr.ReadLine();
string line2=sr.ReadLine();
string line3=sr.ReadLine();
if (line1 != null && line1.Split('=').Length > 1)
{
GameField.BackColor = Color.FromArgb(int.Parse(line1.Split('=')[1]));
picBackGround.BackColor = GameField.BackColor;
}
if (line2 != null && line2.Split('=').Length > 1)
GameField.BlockForeColor = strToColor(line2.Split('=')[1]);
if (line3 != null && line3.Split('=').Length > 1)
GameField.BlockBackColor = strToColor(line3.Split('=')[1]);
sr.Close();
fs.Close();
}
/*如果游戏设置被更改,将新的设置保存到Setting.ini*/
private void saveSettings()
{
FileStream fs = new FileStream("Setting.ini", FileMode.Create, FileAccess.ReadWrite);
StreamWriter sw = new StreamWriter(fs);
sw.WriteLine("GameFieldColor="+GameField.BackColor.ToArgb());
sw.WriteLine("BlockFroeColor=" + colorToStr(GameField.BlockForeColor));
sw.WriteLine("BlockBackColor=" + colorToStr(GameField.BlockBackColor));
sw.Flush();
sw.Close();
fs.Close();
}
麻雀虽小,五脏俱全,了解更多请看源码。
游戏源码下载: CODE
源文地址:http://www.cnblogs.com/tuyile006/archive/2007/05/16/748256.html
另有一个js版的俄罗斯方块
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE> 俄罗斯方块</TITLE>
<META NAME="Generator" CONTENT="EditPlus">
<META NAME="Author" CONTENT="">
<META NAME="Keywords" CONTENT="">
<META NAME="Description" CONTENT="">
<style>
span.btn
{
BORDER-RIGHT: #7b9ebd 1px solid; PADDING-RIGHT: 2px; BORDER-TOP: #7b9ebd 1px solid; PADDING-LEFT: 2px; FONT-SIZE: 12px; FILTER: progid:DXImageTransform.Microsoft.Gradient(GradientType=0, StartColorStr=#ffffff, EndColorStr=#cecfde); BORDER-LEFT: #7b9ebd 1px solid; CURSOR: hand; COLOR: black; PADDING-TOP: 2px; BORDER-BOTTOM: #7b9ebd 1px solid
}
</style>
<script language=javascript>
var grid=
[
[1,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,1],
[1,1,1,1,1,1,1,1,1,1,1]
];
var gridBuf=
[
[1,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,1],
[1,1,1,1,1,1,1,1,1,1,1]
];
var boxdata=
[
[
[1,1,1,1],
[0,0,0,0],
[0,0,0,0],
[0,0,0,0]
],
[
[1,1,1,0],
[1,0,0,0],
[0,0,0,0],
[0,0,0,0],
],
[
[1,1,1,0],
[0,1,0,0],
[0,0,0,0],
[0,0,0,0]
],
[
[1,1,1,0],
[0,0,1,0],
[0,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,1,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]
]
];
var colors=["black","#A0A0A0","red","green","yellow","pink"];
var gotLine=0;
var box;
var bGameOver=false;
function getHeight(arr)
{
var i,j;
for(i=3;i>=0;i--)
for(j=0;j<4;j++)
if(arr[i][j]) return i;
}
function getWidth(arr)
{
var i,j;
for(i=3;i>=0;i--)
for(j=0;j<4;j++)
if(arr[j][i]) return i;
}
function Box(x,y,arr,color)
{
this.arr=arr;
this.x=x;
this.y=y;
this.w=getWidth(arr);
this.h=getHeight(arr);
this.color=color;
this.active=true;
this.clearOldBox=function()
{
for(var j=0;j<=this.h;j++)
for(var i=0;i<=this.w;i++)
if(this.arr[j][i]>0) grid[this.y+j][this.x+i]=0;
}
this.putNewBox=function()
{
for(var j=0;j<=this.h;j++)
for(var i=0;i<=this.w;i++)
if(this.arr[j][i]>0) grid[this.y+j][this.x+i]=this.color;
}
this.moveLeft=function()
{
this.clearOldBox();
var _x=this.x-1;
if(this.canMove(_x,this.y)) this.x=_x;
this.putNewBox();
drawGrid();
}
this.moveRight=function()
{
this.clearOldBox();
var _x=this.x+1;
if(this.canMove(_x,this.y)) this.x=_x;
this.putNewBox();
drawGrid();
}
this.moveDown=function()
{
this.clearOldBox();
var _y=this.y+1;
if(this.canMove(this.x,_y))
{
this.y=_y;
this.putNewBox();
drawGrid();
}
else
{
this.putNewBox();
drawGrid();
checkLineFull();
return;
}
}
this.rotate=function()
{
var tmp=[[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]];
for(j=0;j<=this.h;j++)
for(i=0;i<=this.w;i++)
tmp[this.w-i][j]=this.arr[j][i];
var newBox=new Box(this.x,this.y,tmp,this.color);
this.clearOldBox();
if(! newBox.canMove(this.x,this.y)) this.putNewBox();
else
{
box=newBox;
box.putNewBox();
drawGrid();
}
}
this.canMove=function(x,y)
{
for(var j=0;j<=this.h;j++)
for(var i=0;i<=this.w;i++)
{
if(grid[y+j][x+i]!=0 && this.arr[j][i]!=0){ return false; }
}
return true;
}
}
function drawGrid()
{
for(var j=0;j<=15;j++)
for(var i=0;i<=10;i++)
{
if( grid[j][i]!=gridBuf[j][i])
{
paintCell(j,i,grid[j][i]);
}
gridBuf[j][i]=grid[j][i];
}
}
function paintCell(i,j,color)
{
var htmlGrid=document.getElementById("TetrisGrid").firstChild;
htmlGrid.childNodes[i].childNodes[j].style.backgroundColor=colors[color];
}
function init()
{
var html='<table id="TetrisGrid" cellspacing=1 style="background-color:green"><tbody>';
for(var i=0;i<=15;i++)
{
html+='<tr>';
for(var j=0;j<=10;j++)
{
html+='<td width="20" height="20" style="background-color:'+colors[grid[i][j]]+';"></td>';
}
html+='</tr> \r\n';
}
html+='</tbody></table>';
document.write(html);
}
function checkLineFull()
{
var full,i,j,i2;
var y3=box.y+box.h;
var y4=box.y;
for(i=y3;i>=y4;)
{
full=1;
for(j=1;j<10;j++)
if(grid[i][j]==0){full=0; break;}
if(full==0){ --i; continue;}
for(i2=i; i2>0;i2--)
for(j=1;j<10;j++)
grid[i2][j]=grid[i2-1][j];
drawGrid();
y4++;
gotLine++;
}
checkGameOver();
}
function checkGameOver()
{
var bOver=false;
for(var j=1;j<10;j++)
if(grid[1][j]>0){ bOver=true; break;}
if(!bOver){
box=new Box(1,1,boxdata[Math.floor(Math.random()*7)],Math.floor(Math.random()*5)+1);
box.putNewBox();
}
else
{
bGameOver=true;
msg.innerHTML="游戏结束! 您的得分为"+gotLine*100;
window.clearInterval();
}
}
function document_onkeydown()
{
if(bGameOver) return;
switch(event.keyCode)
{
case 37:
box.moveLeft();
break;
case 39:
box.moveRight();
break;
case 38:
box.rotate();
break;
case 40:
box.moveDown();
break;
}
}
function moveDownBox()
{
var interval=1000-10*(gotLine>80?80 :gotLine);
msg.innerHTML="等级:"+Math.floor(gotLine/10)+" 得分:"+gotLine*100;
box.moveDown();
window.setTimeout('moveDownBox()',interval);
}
function startGame()
{
init();
window.setTimeout('moveDownBox()',1000);
bGameOver=false;
box=new Box(1,1,boxdata[Math.floor(Math.random()*7)],Math.floor(Math.random()*5)+1);
box.putNewBox();
drawGrid();
}
</script>
<SCRIPT LANGUAGE=javascript FOR=document EVENT=onkeydown>
<!--
if (document.all)document_onkeydown()
//-->
</SCRIPT>
</HEAD>
<BODY LANGUAGE=javascript onLoad="window.focus()">
<span class="btn" style="width:254;background-color:#F0C0C0;color:#0000FF;text-align:center">sunnisdu 山东大学 <a href="javascript:window.location.reload();">开始</a></span><br/>
<span style="background-color:black;width:22"></span><span id="msg" style="width:232;background-color:black;color:#00FF00;">俄罗斯方块</span>
<script language=javascript>
startGame();
</script>
</BODY>
</HTML>
评论Feed: http://www.elfnest.com/blog/feed.asp?q=comment&id=162
这篇日志没有评论.









