本文實例為大家分享了java實現(xiàn)俄羅斯方塊的具體代碼,供大家參考,具體內容如下
使用一個二維數(shù)組保存游戲的地圖:
1
2
|
// 游戲地圖格子,每個格子保存一個方塊,數(shù)組紀錄方塊的狀態(tài) private state map[][] = new state[rows][columns]; |
游戲前先將所有地圖中的格子初始化為空:
1
2
3
4
5
6
|
/* 初始化所有的方塊為空 */ for ( int i = 0 ; i < map.length; i++) { for ( int j = 0 ; j < map[i].length; j++) { map[i][j] = state.empty; } } |
玩游戲過程中,我們能夠看到界面上的方塊,那么就得將地圖中所有的方塊繪制出來,當然,除了需要繪制方塊外,游戲積分和游戲結束的字符串在必要的時候也需要繪制:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
/** * 繪制窗體內容,包括游戲方塊,游戲積分或結束字符串 */ @override public void paint(graphics g) { super .paint(g); for ( int i = 0 ; i < rows; i++) { for ( int j = 0 ; j < columns; j++) { if (map[i][j] == state.active) { // 繪制活動塊 g.setcolor(activecolor); g.fillroundrect(j * block_size, i * block_size + 25 , block_size - 1 , block_size - 1 , block_size / 5 , block_size / 5 ); } else if (map[i][j] == state.stoped) { // 繪制靜止塊 g.setcolor(stopedcolor); g.fillroundrect(j * block_size, i * block_size + 25 , block_size - 1 , block_size - 1 , block_size / 5 , block_size / 5 ); } } } /* 打印得分 */ g.setcolor(scorecolor); g.setfont( new font( "times new roman" , font.bold, 30 )); g.drawstring( "score : " + totalscore, 5 , 70 ); // 游戲結束,打印結束字符串 if (!isgoingon) { g.setcolor(color.red); g.setfont( new font( "times new roman" , font.bold, 40 )); g.drawstring( "game over !" , this .getwidth() / 2 - 140 , this .getheight() / 2 ); } } |
通過隨機數(shù)的方式產生方塊所組成的幾種圖形,一般七種圖形:條形、田形、正7形、反7形、t形、z形和反z形,如生成條形:
1
2
|
map[ 0 ][randpos] = map[ 0 ][randpos - 1 ] = map[ 0 ][randpos + 1 ] = map[ 0 ][randpos + 2 ] = state.active; |
生成圖形后,實現(xiàn)下落的操作。如果遇到阻礙,則不能再繼續(xù)下落:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
isfall = true ; // 是否能夠下落 // 從當前行檢查,如果遇到阻礙,則停止下落 for ( int i = 0 ; i < blockrows; i++) { for ( int j = 0 ; j < columns; j++) { // 遍歷到行中塊為活動塊,而下一行塊為靜止塊,則遇到阻礙 if (map[rowindex - i][j] == state.active && map[rowindex - i + 1 ][j] == state.stoped) { isfall = false ; // 停止下落 break ; } } if (!isfall) break ; } |
如果未遇到阻礙,則下落的時候,方塊圖形整體向下移動一行:
1
2
3
4
5
6
7
8
9
|
// 圖形下落一行 for ( int i = 0 ; i < blockrows; i++) { for ( int j = 0 ; j < columns; j++) { if (map[rowindex - i][j] == state.active) { // 活動塊向下移動一行 map[rowindex - i][j] = state.empty; // 原活動塊變成空塊 map[rowindex - i + 1 ][j] = state.active; // 下一行塊變成活動塊 } } } |
向左、向右方向移動時是類似的操作:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
/** * 向左走 */ private void left() { // 標記左邊是否有阻礙 boolean hasblock = false ; /* 判斷是否左邊有阻礙 */ for (int i = 0; i < blockrows; i++) { if (map[rowindex - i][0] == state.active) { // 判斷左邊是否為墻 hasblock = true; break; // 有阻礙,不用再循環(huán)判斷行 } else { for (int j = 1; j < columns; j++) { // 判斷左邊是否有其它塊 if (map[rowindex - i][j] == state.active && map[rowindex - i][j - 1] == state.stoped) { hasblock = true; break; // 有阻礙,不用再循環(huán)判斷列 } } if (hasblock) break; // 有阻礙,不用再循環(huán)判斷行 } } /* 左邊沒有阻礙,則將圖形向左移動一個塊的距離 */ if (!hasblock) { for ( int i = 0 ; i < blockrows; i++) { for ( int j = 1 ; j < columns; j++) { if (map[rowindex - i][j] == state.active) { map[rowindex - i][j] = state.empty; map[rowindex - i][j - 1 ] = state.active; } } } // 重繪 repaint(); } } |
向下加速移動時,就是減小每次正常狀態(tài)下落的時間間隔:
1
2
3
4
5
6
7
|
/** * 向下直走 */ private void down() { // 標記可以加速下落 immediate = true ; } |
如何變換圖形方向,這里僅使用了非常簡單的方法來實現(xiàn)方向變換,當然可以有更優(yōu)的算法實現(xiàn)方向變換操作,大家可以自己研究:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
|
/** * 旋轉方塊圖形 */ private void rotate() { try { if (shape == 4 ) { // 方形,旋轉前后是同一個形狀 return ; } else if (shape == 0 ) { // 條狀 // 臨時數(shù)組,放置旋轉后圖形 state[][] tmp = new state[ 4 ][ 4 ]; int startcolumn = 0 ; // 找到圖形開始的第一個方塊位置 for ( int i = 0 ; i < columns; i++) { if (map[rowindex][i] == state.active) { startcolumn = i; break ; } } // 查找旋轉之后是否有阻礙,如果有阻礙,則不旋轉 for ( int i = 0 ; i < 4 ; i++) { for ( int j = 0 ; j < 4 ; j++) { if (map[rowindex - 3 + i][j + startcolumn] == state.stoped) { return ; } } } if (map[rowindex][startcolumn + 1 ] == state.active) { // 橫向條形,變換為豎立條形 for ( int i = 0 ; i < 4 ; i++) { tmp[i][ 0 ] = state.active; for ( int j = 1 ; j < 4 ; j++) { tmp[i][j] = state.empty; } } blockrows = 4 ; } else { // 豎立條形,變換為橫向條形 for ( int j = 0 ; j < 4 ; j++) { tmp[ 3 ][j] = state.active; for ( int i = 0 ; i < 3 ; i++) { tmp[i][j] = state.empty; } } blockrows = 1 ; } // 將原地圖中圖形修改為變換后圖形 for ( int i = 0 ; i < 4 ; i++) { for ( int j = 0 ; j < 4 ; j++) { map[rowindex - 3 + i][startcolumn + j] = tmp[i][j]; } } } else { // 臨時數(shù)組,放置旋轉后圖形 state[][] tmp = new state[ 3 ][ 3 ]; int startcolumn = columns; // 找到圖形開始的第一個方塊位置 for ( int j = 0 ; j < 3 ; j++) { for ( int i = 0 ; i < columns; i++) { if (map[rowindex - j][i] == state.active) { startcolumn = i < startcolumn ? i : startcolumn; } } } // 判斷變換后是否會遇到阻礙 for ( int i = 0 ; i < 3 ; i++) { for ( int j = 0 ; j < 3 ; j++) { if (map[rowindex - 2 + j][startcolumn + 2 - i] == state.stoped) return ; } } // 變換 for ( int i = 0 ; i < 3 ; i++) { for ( int j = 0 ; j < 3 ; j++) { tmp[ 2 - j][i] = map[rowindex - 2 + i][startcolumn + j]; } } // 將原地圖中圖形修改為變換后圖形 for ( int i = 0 ; i < 3 ; i++) { for ( int j = 0 ; j < 3 ; j++) { map[rowindex - 2 + i][startcolumn + j] = tmp[i][j]; } } // 重繪 repaint(); // 重新修改行指針 for ( int i = 0 ; i < 3 ; i++) { for ( int j = 0 ; j < 3 ; j++) { if (map[rowindex - i][startcolumn + j] != null || map[rowindex - i][startcolumn + j] != state.empty) { rowindex = rowindex - i; blockrows = 3 ; return ; } } } } } catch (exception e) { // 遇到數(shù)組下標越界,說明不能變換圖形形狀,不作任何處理 } } |
當圖形下落遇到阻礙時停止,我們就需要判斷這時是否有某一行或幾行可以消除掉,這時可以先獲取每行中方塊的個數(shù),然后再進行判斷:
1
2
3
4
5
6
7
8
9
10
|
int [] blockscount = new int [rows]; // 記錄每行有方塊的列數(shù) int eliminaterows = 0 ; // 消除的行數(shù) /* 計算每行方塊數(shù)量 */ for ( int i = 0 ; i < rows; i++) { blockscount[i] = 0 ; for ( int j = 0 ; j < columns; j++) { if (map[i][j] == state.stoped) blockscount[i]++; } } |
如果有滿行的方塊,則消除掉該行方塊:
1
2
3
4
5
6
7
8
9
10
11
12
|
/* 實現(xiàn)有滿行的方塊消除操作 */ for ( int i = 0 ; i < rows; i++) { if (blockscount[i] == columns) { // 清除一行 for ( int m = i; m >= 0 ; m--) { for ( int n = 0 ; n < columns; n++) { map[m][n] = (m == 0 ) ? state.empty : map[m - 1 ][n]; } } eliminaterows++; // 記錄消除行數(shù) } } |
最后我們再重繪顯示積分就可以了。
重復以上的生成圖形、圖形下落、左右下移動、判斷消除行的操作,一個簡單的俄羅斯方塊就完成了。
運行效果:
完整示例代碼:俄羅斯方塊
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。
原文鏈接:https://blog.csdn.net/zhliro/article/details/45746719