Adol  
日历
<2015年1月>
28293031123
45678910
11121314151617
18192021222324
25262728293031
1234567
统计
  • 随笔 - 2
  • 文章 - 6
  • 评论 - 5
  • 引用 - 0

导航

常用链接

留言簿(1)

随笔档案

文章档案

搜索

  •  

最新评论

阅读排行榜

评论排行榜

 
最近在学习JAVA,就学参考学着写了一个俄罗斯方块,代码有详细注释,这里就不多做说明了。
可以用键盘,空格控制,或者用界面上的按钮。

  1import java.awt.*;
  2import java.awt.event.*;
  3import javax.swing.*;
  4import javax.swing.event.*;
  5
  6class Block implements Runnable// 方块类
  7{
  8    static final int type = 7, state = 4;
  9
 10    static final int[][] patten = // 16进制代表每种方块
 11    0x0f000x44440x0f000x4444 },// 长条
 12            0x66000x66000x66000x6600 },// 正方块
 13            0x04e00x04640x00e40x04c4 },// 三角
 14            0x08e00x06440x00e20x044c },// 弯折一下,1、3,1左
 15            0x02e00x04460x00e80x0c44 },// 弯折一下,1、3,1右
 16            0x04620x006c0x04620x006c },// 弯折两下,1、2、1,1左上;1右下
 17            0x02640x00c60x02640x00c6 } // 弯折两下,1、2、1,1右上;1左下
 18    }
