服务器之家:专注于服务器技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - Java教程 - java代码实现俄罗斯方块

java代码实现俄罗斯方块

2021-05-11 14:12angry_youth Java教程

这篇文章主要为大家详细介绍了java代码实现俄罗斯方块,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

本文实例为大家分享了java实现俄罗斯方块的具体代码,供大家参考,具体内容如下

俄罗斯方块设计思想

俄罗斯方块都从小玩到大吧,什么规则大家都知道了吧,以前感觉那玩意贼好玩,但是就是老赢不了,现在学会了自己写一个天天练!

键盘操作:

左键:左移; 右键:右移;
上键:变换造型 下键:加速下掉(没毛病吧,没有继续整)

任意一行的方块满格,这一行就消除,消除一行方块得10分,目前小主我还没有设置关卡,各位喜欢的宝宝们可以自己设置关卡哦;

那么那些方块的造型到底从哪里来的呢,那就是我们自己设计的,常见的几种造型就是:i型,t型,l型,田字格型等等吧,自己个加呗!
那么到底咋整的咧?其实啊就是一个4*4的数组,当然了你开心设计n*n也可以,你牛皮你说了算!
那么下面举了一个例子,用来告诉你们为啥你们看见的造型可以变换的原因就是这样提前设计好,0为空,1为填充格,这样你就可以在你的游戏里面凹造型了!

java代码实现俄罗斯方块

算了:直接放图先看代码运行结果吧:

java代码实现俄罗斯方块

喜欢吗?喜欢就直接做吧,可能代码写的不够好,请各位大神多多包涵,我回头也会多总结,会不断更新代码的;

gamepanel类:游戏界面类,整个方块掉落和显示,游戏的逻辑斯洛都在这个类里面实现;

?
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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
package tetris;
 
import java.awt.graphics;
import java.awt.event.actionevent;
import java.awt.event.actionlistener;
import java.awt.event.keyevent;
import java.awt.event.keylistener;
import java.util.random;
 
import javax.swing.joptionpane;
import javax.swing.jpanel;
import javax.swing.timer;
 
public class gamepanel extends jpanel implements keylistener{
 private int maprow = 21;
 private int mapcol = 12;
 private int mapgame[][] = new int[maprow][mapcol];//开辟一个二维数组空间,用来存放我们的地图信息
 
 private timer timer;
 private int score = 0;//记录成绩
 random random = new random();
 private int curshapetype = -1;
 private int curshapestate = -1;//设置当前的形状类型和当前的形状状态
 private int nextshapetype = -1;
 private int nextshapestate = -1;//设置下一次出现的方块组的类型和状态
 
 private int posx = 0;
 private int posy = 0;
 
