最近一直在測試前些日子寫的俄羅斯方塊(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 ??!!
