本文实例为大家分享了java实现俄罗斯方块的具体代码,供大家参考,具体内容如下
使用一个二维数组保存游戏的地图:
1
2
|
// 游戏地图格子,每个格子保存一个方块,数组纪录方块的状态 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 ); } } |
通过随机数的方式产生方块所组成的几种图形,一般七种图形:条形、田形、正7形、反7形、t形、z形和反z形,如生成条形:
1
2
|
map[ 0 ][randpos] = map[ 0 ][randpos - 1 ] = map[ 0 ][randpos + 1 ] = map[ 0 ][randpos + 2 ] = state.active; |
生成图形后,实现下落的操作。如果遇到阻碍,则不能再继续下落:
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; // 有阻碍,不用再循环判断行 } 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; // 有阻碍,不用再循环判断列 } } if (hasblock) break; // 有阻碍,不用再循环判断行 } } /* 左边没有阻碍,则将图形向左移动一个块的距离 */ 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(); } } |
向下加速移动时,就是减小每次正常状态下落的时间间隔:
1
2
3
4
5
6
7
|
/** * 向下直走 */ private void down() { // 标记可以加速下落 immediate = true ; } |
如何变换图形方向,这里仅使用了非常简单的方法来实现方向变换,当然可以有更优的算法实现方向变换操作,大家可以自己研究:
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 ) { // 条状 // 临时数组,放置旋转后图形 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 { // 临时数组,放置旋转后图形 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) { // 遇到数组下标越界,说明不能变换图形形状,不作任何处理 } } |
当图形下落遇到阻碍时停止,我们就需要判断这时是否有某一行或几行可以消除掉,这时可以先获取每行中方块的个数,然后再进行判断:
1
2
3
4
5
6
7
8
9
10
|
int [] blockscount = new int [rows]; // 记录每行有方块的列数 int eliminaterows = 0 ; // 消除的行数 /* 计算每行方块数量 */ 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
|
/* 实现有满行的方块消除操作 */ 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++; // 记录消除行数 } } |
最后我们再重绘显示积分就可以了。
重复以上的生成图形、图形下落、左右下移动、判断消除行的操作,一个简单的俄罗斯方块就完成了。
运行效果:
完整示例代码:俄罗斯方块
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。
原文链接:https://blog.csdn.net/zhliro/article/details/45746719