 private final int shapes[][][] = new int[][][]{
  //t字形按逆时针的顺序存储
  {
  {0,1,0,0, 1,1,1,0, 0,0,0,0, 0,0,0,0},
  {0,1,0,0, 1,1,0,0, 0,1,0,0, 0,0,0,0},
  {1,1,1,0, 0,1,0,0, 0,0,0,0, 0,0,0,0},
  {0,1,0,0, 0,1,1,0, 0,1,0,0, 0,0,0,0}
  },
  //i字形按逆时针的顺序存储
  {
  {0,0,0,0, 1,1,1,1, 0,0,0,0, 0,0,0,0},
  {0,1,0,0, 0,1,0,0, 0,1,0,0, 0,1,0,0},
  {0,0,0,0, 1,1,1,1, 0,0,0,0, 0,0,0,0},
  {0,1,0,0, 0,1,0,0, 0,1,0,0, 0,1,0,0}
  },
  //倒z形按逆时针的顺序存储
  {
  {0,1,1,0, 1,1,0,0, 0,0,0,0, 0,0,0,0},
  {1,0,0,0, 1,1,0,0, 0,1,0,0, 0,0,0,0},
  {0,1,1,0, 1,1,0,0, 0,0,0,0, 0,0,0,0},
  {1,0,0,0, 1,1,0,0, 0,1,0,0, 0,0,0,0}
  },
  //z形按逆时针的顺序存储
  {
  {1,1,0,0, 0,1,1,0, 0,0,0,0, 0,0,0,0},
  {0,1,0,0, 1,1,0,0, 1,0,0,0, 0,0,0,0},
  {1,1,0,0, 0,1,1,0, 0,0,0,0, 0,0,0,0},
  {0,1,0,0, 1,1,0,0, 1,0,0,0, 0,0,0,0}
  },
  //j字形按逆时针的顺序存储
  {
  {0,1,0,0, 0,1,0,0, 1,1,0,0, 0,0,0,0},
  {1,1,1,0, 0,0,1,0, 0,0,0,0, 0,0,0,0},
  {1,1,0,0, 1,0,0,0, 1,0,0,0, 0,0,0,0},
  {1,0,0,0, 1,1,1,0, 0,0,0,0, 0,0,0,0}
  },
  //l字形按逆时针的顺序存储
  {
  {1,0,0,0, 1,0,0,0, 1,1,0,0, 0,0,0,0},
  {0,0,1,0, 1,1,1,0, 0,0,0,0, 0,0,0,0},
  {1,1,0,0, 0,1,0,0, 0,1,0,0, 0,0,0,0},
  {1,1,1,0, 1,0,0,0, 0,0,0,0, 0,0,0,0}
  },
  //田字形按逆时针的顺序存储
  {
  {1,1,0,0, 1,1,0,0, 0,0,0,0, 0,0,0,0},
  {1,1,0,0, 1,1,0,0, 0,0,0,0, 0,0,0,0},
  {1,1,0,0, 1,1,0,0, 0,0,0,0, 0,0,0,0},
  {1,1,0,0, 1,1,0,0, 0,0,0,0, 0,0,0,0}
  }
 };
 private int rowrect = 4;
 private int colrect = 4;//这里我们把存储的图像看成是一个4*4的二维数组,虽然在上面我们采用一维数组来存储,但实际还是要看成二维数组来实现
 private int rectwidth = 10;
 
 public gamepanel()//构造函数----创建好地图
 {
 createrect();
 initmap();//初始化这个地图
 setwall();//设置墙
// createrect();
 timer = new timer(500,new timerlistener());
 timer.start();
 }
 
 class timerlistener implements actionlistener{
 public void actionperformed(actionevent e)
 {
  movedown();
 }
 }
 
 public void setwall()//第0列和第11列都是墙,第20行也是墙
 {
 for(int i = 0; i < maprow; i++)//先画列
 {
  mapgame[i][0] = 2;
  mapgame[i][11] = 2;
 }
 for(int j = 1; j < mapcol-1; j++)//画最后一行
 {
  mapgame[20][j] = 2;
 }
 }
 
 public void initmap()//初始化这个地图,墙的id是2,空格的id是0,方块的id是1
 {
 for(int i = 0; i < maprow; i++)
 {
  for(int j = 0; j < mapcol; j++)
  {
  mapgame[i][j] = 0;
  }
 }
 }
 
 public void createrect()//创建方块---如果当前的方块类型和状态都存在就设置下一次的,如果不存在就设置当前的并且设置下一次的状态和类型
 {
 if(curshapetype == -1 && curshapestate == -1)//当前的方块状态都为1,表示游戏才开始
 {
  curshapetype = random.nextint(shapes.length);
  curshapestate = random.nextint(shapes[0].length);
 }
 else
 {
  curshapetype = nextshapetype;
  curshapestate = nextshapestate;
 }
 nextshapetype = random.nextint(shapes.length);
 nextshapestate = random.nextint(shapes[0].length);
 posx = 0;
 posy = 1;//墙的左上角创建方块
 if(gameover(posx,posy,curshapetype,curshapestate))
 {
  joptionpane.showconfirmdialog(null, "游戏结束!", "提示", joptionpane.ok_option);
  system.exit(0);
 }
 }
 
 
 public boolean gameover(int x, int y, int shapetype, int shapestate)//判断游戏是否结束
 {
 if(isornomove(x,y,shapetype,shapestate))
 {
  return false;
 }
 return true;
 }
 
