最近一直在测试前些日子写的俄罗斯方块(SWT),发现了几个BUG(只能说我还比较菜,没设计好):

1.方块类Block的clear和draw方法由于两个线程(一个是主线程,一个是定时器线程)都要调用,而且之前我没做好线程的同步,所以会随机发生该擦除的方块没能及时擦除,或是两个小方块重合.

修正方法:
主线程是在方块的左移,右移,下移,变形,直降 即 moveLeft(),moveRight(),moveDown(),rotateClock(),fall() 这些方法中调用Block的clear和draw方法的,定时器线程是在线程活动时调用moveDown(),所以,moveDown()就成了临界区,不能保证被调用的顺序,所以需要使他们同步,要使他们同步,只需将他们都写到一个方法里,即 move(moveSuit type),并且将move方法同步,即加关键字synchronized即可.

2.还是线程没有同步造成的问题,在定时器线程活动时会判断方块是否能下落,如果能就下落,在主线程中,按"下"或空格也会执行前句所说的任务,但由于是两个线程各自判断方块是否能下落,所以判断是否能下落的方法和下移方法的调用顺序不能被保证,所以有时会发生这样的情况:按住下,方块有时会下落到超出面板一格,或是几个方块重合,即主线程判断方块不能下落,但定时器线程在主线程判断方块不能下落之前,判断方块可以下落,于是方块就多下落了一格,这个顺序为:定时线程判断可以下落 -> 主线程判断不能下落 -> 主线程不动 -> 定时线程让方块下落 -> 造成异常发生或方块重合现象.

修正方法:
在 move(moveSuit type)方法的MOVEDOWN情况中,再一次判断方块是否能下落,move(moveSuit type)方法是同步的,所以可以很好的解决这个问题.

1,2修正后代码如下:
public enum MoveSuit {
        MOVELEFT,
        MOVERIGHT,
        MOVEDOWN,
        ROTATE,
        FALL
    }


    
//移动方法,通过移动类型决定如何移动
    public synchronized void move(MoveSuit type, TetrisBoard tetrisBoard){
        
        
switch(type){
        
        
case MOVELEFT:
            moveLeft();
            
break;
        
case MOVERIGHT:
            moveRight();
            
break;
        
case MOVEDOWN:
            
if(tetrisBoard.canMoveDown(this))
                moveDown();
            
break;
        
case ROTATE:
            clear();
            rotateClock().draw();
            
break;
        
case FALL:
            fall(tetrisBoard);
            
break;
            
        }

    }


3.如果GameOver一次以后再TryAgain,游戏等级和方块下落间隔会在分数到达100分左右时突然变到刚才GameOver时的最高等级和方块下落间隔.

修正方法:
游戏等级和方块下落间隔都是通过消行总数判断的,之前我忘记再每次游戏开始时将消行总数设为0,所以只需要在TetrisBoard类中加一个setRemovedLines方法,在Game类中的startGame方法中调用setRemovedLines(0)即可.

4.每个小方块的边框原来我设为了白色,在两个大方块相临时会将其中一个大方块的一部分边框擦除,比较难看,如果把小方块长宽缩小一个象素,当两个大方块相临时,衔接处就会有两个边框,也不是很好看.

修正方法:将边框颜色设为背景色黑色,这样边框被擦除也看不出来,两个大方块衔接处只有一个边框,可以两全其美.虽然这个方法不太好...


BUG说完了,该说说新功能了,呵呵~

我又添加了一个可以记录并显示最好成绩信息的功能,玩游戏总得有个奔头么,嘿嘿!
第一次玩游戏时,最高分为0,最高等级为1,创造者姓名为"Are you the winner?"
当游戏gameover时,如果当前游戏分数大于最高分,就让玩家输入自己姓名,并将其和最高分数,等级加密后存入myTetris.dat.
重新打开游戏时,会从myTetris.dat中读取信息并解密,并将最高分,最高等级和最高分创造者显示在游戏界面上

最后添张图:


最后把jar包和源代码放出来!希望大家给我留言,互相交流,嘿嘿!
以前忘说了,如果想让帮助正常显示的话,需要在和jar包同级目录下新建个文件夹叫pics,然后在里面放一个叫logo的图片.
myTetris下载地址
谢谢大家对我的支持!


 



what the hell is going on ??!!