;
 19
 20    private int blockType = -1// 方块类型,7种,大小范围0-6
 21
 22    private int blockState;// 方块状态,4种,大小范围0-3
 23
 24    private int row, col; // 方块所在的行数,列数
 25
 26    private int oldRow, oldCol; // 记录方块变化前所在的行数,列数
 27
 28    private int oldType = -1, oldState; // 记录方块变化前的类型和状态
 29
 30    private int isfall = 1// 标记若画,画成什么颜色的,
 31
 32    // 1表示可以下落,画为红色;0表示不可下落,画为蓝色
 33
 34    private boolean end = false;// 结束标记,为true时表示结束
 35
 36    LeftShowCanvas lsc;
 37
 38    public Block(LeftShowCanvas lsc)
 39    {
 40        this.lsc = lsc;
 41        row = 0;
 42        col = 3;
 43        oldRow = row;
 44        oldCol = col;
 45    }

 46
 47    public void reInit() // 一个方块无法下落后,重新初始化
 48    {
 49        blockType = -1;
 50        isfall = 1;
 51    }

 52
 53    public void reInitRowCol() // 初始化方块起始点
 54    {
 55        row = 0;
 56        col = 3;
 57    }

 58
 59    public void run() // 下落线程
 60    {
 61        lsc.requestFocusInWindow(); // 获得焦点
 62        while (!end)
 63        {
 64            int blocktype = (int) (Math.random() * 100% 7;
 65            drawBlock(blocktype);
 66            do
 67            {
 68                try
 69                {
 70                    Thread.sleep(500); // 控制下落速度
 71                }
 catch (InterruptedException e)
 72                {
 73
 74                }

 75            }
 while (fallMove()); // 下落
 76            for (int j = 0; j < lsc.maxcols; j++)
 77                // 判断是否结束
 78                if (lsc.unitState[3][j] == 2)
 79                    end = true;
 80        }

 81    }

 82
 83    public synchronized void drawBlock(int blockType) // 画方块
 84    {
 85        if (this.blockType != blockType)
 86            blockState = (int) (Math.random() * 100% 4// 状态
 87        this.blockType = blockType; // 样式
 88        if (!isMove(3)) // 判断是否能画
 89        {
 90            this.blockType = oldType;
 91            this.blockState = oldState;
 92            return;
 93        }

 94        int comIndex = 0x8000;
 95        if (this.oldType != -1)
 96        {
 97            for (int i = oldRow; i < oldRow + 4; i++)
 98                for (int j = oldCol; j < oldCol + 4; j++)
 99                {
100                    if ((patten[oldType][oldState] & comIndex) != 0
101                            && lsc.unitState[i][j] == 1)
102                        //lsc.drawUnit(i, j, 0); // 先还原
103                        lsc.unitState[i][j]=0;//将状态记录改变,用于画下张图
104                    comIndex = comIndex >> 1;
105                }

106        }

107        comIndex = 0x8000;
108        for (int i = row; i < row + 4; i++)
109            for (int j = col; j < col + 4; j++)
110            {
111                if ((patten[blockType][blockState] & comIndex) != 0)
112                {
113                    if (isfall == 1)
114                        //lsc.drawUnit(i, j, 1); // 再画,画为RED
115                        lsc.unitState[i][j]=1//将状态记录改变
116                    else if (isfall == 0)
117                    {
118                        //lsc.drawUnit(i, j, 2); // 无法下落,画为BLUE
119                        lsc.unitState[i][j]=2;//将状态记录改变,用于画下张图
120                        lsc.deleteFullLine(i); // 判断此行是否可以消
121                    }

122                }

123                comIndex = comIndex >> 1;
124            }

125        
126        Image image; //创建缓冲图片,利用双缓冲消除闪烁,画的下个状态图
127        image=lsc.createImage(lsc.getWidth(),lsc.getHeight());
128        Graphics g=image.getGraphics();
129        lsc.paint(g);
130        g.drawImage(image, 00, lsc);
131            
132        if (isfall == 0// 无法下落,先判断是否能消行,再重新初始化
133        {
134            // lsc.deleteFullLine(row,col);
135            reInit();
136            reInitRowCol();
137        }

138        oldRow = row;
139        oldCol = col;
140        oldType = blockType;
141        oldState = blockState;
142    }

143
144    public void leftTurn() // 旋转,左转
145    {
146        if (this.blockType != -1)
147        {
148            blockState = (blockState + 1% 4;
149            if (isMove(3))
150                drawBlock(blockType);
151            else
152                blockState = (blockState + 3% 4;
153        }

154    }

155
156    public void leftMove() // 左移
157    {
158        if (this.blockType != -1 && isMove(0))
159        {
160            col -= 1;
161            drawBlock(blockType);
162        }

163    }

164
165    public void rightMove() // 右移
166    {
167        if (this.blockType != -1 && isMove(1))
168        {
169            col += 1;
170            drawBlock(blockType);
171        }

172    }

173
174    public boolean fallMove() // 下移
175    {
176        if (this.blockType != -1)
177        {
178            if (isMove(2))
179            {
180                row += 1;
181                drawBlock(blockType);
182                return true;
183            }
 else
184            {
185                isfall = 0;
186                drawBlock(blockType);
187                return false;
188            }

189        }

190        return false;
191    }

192
193    public synchronized boolean isMove(int tag) // 左 0 ,右 1 ,下 2 ,旋转 3
194    {
195        int comIndex = 0x8000;
196        for (int i = row; i < row + 4; i++)
197            for (int j = col; j < col + 4; j++)
198            {
199                if ((patten[blockType][blockState] & comIndex) != 0)
200                {
201                    if (tag == 0 && (j == 0 || lsc.unitState[i][j - 1== 2))// 是否能左移
202                        return false;
203                    else if (tag == 1 && // 是否能右移
204                            (j == lsc.maxcols - 1 || lsc.unitState[i][j + 1== 2))
205                        return false;
206                    else if (tag == 2 && // 是否能下移
207                            (i == lsc.maxrows - 1 || lsc.unitState[i + 1][j] == 2))
208                        return false;
209                    else if (tag == 3 && // 是否能旋转
210                            (i > lsc.maxrows - 1 || j < 0
211                                    || j > lsc.maxcols - 1 || lsc.unitState[i][j] == 2))
212                        return false;
213                }

214                comIndex = comIndex >> 1;
215            }

216        return true;
217    }

218}

219
220class LeftShowCanvas extends Canvas
221{
222    int maxrows, maxcols; // 画布最大行数,列数
223
224    int unitSize; // 单元格的大小,小正方格
225
226    int[][] unitState; // 每个小方格的状态 0、1、2表示
227
228    RightPanel rp;
229
230    int score;
231
232    public LeftShowCanvas(RightPanel rp)
233    {
234        this.rp = rp;
235        score = Integer.valueOf(rp.jtf.getText());
236        maxrows = 20;
237        maxcols = 10;
238        unitSize = 20;
239        unitState = new int[maxrows][maxcols];
240        initCanvas();
241    }

242
243    public void initCanvas() // 初始化,画布方格
244    {
245        for (int i = 0; i < maxrows; i++)
246            for (int j = 0; j < maxcols; j++)
247                unitState[i][j] = 0;
248    }

249
250    public void paint(Graphics g)
251    {
252        for (int i = 0; i < maxrows; i++)
253        {
254            for (int j = 0; j < maxcols; j++)
255                drawUnit(i, j, unitState[i][j]); // 画方格
256            if (i == 3)
257            {
258                g.setColor(Color.RED);
259                g.drawLine(0, (i + 1* (unitSize + 1- 1, maxcols
260                        * (unitSize + 1- 1, (i + 1* (unitSize + 1- 1);
261            }

262        }

263    }

264
265    public void drawUnit(int row, int col, int tag) // 画方格
266    {
267        unitState[row][col] = tag; // 记录状态
268        Graphics g = getGraphics();
269        switch (tag)
270        {
271        case 0// 初始黑色
272            g.setColor(Color.BLACK);
273            break;
274        case 1// 方格黑色
275            g.setColor(Color.RED);
276            break;
277        case 2:
278            g.setColor(Color.BLUE);
279            break;
280        }

281        g.fillRect(col * (unitSize + 1), row * (unitSize + 1), unitSize,
282                unitSize);
283    }

284
285    public void deleteFullLine(int row) // 判断此行是否可以消,同时可消就消行
286    {
287        for (int j = 0; j < maxcols; j++)
288            if (unitState[row][j] != 2)
289                return;
290
291        for (int i = row; i > 3; i--)
292            // 到此即为可消,将上面的移下消此行
293            for (int j = 0; j < maxcols; j++)
294                //drawUnit(i, j, unitState[i - 1][j]);
295            unitState[i][j]=unitState[i-1][j];//将状态记录改变,用于画下张图
296        score++;
297        rp.jtf.setText(String.valueOf(score));
298    }

299}

300
301class RightPanel extends JPanel
302{
303    JButton[] jbt = new JButton[7];
304
305    JButton[] jbt2 = new JButton[4];
306
307    JButton jbt3;
308
309    JTextField jtf;
310
311    JLabel jlb;
312
313    MyJPanel jp1, jp2;
314
315    public RightPanel()
316    {
317        jbt[0= new JButton("长条");
318        jbt[1= new JButton("方块");
319        jbt[2= new JButton("三角");
320        jbt[3= new JButton("左三");
321        jbt[4= new JButton("右三");
322        jbt[5= new JButton("左二");
323        jbt[6= new JButton("右二");
324        jbt2[0= new JButton("左移");
325        jbt2[1= new JButton("右移");
326        jbt2[2= new JButton("下移");
327        jbt2[3= new JButton("翻转");
328
329        jbt3 = new JButton("开始");
330        jtf = new JTextField("0"5);
331        jlb = new JLabel("得分", JLabel.CENTER);
332
333        jp1 = new MyJPanel(); // 左边的上面板
334        jp2 = new MyJPanel(); // 左边的下面板
335        jp1.setLayout(new GridLayout(422010)); // 网格布局
336        jp2.setLayout(new GridLayout(422010)); // 网格布局
337        this.setLayout(new BorderLayout()); // 边界布局
338        for (int i = 0; i < 7; i++)
339            jp1.add(jbt[i]);
340
341        jp1.add(jbt3);
342
343        for (int i = 0; i < 4; i++)
344            jp2.add(jbt2[i]);
345
346        jp2.add(jlb);
347        jp2.add(jtf);
348
349        this.add(jp1, "North");
350        this.add(jp2, "Center");
351    }

352}

353
354// 重写MyPanel类,使Panel的四周留空间
355class MyJPanel extends JPanel
356{
357    public Insets getInsets()
358    {
359        return new Insets(10303030);
360    }

361}

362
363class MyActionListener implements ActionListener
364{
365    RightPanel rp;
366
367    Block bl;
368
369    LeftShowCanvas lsc;
370
371    public MyActionListener(RightPanel rp, Block bl, LeftShowCanvas lsc)
372    {
373        this.rp = rp;
374        this.bl = bl;
375        this.lsc = lsc;
376    }

377
378    public void actionPerformed(ActionEvent e)
379    {
380        if (e.getSource().equals(rp.jbt3))
381        {
382            // 这样子则按几次开始按钮就创建几个相同的线程,控制着相同的数据
383            Thread th = new Thread(bl);
384            th.start();
385        }

386        for (int i = 0; i < Block.type; i++)
387            if (e.getSource().equals(rp.jbt[i])) // 看是画哪个
388            {
389                bl.reInitRowCol();
390                bl.drawBlock(i);
391                lsc.requestFocusInWindow(); // 获得焦点
392                return;
393            }

394        if (e.getSource().equals(rp.jbt2[0]))
395            bl.leftMove();
396        else if (e.getSource().equals(rp.jbt2[1]))
397            bl.rightMove();
398        else if (e.getSource().equals(rp.jbt2[2]))
399            bl.fallMove();
400        else if (e.getSource().equals(rp.jbt2[3]))
401            bl.leftTurn();
402        lsc.requestFocusInWindow(); // 获得焦点
403    }

404}

405
406class MyKeyAdapter extends KeyAdapter
407{
408    Block bl;
409
410    public MyKeyAdapter(Block bl)
411    {
412        this.bl = bl;
413    }

414
415    public void keyPressed(KeyEvent e)
416    {
417        if (e.getKeyCode() == KeyEvent.VK_LEFT)
418            bl.leftMove();
419        else if (e.getKeyCode() == KeyEvent.VK_RIGHT)
420            bl.rightMove();
421        else if (e.getKeyCode() == KeyEvent.VK_DOWN)
422            bl.fallMove();
423        else if (e.getKeyCode() == KeyEvent.VK_SPACE)
424            bl.leftTurn();
425    }

426}

427
428public class FinalElsBlock extends JFrame
429{
430    Block bl;
431
432    LeftShowCanvas lsc;
433
434    RightPanel rp;
435
436    public FinalElsBlock()
437    {
438        super("ELSBlock Study");
439        setBounds(130130500450);
440        setLayout(new GridLayout(125030));
441        rp = new RightPanel();
442        lsc = new LeftShowCanvas(rp);
443        bl = new Block(lsc);
444        rp.setSize(80400);
445        for (int i = 0; i < 7; i++)
446            // 为每个按钮添加消息监听
447            rp.jbt[i].addActionListener(new MyActionListener(rp, bl, lsc));
448        rp.jbt3.addActionListener(new MyActionListener(rp, bl, lsc));
449        for (int i = 0; i < 4; i++)
450            rp.jbt2[i].addActionListener(new MyActionListener(rp, bl, lsc));
451        lsc.addKeyListener(new MyKeyAdapter(bl));
452        this.add(lsc);
453        this.add(rp);
454        this.addWindowListener(new WindowAdapter()
455        {
456            public void windowClosing(WindowEvent e)
457            {
458                dispose();
459                System.exit(0);
460            }

461        }
);
462        setVisible(true);
463    }

464
465    public static void main(String[] args)
466    {
467        new FinalElsBlock();
468    }

469}
posted on 2009-08-12 23:08 Adol 阅读(45371) 评论(5)  编辑  收藏
评论:
  • # 下落预测方块代码  1094229563@qq.com Posted @ 2014-11-10 21:17
    楼主你好,我也在学习java俄罗斯方块游戏开发,现在想增加下落预测方块,带阴影(方块还没落下时,有个影子落在已经落好的方块上),这个阴影方块的代码怎么也不会做,望楼主不吝赐教  回复  更多评论   

  • # re: 一个用JAVA写的俄罗斯方块(基本仅代码&代码附详细解释)  zuidaima Posted @ 2015-01-04 22:36
    俄罗斯方块游戏源代码下载:http://zuidaima.com/share/k%E4%BF%84%E7%BD%97%E6%96%AF%E6%96%B9%E5%9D%97-p1-s1.htm  回复  更多评论   

  • # re: 一个用JAVA写的俄罗斯方块(基本仅代码&代码附详细解释)  ewqt Posted @ 2016-02-14 15:24
    sdfwegfwegf  回复  更多评论   

  • # re: 一个用JAVA写的俄罗斯方块(基本仅代码&代码附详细解释)  陌上花开 Posted @ 2016-06-14 10:09
    好像连main方法都没有啊 怎么运行  回复  更多评论   

  • # re: 一个用JAVA写的俄罗斯方块(基本仅代码&代码附详细解释)[未登录]  gary Posted @ 2016-08-11 23:50
    @陌上花开 倒数5行啊  回复  更多评论   


只有注册用户登录后才能发表评论。


网站导航:
 
 
Copyright © Adol Powered by: 博客园 模板提供:沪江博客