Email:shun_shun@21cn.com
三叶
有几个类文件,注释写的比较详细,由于这里篇幅有限制所以我只帖出三个类,如果想添加新的图形就再写一个类,继承shape这个类,将里面的数组按照想要的形状初始化就好了,当然在RRFrame中也要做点修改,要不然新的图形怎么能显示出来,本来想写个配置文件把所有的图形初始化信息都写到里面,实在没有时间了,现在又在学oracle比较忙,~~~~~~~~希望大家能给我提点宝贵意见,谢谢, sql语句,看起来简单做起来难啊!~~~~~~~~~~~,
顺便说下如果有人想转载我的文章摆脱,把前面的说明也顺便一道转了
呵呵,帮帮兄弟烧烧人气吧.谢谢!~~~~~~~~~~~~~
-------------------------------------------------------------------------------------------------------------------------------
RRFrame.java
import java.awt.Color;
import java.awt.Font;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Menu;
import java.awt.MenuBar;
import java.awt.MenuItem;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class RRFrame extends Frame {
MenuBar mb=new MenuBar();
Menu m_control=new Menu("控制");
Menu m_about=new Menu("关于");
MenuItem mit_Start = new MenuItem("Strat(F2)");
MenuItem mit_Pause = new MenuItem("Pause(F5)");
Random rand=new Random();
public static final int step=10;//网格大小
public static final int GameWidth = 20;//网格宽的 个数
public static final int GameHeight = 40;//网格 高的 个数
public static final int ScreenWidth = 300;
public static final int ScreenHeight = 500;
public static final int SmallShapeX = 230;
public static final int SmallShapeY = 150;
/**
* 记录游戏的状态,死亡时 为true
* 运行时为false
* */
private boolean dead = false;
/**
* 记录游戏的状态,暂停时为 true
* 运行时为 false
* */
private boolean pause = false;
/**
*
* 记录得分规则为:
* 基础得分(100)*
*
* */
public int source = 0;
/**
* 游戏死亡的高度
*
* */
public int DeadHeight = 1;
/**
*
* 双缓冲屏幕所用的图片
*
* */
Image offScreenImage = null;
/**
*
* 记录整个游戏图形堆积的信息;
*
* */
byte[][] DataStruct=new byte[GameHeight][GameWidth];
/**
* 当前正在操作的图形;
* */
Shape shape = null;
/**
*
* 下一个图形
*
* */
Shape nextshape = null;
/**
*
* 随机获取一个图形;
*
* */
public Shape getShape(){
Shape s = null;
int i=rand.nextInt(7);
switch(i){
case 0 :
s = new ShapeI(this);
break;
case 1 :
s = new ShapeL(this);
break;
case 2 :
s = new ShapeRec(this);
break;
case 3 :
s = new ShapeJ(this);
break;
case 4 :
s = new ShapeS(this);
break;
case 5 :
s = new ShapeS2(this);
break;
case 6 :
s = new ShapeT(this);
break;
}
return s;
}
/**
*
* 程序运行时的配置方法;
* */
private void lanuch() {
this.shape = this.getShape();
this.nextshape = this.getShape();
mb.add(m_control);
mb.add(m_about);
m_control.add(mit_Start);
m_control.add(mit_Pause);
mit_Start.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
restart();
}
});
mit_Pause.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
pauseAction();
}
});
this.setMenuBar(mb);
this.setLocation(200,200);
this.setSize(ScreenWidth,ScreenHeight);
this.addKeyListener(new KeyMonitor());
this.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e){
System.exit(0);
}
});
this.setVisible(true);
new Thread(new Repaint()).start();
}
public void paint(Graphics g){
this.drawNextShape(g);
this.drawDataStruct(g);
this.gameOver(g);
shape.draw(g);
this.drawSource(g);
this.drawPause(g);
}
/**
* 显示游戏得分情况
*
* */
public void drawSource(Graphics g){
Font f=new Font("隶书",20,20);
Font fg=g.getFont();
g.setFont(f);
g.drawString("Source:", 210, 80);
g.drawString(""+source, 230, 100);
g.setFont(fg);
}
/**
*
* 双缓冲方法
* */
public void update(Graphics g){
if(offScreenImage==null)
offScreenImage=this.createImage(ScreenWidth,ScreenHeight);
Graphics goffScreenImage=offScreenImage.getGraphics();
Color c=goffScreenImage.getColor();
goffScreenImage.setColor(Color.GREEN);
goffScreenImage.fillRect(0, 0, ScreenWidth,ScreenHeight);
goffScreenImage.setColor(c);
paint(goffScreenImage);
g.drawImage(offScreenImage, 0, 0, null);
}
/**
* 将整个游戏的数据结构变成图形显示在屏幕上
*
* */
public void drawDataStruct(Graphics g){
Color c = g.getColor();
g.setColor(Color.red);
for(int i=0;i<this.GameHeight;i++){
for(int j=0;j<this.GameWidth;j++) {
if(DataStruct[i][j]==0){
g.drawRect(j*step, i*step, step, step);
}else {
if(DataStruct[i][j]==1){
g.fillOval(j*step, i*step, step, step);
}
}
}
}
g.setColor(c);
}
/**
*
* 测试游戏是否死亡的方法;
*
* */
private boolean deadTest() {
for(int i=0;i<DataStruct[DeadHeight].length;i++) {
if(1 == DataStruct[DeadHeight][i]) {
this.dead = true;
return true;
}
}
return false;
}
public static void main(String[] args) {
RRFrame rrframe=new RRFrame();
rrframe.lanuch();
//rrframe.nextShape();
}
/**
* 删除行的方法,当Shape调用bulid()方法时调用此方法
* delRows(int startRow,int height)
*
* 参数int startRow为DataStruct开始检测的行数,
* 参数 int height为要检测的高度
*
*
* */
public void delRows(int startRow,int height){
boolean rowflag=true;
List<Integer> rowNumber =new ArrayList<Integer>();
for(int h=startRow; h<startRow+height; h++) {
for(int w=0; w<DataStruct[0].length; w++){
if(DataStruct[h][w]==0){
rowflag=false;
break;
}
}
if(rowflag)rowNumber.add(h);
rowflag=true;
}
if(rowNumber.size()>0){
source = source +Double.valueOf(100*Math.pow(2.0,(double)rowNumber.size()-1)).intValue();
}
for(int i=0;i<rowNumber.size();i++){
System.arraycopy(DataStruct, 0, DataStruct, 1, rowNumber.get(i));
}
}
/**
* 当游戏达到死亡条件时显示 Game Over 字样
* */
public void gameOver(Graphics g) {
if(this.deadTest()){
Font f = new Font("隶书",60,60);
Font of = g.getFont();
Color c = g.getColor();
g.setColor(new Color(100,50,50));
g.setFont(f);
g.drawString("Game Over", 20, 200);
g.setColor(c);
g.setFont(of);
}
}
/**
* 将nextshap的图形信息显示在屏幕上
*
*
* */
public void drawNextShape(Graphics g){
Font f=new Font("隶书",20,16);
Font fg=g.getFont();
g.setFont(f);
g.drawString("Next Shape", 210, 140);
g.setFont(fg);
for(int h=0;h<nextshape.shapeData[nextshape.currentkind].length;h++){
for(int w=0;w<nextshape.shapeData[nextshape.currentkind][0].length;w++){
if(nextshape.shapeData[nextshape.currentkind][h][w]==1){
g.fillOval(this.SmallShapeX+w*step,this.SmallShapeY+h*step,step,step);
}
}
}
}
/**
* 游戏重新开始的方法
*
* */
private void restart(){
for(int h=0;h<this.DataStruct.length; h++){
for(int w=0; w<this.DataStruct[0].length;w++){
this.DataStruct[h][w] = 0;
}
}
this.shape = this.getShape();
this.nextshape = this.getShape();
if(true == this.dead || true == pause){
this.dead = false;
pause = false;
new Thread(new Repaint()).start();
}
}
private void drawPause(Graphics g){
if(!pause) {
return;
}
Font f=new Font("隶书",20,20);
Font fg=g.getFont();
g.setFont(f);
g.drawString("PAUSE", 220, 220);
g.setFont(fg);
}
/**
* 处理游戏暂停的方法
* */
private void pauseAction(){
if(true == pause){
pause = false;
new Thread(new Repaint()).start();
}else {
pause = true;
this.repaint();
}
}
/**
*
* 屏幕刷新线程
* */
class Repaint implements Runnable{
public void run(){
while(!pause && !dead){
repaint();
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
/**
*
* 键盘监听事件
* */
class KeyMonitor extends KeyAdapter {
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_F2){
restart();
}
if(dead){
return;
}
if(e.getKeyCode() == KeyEvent.VK_F5){
pauseAction();
}
shape.keyPressed(e);
}
public void keyReleased(KeyEvent e) {
shape.keyReleased(e);
}
}
}
-------------------------------------------------------------------------------------------------------------------------------
Shape.java
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.util.Random;
/**
*
* 在初始化shapeData时,要靠左上对齐
*
* 也就是图形的左边界贴在shapeData的左边界
* 图形的下边界要贴在shapeData的右边界;
* 理由:这样只用计算图形的下边界和右边界即可,方便运算
* 例如:
* static {
shapeData=new byte[][][]{
{
{1,1},
{0,1},
{0,1},
},
{
{0,0,1},
{1,1,1},
},
{
{1,0},
{1,0},
{1,1},
},
{
{1,1,1},
{1,0,0},
},
};
}
*
*
*
*
*
* */
public class Shape {
static Random rand=new Random();
//private Random r=new Random();
/**
*
* 控制下落速度的常量
* 也就是说没刷屏DownSpeed的次数,图形的位置下降一个单位
*
*
* */
private static final int DownSpeed=5;
private int downspeedi = 0;// DownSpeed的计数器
// public int ShapeWidth;
// public int ShapeHeight;
/**
* 这个为存储图形形状的数组
* byte[z][y][x]
* byte.length为本图形的状态数
* byte[z].length为图形在z状态下的高度;
* byte[z][0].length为图形在z状态下的宽度
*
*
*
* */
byte[][][] shapeData;//=new byte[ShapeHeight][ShapeWidth];
public int kind;
public int currentkind;
private int step=RRFrame.step;
private int x = (RRFrame.GameWidth/2-2)*step;
private int y = 0;
private RRFrame rrf;
/**
* 向左的键按下后为true
* */
private boolean left = false;
/**
* 向右的键按下后为true
* */
private boolean right = false;
/**
* 向下的键按下后为true
* */
private boolean down = false;
public Shape(RRFrame rrf) {
this.rrf = rrf;
}
/**
*
* 画图形的方法
*
* */
public void draw(Graphics g){
for(int h=0;h<shapeData[currentkind].length;h++){
for(int w=0;w<shapeData[currentkind][0].length;w++){
if(shapeData[currentkind][h][w]==1){
g.fillOval(x+w*step,y+h*step,step,step);
}
}
}
move();
}
// public void setShape(){
// currentkind=rand.nextInt(kind);
// //ShapeWidth = shapeData[currentkind][0].length;
// //ShapeHeight = shapeData[currentkind].length;
// }
/**
*
* 图形旋转的方法
*
* */
private void rotate(){
if(!rotateTest((currentkind+1)%kind)){
return;
}
this.currentkind=(currentkind+1)%kind;
// ShapeWidth = shapeData[currentkind][0].length;
// ShapeHeight = shapeData[currentkind].length;
}
/**
*
* 检测当前图形位置是否能够旋转
* 如果可以旋转返回true;
* 如果不可旋转返回false;
*
* */
private boolean rotateTest(int testKind) {
if((rrf.GameWidth < mappedX(shapeData[testKind][0].length)) || (rrf.GameHeight < mappedY(shapeData[testKind].length))){
return false;
}
for(int h=0; h<shapeData[testKind].length; h++){
for(int w=0; w<shapeData[testKind][0].length; w++){
if((1 == shapeData[testKind][h][w]) && (1 ==rrf.DataStruct[mappedY(h)][mappedX(w)])){
return false;
}
}
}
return true;
}
/**
*
* 当图形所在位置符合游戏设计的堆加原则,调用此方法,
* 改写RRFrame.DataStruct[][]的内容
*
*
*
* */
private void bulid(){
int tempw;
int temph;
for(int h=0; h<shapeData[currentkind].length; h++) {
for(int w=0; w<shapeData[currentkind][0].length; w++) {
if(shapeData[currentkind][h][w]==1) {
tempw = x/step+w;
temph = y/step+h;
rrf.DataStruct[temph][tempw]=1;
}
}
}
rrf.delRows(mappedY(0), shapeData[currentkind].length);
//rrf.shape=new ShapeI(rrf);
rrf.shape = rrf.nextshape;
rrf.nextshape = rrf.getShape();
}
private void move(){
//控制自然落下down 的速度
if(downspeedi%this.DownSpeed == 0 || down){
y=y + step;
}
this.downspeedi ++;
//控制左右的移动
if(left && !touchLeftSide()){
this.x = this.x - step;
}else if(right && !touchRightSide()) {
this.x = this.x + step;
}
this.tuchDownObject();
}
/**
*
* 判断碰触底边物体
*
* */
private boolean tuchDownObject() {
if(rrf.GameHeight == mappedY(shapeData[currentkind].length)) {
this.bulid();
return true;
}
for(int h=0; h < shapeData[currentkind].length;h++){
for(int w=0; w < shapeData[currentkind][0].length; w++){
if((1 == shapeData[currentkind][h][w]) && (1 == rrf.DataStruct[mappedY(h)+1][mappedX(w)])){
this.bulid();
return true;
}
}
}
return false;
}
/**
*
* 判断碰触左边物体
*
* */
private boolean touchLeftSide() {
if(0 == x ){
return true;
}
for(int h=0; h <shapeData[currentkind].length; h++){
for(int w=0; w < shapeData[currentkind][0].length; w++) {
if((1 == shapeData[currentkind][h][w]) && (1 == rrf.DataStruct[mappedY(h)][mappedX(w)-1])){
return true;
}
}
}
return false;
}
/**
*
* 判断碰触右边物体
*
* */
private boolean touchRightSide() {
if(mappedX(shapeData[currentkind][0].length) == rrf.GameWidth ){
return true;
}
for(int h=0; h < shapeData[currentkind].length; h++){
for(int w=0; w < shapeData[currentkind][0].length; w++) {
if((1 == shapeData[currentkind][h][w]) && (1 == rrf.DataStruct[mappedY(h)][mappedX(w)+1])){
return true;
}
}
}
return false;
}
/**
*
* 此函数是将图形内横向的点映射到,RRFrame的DataStruct中
* 参数 int w为图形点所在的列数
*
* */
private int mappedX(int w){
int i=0;
i=x/step+w;
return i;
}
/**
*
* 此函数是将图形内纵向的点映射到,RRFrame的DataStruct中
* 参数 int h为图形点所在的行数
*
* */
private int mappedY(int h){
int i=0;
i=y/step+h;
return i;
}
/**
*
* 响应键盘事件
* VK_DOWN : 向下加速
* VK_LEFT :向左移动
* VK_RIGHT :向右移动
* VK_SPACE :旋转图形
* */
public void keyPressed(KeyEvent e) {
switch(e.getKeyCode()) {
case KeyEvent.VK_DOWN :
down = true;
break;
case KeyEvent.VK_LEFT :
this.left = true;
break;
case KeyEvent.VK_RIGHT :
this.right = true;
break;
case KeyEvent.VK_SPACE :
this.rotate();
break;
}
}
/**
*
* 响应键盘事件
* VK_DOWN : 向下加速
* VK_LEFT :向左移动
* VK_RIGHT :向右移动
* VK_SPACE :旋转图形
* */
public void keyReleased(KeyEvent e) {
switch(e.getKeyCode()){
case KeyEvent.VK_DOWN :
down = false;
break;
case KeyEvent.VK_LEFT :
this.left = false;
break;
case KeyEvent.VK_RIGHT :
this.right = false;
break;
}
}
}
----------------------------------------------------------------------------------------------------------------------------
ShapeI.java
public class ShapeI extends Shape {
public ShapeI(RRFrame rrf) {
super(rrf);
shapeData=new byte[][][]{
{
{1},
{1},
{1},
{1},
},
{
{1,1,1,1}
},
};
kind = shapeData.length;
currentkind=rand.nextInt(kind);
}
}
-----------------------------------------------------------------------------------------------------------------------------
分享到:
相关推荐
C++俄罗斯方块源代码
《Android版俄罗斯方块源代码解析与多人游戏机制详解》 在移动设备上,经典游戏“俄罗斯方块”因其简洁的玩法和极高的娱乐性深受玩家喜爱。在Android平台上,开发者们利用Java语言和Android SDK构建了各种版本的...
【俄罗斯方块源代码解析】 俄罗斯方块是一款深受全球玩家喜爱的经典益智游戏,自1984年诞生以来,其简洁的设计和无尽的挑战性使其成为了电子游戏史上的里程碑。这款游戏中,不同形状的方块从屏幕顶部落下,玩家需要...
【标题】"俄罗斯方块源代码(c++语言)"涉及的是使用C++编程语言实现的经典游戏——俄罗斯方块的源代码。C++是一种通用、面向对象的编程语言,具有高效性、灵活性和丰富的库支持,是开发游戏的常用语言之一。 ...
总的来说,通过分析C#实现的俄罗斯方块源代码,我们可以学习到C#的基本语法、面向对象编程、控件使用、事件处理、图形绘制以及游戏逻辑设计等多个方面的知识。对于初学者而言,这是一个绝佳的实践项目,既能提升编程...
【标题】"FLASH 俄罗斯方块 源代码"揭示了这是一个基于Adobe Flash平台的编程项目,使用ActionScript 3(AS3)语言实现的经典游戏——俄罗斯方块。ActionScript是Flash开发的主要脚本语言,它允许开发者创建交互式...
《MFC俄罗斯方块源代码解析与探讨》 在编程世界中,俄罗斯方块是一款经典的休闲游戏,它的简单规则和无限挑战性使其成为了学习游戏开发的绝佳起点。本篇文章将深入探讨基于MFC(Microsoft Foundation Classes)框架...
在这个“html5俄罗斯方块源代码”项目中,开发者使用HTML5的Canvas元素、JavaScript编程语言以及可能的CSS3来实现了一款经典的电子游戏——俄罗斯方块。俄罗斯方块是一款广受欢迎的益智游戏,玩家需要操控下落的各种...
通过学习和分析这个C#俄罗斯方块源代码,我们可以理解游戏开发的基本流程,提高C#编程技能,并学习如何将理论知识应用于实际项目中。同时,这也是一个很好的练习项目,有助于提升问题解决和算法设计能力。
当我们提到“俄罗斯方块源代码,竟然只有60行”时,这可能是指一个精简版或简化实现的俄罗斯方块游戏,它通过高度优化和简洁的编程技巧将整个游戏逻辑压缩在了非常少的代码行中。 在编程领域,简洁的代码往往被视为...
《VB2008实现俄罗斯方块源代码解析与学习指南》 VB2008,全称为Visual Basic 2008,是Microsoft公司开发的一款面向对象的编程语言,属于.NET Framework的一部分。它以其易学易用的特性,成为了初学者入门编程的首选...
【标题】"十分不错的java写的俄罗斯方块源代码"揭示了这个项目是使用Java编程语言实现的俄罗斯方块游戏的源代码。Java是一种广泛应用的面向对象的编程语言,以其跨平台性和高性能而闻名,尤其适合开发桌面应用和游戏...