 public boolean isornomove(int x, int y, int shapetype, int shapestate)//判断当前的这个图形是否可以移动,这里重点强调x,y的坐标是指4*4的二维数组(描述图形的那个数组)的左上角目标
 {
 for(int i = 0; i < rowrect ; i++)
 {
  for(int j = 0; j < colrect; j++)
  {
  if(shapes[shapetype][shapestate][i*colrect+j] == 1 && mapgame[x+i][y+j] == 1
  || shapes[shapetype][shapestate][i*colrect+j] == 1 && mapgame[x+i][y+j] == 2)
  {
   return false;
  }
  }
 }
 return true;
 }
 
 
 public void turn()//旋转
 {
 int temp = curshapestate;
 curshapestate = (curshapestate+1) % shapes[0].length;
 if(isornomove(posx,posy,curshapetype,curshapestate))
 {
 }
 else
 {
  curshapestate = temp;
 }
 repaint();
 }
 
 public void movedown()//向下移动
 {
 if(isornomove(posx+1,posy,curshapetype,curshapestate))
 {
  posx++;
 }
 else
 {
  addtomap();//将此行固定在地图中
  checkline();
  createrect();//重新创建一个新的方块
 }
 repaint();
 }
 
 public void moveleft()//向左移动
 {
 if(isornomove(posx,posy-1,curshapetype,curshapestate))
 {
  posy--;
 }
 repaint();
 }
 
 public void moveright()//向右移动
 {
 if(isornomove(posx,posy+1,curshapetype,curshapestate))
 {
  posy++;
 }
 repaint();
 }
 
 public void addtomap()//固定掉下来的这一图像到地图中
 {
 for(int i = 0; i < rowrect; i++)
 {
  for(int j = 0; j < colrect; j++)
  {
  if(shapes[curshapetype][curshapestate][i*colrect+j] == 1)
  {
   mapgame[posx+i][posy+j] = shapes[curshapetype][curshapestate][i*colrect+j];
  }
  }
 }
 }
 
 public void checkline()//检查一下这些行中是否有满行的
 {
 int count = 0;
 for(int i = maprow-2; i >= 0; i--)
 {
  count = 0;
  for(int j = 1; j < mapcol-1; j++)
  {
  if(mapgame[i][j] == 1)
  {
   count++;
  }
  else
   break;
  }
  if(count >= mapcol-2)
  {
  for(int k = i; k > 0; k--)
  {
   for(int p = 1; p < mapcol-1; p++)
   {
   mapgame[k][p] = mapgame[k-1][p];
   }
  }
  score += 10;
  i++;
  }
 }
 }
 
 public void paint(graphics g)//重新绘制窗口
 {
 super.paint(g);
 for(int i = 0; i < rowrect; i++)//绘制正在下落的方块
 {
  for(int j = 0; j < colrect; j++)
  {
  if(shapes[curshapetype][curshapestate][i*colrect+j] == 1)
  {
   g.fillrect((posy+j+1)*rectwidth, (posx+i+1)*rectwidth, rectwidth, rectwidth);
  }
  }
 }
 for(int i = 0; i < maprow; i++)//绘制地图上面已经固定好的方块信息
 {
  for(int j = 0; j < mapcol; j++)
  {
  if(mapgame[i][j] == 2)//画墙
  {
   g.drawrect((j+1)*rectwidth, (i+1)*rectwidth, rectwidth, rectwidth);
  }
  if(mapgame[i][j] == 1)//画小方格
  {
   g.fillrect((j+1)*rectwidth, (i+1)*rectwidth, rectwidth, rectwidth);
  }
  }
 }
 g.drawstring("score = "+ score, 225, 15);
 g.drawstring("下一个方块:", 225, 50);
 for(int i = 0; i < rowrect; i++)
 {
  for(int j = 0; j < colrect; j++)
  {
  if(shapes[nextshapetype][nextshapestate][i*colrect+j] == 1)
  {
   g.fillrect(225+(j*rectwidth), 100+(i*rectwidth), rectwidth, rectwidth);
  }
  }
 }
 }
 
