`
wangshu3000
  • 浏览: 131382 次
  • 性别: Icon_minigender_1
  • 来自: 大连
社区版块
存档分类
最新评论

假期没事,写了个90行的俄罗斯方块,Java实现,史上最小巧

阅读更多

Bug已经Fix~~ 注释已经补充

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Terris extends JFrame implements Runnable, KeyListener {
    private short isPlaying=0/*是否游戏,声明*/,xOffSet = 3/*当前方块的横坐标*/, yOffSet = 0/*当前方块的纵坐标*/, blockType = (short) Math.round(Math.random() * 6)/*随即初始方块类型*/, blockRotation = 0/*初始方块旋转角度*/, blockColor = (short) Math.round(Math.random() * 5)/*随即初始方块颜色*/;
    private short matrix[][] = new short[21][10];/*整个画布21*10的矩阵*/
    private short block[][][][] = {{{{ 0, 1, 0, 0 },{ 0, 1, 0, 0 },{ 0, 1, 0, 0 },{ 0, 1, 0, 0 }},/* l */{{ 0, 0, 0, 0 }, { 1, 1, 1, 1 }, { 0, 0, 0, 0 },{ 0, 0, 0, 0 } } },/*-*/{{ { 0, 0, 0, 0 }, { 1, 1, 0, 0 }, { 0, 1, 1, 0 },{ 0, 0, 0, 0 } },/* z */{ { 0, 0, 0, 0 }, { 0, 0, 1, 0 }, { 0, 1, 1, 0 },{ 0, 1, 0, 0 } } },/* z| */{{ { 0, 0, 0, 0 }, { 0, 1, 1, 0 }, { 1, 1, 0, 0 },{ 0, 0, 0, 0 } },/* xz */{ { 0, 1, 0, 0 }, { 0, 1, 1, 0 }, { 0, 0, 1, 0 },{ 0, 0, 0, 0 } } },/* xz| */{ { { 0, 0, 0, 0 }, { 0, 1, 1, 0 }, { 0, 1, 1, 0 }, { 0, 0, 0, 0 } } },/** []*/{{ { 0, 1, 1, 0 }, { 0, 1, 0, 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, 1, 0, 0 }, { 0, 1, 0, 0 }, { 1, 1, 0, 0 },{ 0, 0, 0, 0 } },{ { 1, 0, 0, 0 }, { 1, 1, 1, 0 }, { 0, 0, 0, 0 },{ 0, 0, 0, 0 } } },/* f */{{ { 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 } },{ { 0, 1, 0, 0 }, { 0, 1, 0, 0 }, { 0, 1, 1, 0 },{ 0, 0, 0, 0 } },{ { 0, 0, 0, 0 }, { 1, 1, 1, 0 }, { 1, 0, 0, 0 },{ 0, 0, 0, 0 } } },/* xf */ {{ { 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 } } } };/* t *//*保存所有方块的4维矩阵,分别是:方块类型、方块旋转、方块x坐标、方块y坐标*/
    private Image[] images = {new ImageIcon("D:/Java/eclipse/workspace/Terris/src/img/Red.gif").getImage(),new ImageIcon("D:/Java/eclipse/workspace/Terris/src/img/Blue.gif").getImage(),new ImageIcon(("D:/Java/eclipse/workspace/Terris/src/img/Pink.gif")).getImage(),new ImageIcon(("D:/Java/eclipse/workspace/Terris/src/img/BBlue.gif")).getImage(),new ImageIcon(("D:/Java/eclipse/workspace/Terris/src/img/Orange.gif")).getImage(),new ImageIcon(("D:/Java/eclipse/workspace/Terris/src/img/Green.gif")).getImage(),new ImageIcon("D:/Java/eclipse/workspace/Terris/src/img/Red.gif").getImage()};/*各种颜色方块图片*/
    public Terris() {
        setSize(160, 335);/*窗口大小*/
        setVisible(true);/*可视*/
        createBufferStrategy(2);/*对当前窗口创建双缓冲*/
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);/*设置关闭按钮事件*/
        addKeyListener(this);/*添加按键响应*/
    }
    public void paint(Graphics g) {
        Graphics tg = this.getBufferStrategy().getDrawGraphics();/*获取后台缓冲画布*/
        tg.fillRect(5, 30, 150, 340);/*涂黑背景*/
        for (int i = 0; i < 21; i++)
            for (int j = 0; j < 10; j++) {
                if (matrix[i][j] != 0)
                    tg.drawImage(images[matrix[i][j]], j * 15 + 5, i * 15 + 15,null);/*根据后台背景的矩阵绘制已经固定的各方块*/
                if (i < 4 && j < 4&& block[blockType][blockRotation][i][j] != 0)
                    tg.drawImage(images[blockColor + 1],((j + xOffSet) * 15) + 5,((i + yOffSet) * 15) + 15, null);/*绘制当前能控制的方块*/
            }
        this.getBufferStrategy().show();/*切换后台画布到前台显示*/
    }
    public static void main(String[] args) {
        new Thread(new Terris()).start();//初始化界面并创建启动游戏线程
    }
    public void run() {
        while (isPlaying==0)/*当游戏正在进行 不断下落*/
            try {
                if (check(0, 0, 0, 1))/*最后一个参数1 是下落 表示下落一格 其他参数见下面的注释*/
                    yOffSet += 1;/*如果能下落 y坐标+1*/
                else {/*如不能下落 说明到底了*/
                    if (yOffSet == 0) {/*如果当前是第一个方块 游戏结束*/
                        isPlaying = 1;
                        continue;/*不再循环*/
                    }
                    freezeAndNew();/*将当前控制的方块合并到背景矩阵中 并初始化新的方块*/
                }
                repaint();/*重绘画布*/
                Thread.sleep(600);/*线程sleep 可以修改作为难度*/
            } catch (InterruptedException e) {/*无用*/
            }
    }
    private boolean check(int left, int right, int up, int down) {/*判断方块是否可以左右移动、下落、旋转 都合并到一个方法中了 四个参数分别代表要判断左移、右移、旋转、下落 如果对应方向有动作 则传入1 没有动作传入0 在判断时直接计算参数值即可 而不考虑传入的具体值是1还是0*/
        for (int i = 0; i < 4; i++)
            for (int j = 0; j < 4; j++)
                if (((xOffSet + j - left + right < 0 || xOffSet + j - left+ right >= 10) && block[blockType][((blockRotation + up) >= block[blockType].length ? 0: (blockRotation + up))][i][j] != 0)|| ((yOffSet + i + down >= 21) && block[blockType][((blockRotation + up) >= block[blockType].length ? 0: (blockRotation + up))][i][j] != 0)|| (block[blockType][((blockRotation + up) >= block[blockType].length ? 0: (blockRotation + up))][i][j] != 0 && matrix[yOffSet+ i + down][xOffSet + j - left + right] != 0))
                    return false;
        return true;
    }
    private synchronized void  freezeAndNew() {/*方块到底 固定到背景矩阵 并初始化新方块*/
        boolean[] clear = new boolean[]{false,false,false,false};/*是否可以消行的数组 每个方块4*4 只需判断方块所在的4行即可*/
        for (int i = 0; i < 4; i++){
            for (int j = 0; j < 4; j++)
                if (block[blockType][blockRotation][i][j] != 0)/*循环将方块的1赋值到背景的矩阵中 方块4*4中的0 没有方块的地方不复制*/
                    matrix[i + yOffSet][j + xOffSet] = (short) (blockColor + 1);/*根据当前方块颜色复制到背景 可修改为灰色*/
            clear[i]=i + yOffSet>=matrix.length?false:(matrix[i + yOffSet][0]!=0&&matrix[i + yOffSet][1]!=0&&matrix[i + yOffSet][2]!=0&&matrix[i + yOffSet][3]!=0&&matrix[i + yOffSet][4]!=0&&matrix[i + yOffSet][5]!=0&&matrix[i + yOffSet][6]!=0&&matrix[i + yOffSet][7]!=0&&matrix[i + yOffSet][8]!=0&&matrix[i + yOffSet][9]!=0);/*一次判断一行0~9个方块是否有值 有值 复制到消行数组为true*/
        }
        for(int i=0;i<clear.length;i++)
            if(clear[i])/*如果消行*/
                for(int j=yOffSet+i;j>0;j--)
                    System.arraycopy(matrix[j-1],0,matrix[j],0,10);/*循环从当前行依次把上面一行复制下来 下落效果*/
        yOffSet = blockRotation = 0;/*消行结束 下面几行是初始化新方块 xy方块类型 旋转 颜色*/
        xOffSet = 3;
        blockType = (short) Math.round(Math.random() * 6);
        blockRotation = (short) Math.round((Math.random() * (block[blockType].length - 1)));
        blockColor = (short) Math.round(Math.random() * 5);
    }
    public void keyPressed(KeyEvent e) {// 38-上 40-下 37-左 39-右
        if ((e.getKeyCode() == 65 || e.getKeyCode() == 37) && check(1, 0, 0, 0)&&isPlaying==0) {// left/*左移 传入判断方块是否能移动的方法 第一个参数传1 其他传0*/
            xOffSet--;/*能左移 x减1*/
        } else if ((e.getKeyCode() == 68 || e.getKeyCode() == 39)&& check(0, 1, 0, 0)&&isPlaying==0) {// right/*类似上面 右移第二个参数传1 其他0*/
            xOffSet++;/*能右移 x加1*/
        } else if ((e.getKeyCode() == 87 || e.getKeyCode() == 38)&& check(0, 0, 1, 0)&&isPlaying==0) {// up
            blockRotation = (short) ((blockRotation + 1) >= block[blockType].length ? 0: (blockRotation + 1));/*能旋转 根据当前方块类型进行旋转 如果到最后一个角度 回到0 继续旋转*/
        } else if ((e.getKeyCode() == 83 || e.getKeyCode() == 40)&& check(0, 0, 0, 1)&&isPlaying==0) {// down
                yOffSet += 1;/*能下落 y加1*/
        } else if((e.getKeyCode() == 83 || e.getKeyCode() == 40)&& isPlaying==0)
                freezeAndNew();/*不能下落 固定 并消行 新方块*/
        repaint();/*移动事件触发重绘*/
    }
    public void keyReleased(KeyEvent arg0) {/*无用*/
    }
    public void keyTyped(KeyEvent arg0) {/*无用*/
    }
}
//作者:http://wireless.iteye.com/blog/595321
 

 转载请注明出处http://wireless.iteye.com/blog/595321

  • 大小: 9.9 KB
  • 大小: 138 Bytes
  • 大小: 137 Bytes
  • 大小: 137 Bytes
  • 大小: 138 Bytes
  • 大小: 139 Bytes
  • 大小: 138 Bytes
分享到:
评论
34 楼 eyelock 2012-06-12  
我运行报错,,楼主能解答一下G,对swing不熟。
raphics tg = this.getBufferStrategy().getDrawGraphics();/*获取后台缓冲画布*/

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at Terris.paint(Terris.java:17)
at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:734)
at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:679)
at javax.swing.RepaintManager.seqPaintDirtyRegions(RepaintManager.java:659)
at javax.swing.SystemEventQueueUtilities$ComponentWorkRequest.run(SystemEventQueueUtilities.java:128)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:597)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:273)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:183)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:173)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:168)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:160)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:121)
33 楼 xouou_53320 2012-01-25  
都是牛人
32 楼 zhfally520 2011-02-16  
学习下 不错啊 惭愧
31 楼 jellyfish 2011-02-01  
serious threading problem! google "swing threading"
30 楼 mefly 2011-01-31  
汗呀,我做java程序员5年了,一想到这个游戏,脑子里没什么思路,觉得好难
29 楼 thorlst 2010-05-07  
写得真不错 有空研究一下
28 楼 yy11ll12 2010-05-07  
还算不错,就是图片的绝对路径很不好
27 楼 zqding 2010-05-07  
看看呵,学习了
26 楼 不良市民 2010-05-06  
不过数据结构用的不够翘,哈哈。
25 楼 不良市民 2010-05-06  
wangshu3000 写道

哈哈 见笑了 目的不是写俄罗斯 是看只用100行代码能写出什么东西 挑战一下
图片是15*15

这个可是最高境界了,100行代码想写多少东西,我觉得你可以用python试试,兴许一个DBS都可以写出来。哈哈,不过见识了,写的很漂亮,哈哈
24 楼 xici_magic 2010-02-25  
嗯 下来学习一下
23 楼 vividemon 2010-02-23  
后来发现,可能是我最之前简化错了。
System.arraycopy()p;不支持多维数组。还是我基础太差了。
22 楼 vividemon 2010-02-23  
<p>我边看边自己加的注释……<br>自己写了一遍,又有新的发现,那个clear[true,true,true,true]可以省去。<br>跟上面的循环并在一起,直接作为判断条件后就消去那一行。</p>
<p>对应楼主行数是63到66。<br>大概我写了下可以省去几行</p>
<p><br> if( i + yOffSet &lt; matrix.length<br>       &amp;&amp;matrix[i+yOffSet][0]!=0<br>       &amp;&amp;matrix[i+yOffSet][1]!=0<br>       &amp;&amp;matrix[i+yOffSet][2]!=0<br>       &amp;&amp;matrix[i+yOffSet][3]!=0<br>       &amp;&amp;matrix[i+yOffSet][4]!=0<br>       &amp;&amp;matrix[i+yOffSet][5]!=0<br>       &amp;&amp;matrix[i+yOffSet][6]!=0<br>       &amp;&amp;matrix[i+yOffSet][7]!=0<br>      &amp;&amp;matrix[i+yOffSet][8]!=0<br>     &amp;&amp;matrix[i+yOffSet][9]!=0){</p>
<p><br>    System.arraycopy(matrix, 0, matrix, 1, yOffSet+i);</p>
<p> }</p>
<p> </p>
<p>还有楼主,问下前面8楼说的bug是怎么造成的?我自己写了下,有时候也会有那个bug,有时候就没有。没发现是怎么造成的。请楼主指出呀。</p>
<p> </p>
21 楼 ladybird2010 2010-02-23  
wangshu3000 写道
vividemon 写道
研究了一下午……,给楼主提个简化的地方

第65,66行可以稍微简化一下

     for(int j=yOffSet+i;j>0;j--)                                  <br>           System.arraycopy(matrix[j-1],0,matrix[j],0,10);

 

变成     System.arraycopy(matrix, 0, matrix, 1, yOffSet+i); 

 

还有我上面说的bug 还是没找到原因,时有时无的。我用的Linux下的jdk ,不会跟平台有关吧……

 

呵呵 多谢提醒啊.. arraycopy还能这么用啊 还有地方可以简化 估计还能缩个5行左右

这个bug我也没研究明白原因 可能是双缓冲的地方 研究下 这个问题解决了就没有bug了应该

代码加上注释的话会更好些, 注释是习惯,读者可一目了然啊!
20 楼 wangshu3000 2010-02-22  
vividemon 写道
研究了一下午……,给楼主提个简化的地方

第65,66行可以稍微简化一下

     for(int j=yOffSet+i;j>0;j--)                                  <br>           System.arraycopy(matrix[j-1],0,matrix[j],0,10);

 

变成     System.arraycopy(matrix, 0, matrix, 1, yOffSet+i); 

 

还有我上面说的bug 还是没找到原因,时有时无的。我用的Linux下的jdk ,不会跟平台有关吧……

 

呵呵 多谢提醒啊.. arraycopy还能这么用啊 还有地方可以简化 估计还能缩个5行左右

这个bug我也没研究明白原因 可能是双缓冲的地方 研究下 这个问题解决了就没有bug了应该
19 楼 vividemon 2010-02-22  
<p>研究了一下午……,给楼主提个简化的地方</p>
<p>第65,66行可以稍微简化一下</p>
<p>     for(int j=yOffSet+i;j&gt;0;j--)                                  <br>           System.arraycopy(matrix[j-1],0,matrix[j],0,10);</p>
<p> </p>
<p>变成     System.arraycopy(matrix, 0, matrix, 1, yOffSet+i); </p>
<p> </p>
<p>还有我上面说的bug 还是没找到原因,时有时无的。我用的Linux下的jdk ,不会跟平台有关吧……</p>
<p> </p>
18 楼 vividemon 2010-02-22  
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at main.Terris.paint(Terris.java:70)
at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:796)
at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:713)
at javax.swing.RepaintManager.seqPaintDirtyRegions(RepaintManager.java:693)
at javax.swing.SystemEventQueueUtilities$ComponentWorkRequest.run(SystemEventQueueUtilities.java:125)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:597)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)
我游戏运行正常,但是会报上面的错误,不太懂Swing编程。楼主麻烦看下是什么错误。
我再仔细看下楼主的源代码。
17 楼 mihumouse 2010-02-22  
QQ游戏上就有俄罗斯方块,不用手写的说
16 楼 强强爱妍妍 2010-02-21  
兄弟当年写了个俄罗斯方块,可以单人,双人热座,4人热座,1-4人联机,单机对电脑. 电脑智能还很强,轻易很难赢. 代码写的整洁无比,模块划分很清晰.应用了若干设计模式.
可是去面试悲剧了. 因为有个兄弟在网上搞了个俄罗斯方块,只要600行. 哥的代码有1500行. 最关键的是哥当年没有U盘,代码没show一下.
15 楼 wangshu3000 2010-02-21  
wandou 写道
n年前学编程1个月的时候就写了俄罗斯方块。没bug。
楼主不错,快赶上我学编程1个月的功力了,哈哈。。。

哈哈 见笑了 目的不是写俄罗斯 是看只用100行代码能写出什么东西 挑战一下


图片是15*15

相关推荐

    90行Java代码实现最简洁小巧俄罗斯方块~~全球最小实现:)

    90行Java代码实现小巧俄罗斯方块~~ 66行改为: System.arraycopy(matrix[j-1],0,matrix[j],0,10); 修改的一个Bug 最新版本在:http://wireless.javaeye.com/blog/595321

    俄罗斯方块Java Swing 实现

    JavaSwing 实现俄罗斯方块游戏。

    俄罗斯方块JAVA源代码

    闲时无聊,用Java写了一个小时候经常玩的俄罗斯方块小游戏(里面有源代码和编译好的可执行jar包)。 运行环境jdk1.8 源码使用方法:打开eclipse,新建一个java project然后把tetris目录复制到project里的src目录下。

    俄罗斯方块的java实现源代码

    俄罗斯方块的java实现源代码俄罗斯方块的java实现源代码俄罗斯方块的java实现源代码

    俄罗斯方块 java .net

    俄罗斯方块 java .net 俄罗斯方块 java .net 俄罗斯方块 java .net 俄罗斯方块 java .net 俄罗斯方块 java .net 俄罗斯方块 java .net

    java编的俄罗斯方块

    好游戏java编的俄罗斯方块好游戏java编的俄罗斯方块好游戏java编的俄罗斯方块好游戏java编的俄罗斯方块好游戏java编的俄罗斯方块好游戏java编的俄罗斯方块好游戏java编的俄罗斯方块好游戏java编的俄罗斯方块好游戏...

    用java写的一个俄罗斯方块的游戏

    用java编写的一个俄罗斯方块小游戏 运用了很多关于继承什么的方法

    俄罗斯方块的JAVA代码实现

    俄罗斯方块的JAVA代码实现

    俄罗斯方块java源代码

    俄罗斯方块java源代码俄罗斯方块java源代码俄罗斯方块java源代码俄罗斯方块java源代码俄罗斯方块java源代码

    俄罗斯方块Java版

    地球人都知道的经典益智游戏,需要jre环境。

    俄罗斯方块Java源代码

    俄罗斯方块Java源代码俄罗斯方块Java源代码俄罗斯方块Java源代码俄罗斯方块Java源代码俄罗斯方块Java源代码俄罗斯方块Java源代码俄罗斯方块Java源代码俄罗斯方块Java源代码俄罗斯方块Java源代码俄罗斯方块Java源代码...

    java版俄罗斯方块

    java版俄罗斯方块java版俄罗斯方块java版俄罗斯方块java版俄罗斯方块java版俄罗斯方块java版俄罗斯方块java版俄罗斯方块java版俄罗斯方块java版俄罗斯方块java版俄罗斯方块java版俄罗斯方块java版俄罗斯方块java版...

    小游戏俄罗斯方块java实现

    包含详解的文档说明,视频讲解,利用java实现的俄罗斯方块小游戏,可直接运行

    Java俄罗斯方块源代码,Java俄罗斯方块源代码

    俄罗斯方块源代码,俄罗斯方块源代码,俄罗斯方块源代码,

    俄罗斯方块的Java实现源码

    俄罗斯方块的Java实现源码,还可以哦!

    俄罗斯方块 JAVA版

    用JAVA语言编写俄罗斯方块游戏,实现俄罗斯方块游戏的基本功能。课题主要完成目标是利用小应用程序模版及按钮事件、多线程以及相关事件处理完成俄罗斯方块游戏的操作程序。应用到的技术包括类的继承,接口的引用以及...

    Java实现俄罗斯方块小游戏.zip

    Java实现俄罗斯方块小游戏.zipJava实现俄罗斯方块小游戏.zip Java实现俄罗斯方块小游戏.zipJava实现俄罗斯方块小游戏.zip Java实现俄罗斯方块小游戏.zipJava实现俄罗斯方块小游戏.zip Java实现俄罗斯方块小游戏.zip...

    java小游戏 俄罗斯方块

    java小游戏 俄罗斯方块java小游戏 俄罗斯方块java小游戏 俄罗斯方块java小游戏 俄罗斯方块java小游戏 俄罗斯方块java小游戏 俄罗斯方块java小游戏 俄罗斯方块java小游戏 俄罗斯方块java小游戏 俄罗斯方块java小游戏 ...

Global site tag (gtag.js) - Google Analytics