 public void newgame()//游戏重新开始
 {
 score = 0;
 initmap();
 setwall();
 createrect();
 repaint();
 }
 
 public void stopgame()//游戏暂停
 {
 timer.stop();
 }
 
 public void continuegame()
 {
 timer.start();
 }
 
 @override
 public void keytyped(keyevent e) {
 
 }
 
 @override
 public void keypressed(keyevent e) {
 switch(e.getkeycode())
 {
 case keyevent.vk_up://上----旋转
  turn();
  break;
 case keyevent.vk_down://下----向下移动
  movedown();
  break;
 case keyevent.vk_left://左----向左移动
  moveleft();
  break;
 case keyevent.vk_right://右----向右移动
  moveright();
  break;
 }
 
 }
 
 @override
 public void keyreleased(keyevent e) {
 // todo auto-generated method stub
 
 }
 
}

gameframe类:整个游戏的进入口,好吧,说白了就是有main()函数的类,这个类里面实现游戏界面的一些设计,你可以理解为一个小小小小的ui;

?
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
package tetris;
 
import java.awt.event.actionevent;
import java.awt.event.actionlistener;
 
import javax.swing.jframe;
import javax.swing.jmenu;
import javax.swing.jmenubar;
import javax.swing.jmenuitem;
import javax.swing.joptionpane;
 
public class gameframe extends jframe implements actionlistener{
 private int widthframe = 500;
 private int heightframe = 600;
 private jmenu menuone = new jmenu("游戏");//创建一个菜单
 private jmenuitem newgame = menuone.add("重新开始");//创建一个内置菜单选项
 private jmenuitem exitgame = menuone.add("游戏退出");
 private jmenuitem stopgame = menuone.add("游戏暂停");
 private jmenuitem goongame = menuone.add("游戏继续");
 
 private jmenu menutwo = new jmenu("帮助");//创建第二个菜单
 private jmenuitem aboutgame = menutwo.add("关于游戏");
 gamepanel gamepanel = new gamepanel();
 
 public gameframe()//构造函数
 {
 addkeylistener(gamepanel);
 newgame.addactionlistener(this);
 exitgame.addactionlistener(this);
 stopgame.addactionlistener(this);
 goongame.addactionlistener(this);
 aboutgame.addactionlistener(this);
 
 this.add(gamepanel);
 
 jmenubar menu = new jmenubar();
 menu.add(menuone);
 menu.add(menutwo);
 this.setjmenubar(menu);
 
 this.settitle("俄罗斯方块");
 this.setbounds(50, 10, widthframe, heightframe);
 this.setvisible(true);
 this.setdefaultcloseoperation(jframe.exit_on_close);
 
 }
 
 public void actionperformed(actionevent e)
 {
 if(e.getsource() == newgame)//游戏重新开始
 {
  gamepanel.newgame();
 }
 if(e.getsource() == exitgame)//游戏退出
 {
  system.exit(0);
 }
 if(e.getsource() == stopgame)//游戏暂停
 {
  gamepanel.stopgame();
 }
 if(e.getsource() == goongame)//游戏继续
 {
  gamepanel.continuegame();
 }
 if(e.getsource() == aboutgame)//关于游戏信息
 {
  joptionpane.showmessagedialog(null, "左右键移动,向上建旋转", "提示", joptionpane.ok_option);
 }
 }
 
 
 public static void main(string[] args) {
 new gameframe();
 }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。

原文链接:https://blog.csdn.net/angry_youth/article/details/74619096

延伸 · 阅读

精彩推荐