- 1 import
- java.awt.*
- ;
- 2 import
- java.awt.event.*
- ;
- 3 import java.io.File;
- 4 import java.io.IOException;
- 5 import java.util.Random;
- 6 import
- javax.sound.sampled.*
- ;
- 7 import
- javax.swing.*
- ;
- 8
- 9 class Tile{
- 10 int x;
- 11 int y;
- 12
- 13 public
- Tile(
- int
- x0,
- int y0){
- 14
- x =
- x0;
- 15
- y =
- y0;
- 16 }
- 17 }
- 18
- 19 public class
- SnakeDemo
- extends JComponent{
- 20 /**
- 21 *
- 22 */
- 23 private static final long
- serialVersionUID = 3794762291171148906L
- ;
- 24 private final int
- MAX_SIZE = 400;
- //蛇身体最长为400节
- 25 private
- Tile temp =
- new
- Tile(0,0
- );
- 26 private
- Tile temp2 =
- new
- Tile(0,0
- );
- 27 private
- Tile head =
- new
- Tile(227,100);
- //头部的位置初始化为(227,100)
- 28 private
- Tile[] body =
- new Tile[MAX_SIZE];
- 29 private
- String direction = "R";
- //默认向右走
- 30 private
- String current_direction = "R";
- //当前方向
- 31 private boolean
- first_launch =
- false;
- 32 private boolean
- iseaten =
- false;
- 33 private boolean
- isrun =
- true;
- 34 private int randomx,randomy;
- 35 private int
- body_length = 5;
- //身体长度初始化为5
- 36 private Thread run;
- 37 private
- JLabel label =
- new
- JLabel("当前长度:"
- );
- 38 private
- JLabel label2 =
- new
- JLabel("所花时间:"
- );
- 39 private
- JLabel label3 =
- new
- JLabel("说 明:"
- );
- 40 private
- JTextArea explain =
- new
- JTextArea("此游戏是一个贪吃蛇Demo版本,实现简单地移动,得分,判断撞墙和自己的功能,"
- 41
- + "初始长度为6,头部为红色,身体颜色渐变。注意蛇走动的时候原路返回当做撞自己的身体。游戏本身代码只有300行,"
- 42
- + "加上一些显示,计时和音效后多了几百行。\n按上下左右键实现移动,按ESC重新开始"
- );
- 43 private
- JLabel Score =
- new
- JLabel("6"
- );
- 44 private
- JLabel Time =
- new
- JLabel(""
- );
- 45 private
- Font f =
- new
- Font("微软雅黑",Font.PLAIN,15
- );
- 46 private
- Font f2 =
- new
- Font("微软雅黑",Font.PLAIN,13
- );
- 47 private
- JPanel p =
- new JPanel();
- 48 private int
- hour =0
- ;
- 49 private int
- min =0
- ;
- 50 private int
- sec =0
- ;
- 51 private boolean
- suspended =
- false;
- 52
- 53 public SnakeDemo(){
- 54
- String lookAndFeel =
- UIManager.getSystemLookAndFeelClassName();
- 55 try {
- 56 UIManager.setLookAndFeel(lookAndFeel);
- 57
- }
- catch (ClassNotFoundException e1) {
- 58 // TODO 自动生成的 catch 块
- 59 e1.printStackTrace();
- 60
- }
- catch (InstantiationException e1) {
- 61 // TODO 自动生成的 catch 块
- 62 e1.printStackTrace();
- 63
- }
- catch (IllegalAccessException e1) {
- 64 // TODO 自动生成的 catch 块
- 65 e1.printStackTrace();
- 66
- }
- catch (UnsupportedLookAndFeelException e1) {
- 67 // TODO 自动生成的 catch 块
- 68 e1.printStackTrace();
- 69 }
- 70
- 71 //布局
- 72 add(label);
- 73
- label.setBounds(500, 10, 80, 20
- );
- 74 label.setFont(f);
- 75 add(Score);
- 76
- Score.setBounds(500, 35, 80, 20
- );
- 77 Score.setFont(f);
- 78 add(label2);
- 79
- label2.setBounds(500, 60, 80, 20
- );
- 80 label2.setFont(f);
- 81 add(Time);
- 82
- Time.setBounds(500, 85, 80, 20
- );
- 83 Time.setFont(f);
- 84 add(p);
- 85
- p.setBounds(498, 110, 93, 1
- );
- 86 p.setBorder(BorderFactory.createLineBorder(Color.black));
- 87
- 88 add(label3);
- 89
- label3.setBounds(500, 115, 80, 20
- );
- 90 label3.setFont(f);
- 91 add(explain);
- 92
- explain.setBounds(498, 138, 100, 350
- );
- 93 explain.setFont(f2);
- 94
- explain.setLineWrap(
- true);
- 95
- explain.setOpaque(
- false);
- 96
- 97 for
- (
- int
- i = 0; i < MAX_SIZE;i++
- )
- 98 {
- 99
- body[i] =
- new
- Tile(0,0
- );
- 100 }
- 101
- 102
- addKeyListener(
- new KeyAdapter() {
- 103 public void keyPressed(KeyEvent e) {
- 104 super.keyPressed(e);
- 105 if
- (e.getKeyCode() ==
- KeyEvent.VK_RIGHT)
- 106 {
- 107
- direction = "R"
- ;
- 108 }
- 109 if
- (e.getKeyCode() ==
- KeyEvent.VK_LEFT)
- 110 {
- 111
- direction = "L"
- ;
- 112 }
- 113 if
- (e.getKeyCode() ==
- KeyEvent.VK_UP)
- 114 {
- 115
- direction = "U"
- ;
- 116 }
- 117 if
- (e.getKeyCode() ==
- KeyEvent.VK_DOWN)
- 118 {
- 119
- direction = "D"
- ;
- 120 }
- 121 if
- (e.getKeyCode() ==
- KeyEvent.VK_ESCAPE)
- 122 {
- 123
- direction = "R";
- //默认向右走
- 124
- current_direction = "R";
- //当前方向
- 125
- first_launch =
- false;
- 126
- iseaten =
- false;
- 127
- isrun =
- true;
- 128
- body_length = 5
- ;
- 129
- head =
- new
- Tile(227,100
- );
- 130
- Score.setText("6"
- );
- 131
- hour =0
- ;
- 132
- min =0
- ;
- 133
- sec =0
- ;
- 134 for
- (
- int
- i = 0; i < MAX_SIZE;i++
- )
- 135 {
- 136
- body[i].x = 0
- ;
- 137
- body[i].y = 0
- ;
- 138 }
- 139
- 140
- run =
- new Thread();
- 141 run.start();
- 142
- System.out.println("Start again"
- );
- 143 }
- 144 // if(e.getKeyCode() == KeyEvent.VK_SPACE)//按空格键开始和暂停暂时没做,还在思考中
- 145 // {
- 146 // if(!suspended)
- 147 // {
- 148 // synchronized(run)
- 149 // {
- 150 // try {
- 151 // run.wait();
- 152 // } catch (InterruptedException e1) {
- 153 // e1.printStackTrace();
- 154 // }
- 155 // }
- 156 // }
- 157 // //notify();
- 158 // }
- 159 }
- 160 });
- 161
- 162 new Timer();
- 163
- 164
- setFocusable(
- true);
- 165 }
- 166
- 167 public void paintComponent(Graphics g1){
- 168 super.paintComponent(g1);
- 169
- Graphics2D g =
- (Graphics2D) g1;
- 170 g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
- 171 g.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,RenderingHints.VALUE_STROKE_NORMALIZE);
- 172
- 173 //画头部
- 174 g.setColor(Color.red);
- 175
- g.fillRoundRect(head.x, head.y, 20, 20, 10, 10
- );
- 176
- 177
- g.setPaint(
- new
- GradientPaint(115,135,Color.CYAN,230,135,Color.MAGENTA,
- true));
- 178 if
- (!
- first_launch)
- 179 {
- 180 //初始化身体
- 181 int
- x =
- head.x;
- 182 for
- (
- int
- i = 0;i < body_length;i++
- )
- 183 {
- 184
- x -= 22;
- //相邻两个方块的间距为2个像素,方块宽度都为20像素
- 185
- body[i].x =
- x;
- 186
- body[i].y =
- head.y;
- 187
- g.fillRoundRect(body[i].x, body[i].y, 20, 20, 10, 10
- );
- 188 }
- 189 //初始化食物位置
- 190 ProduceRandom();
- 191
- g.fillOval(randomx, randomy, 19, 19
- );
- 192 }
- 193 else
- 194 {
- 195 //每次刷新身体
- 196 for
- (
- int
- i = 0;i < body_length;i++
- )
- 197 {
- 198
- g.fillRoundRect(body[i].x, body[i].y, 20, 20, 10, 10
- );
- 199 }
- 200
- 201 if
- (EatFood())
- //被吃了重新产生食物
- 202 {
- 203 ProduceRandom();
- 204
- g.fillOval(randomx, randomy, 19, 19
- );
- 205
- iseaten =
- false;
- 206 }
- 207 else
- 208 {
- 209
- g.fillOval(randomx, randomy, 19, 19
- );
- 210 }
- 211 }
- 212
- first_launch =
- true;
- 213 //墙
- 214
- g.setStroke(
- new
- BasicStroke(4
- ,BasicStroke.CAP_BUTT,BasicStroke.JOIN_BEVEL));
- 215 g.setBackground(Color.black);
- 216
- g.drawRect(2, 7, 491, 469
- );
- 217
- 218 //网格线
- 219 for
- (
- int
- i = 1;i < 22;i++
- )
- 220 {
- 221
- g.setStroke(
- new
- BasicStroke(1
- ,BasicStroke.CAP_BUTT,BasicStroke.JOIN_BEVEL));
- 222 g.setColor(Color.black);
- 223
- g.drawLine(5+i*22,9,5+i*22,472
- );
- 224 if
- (i <= 20
- )
- 225 {
- 226
- g.drawLine(4,10+i*22,491,10+i*22
- );
- 227 }
- 228 }
- 229 }
- 230
- 231 public void ProduceRandom(){
- 232 boolean
- flag =
- true;
- 233
- Random rand =
- new Random();
- 234
- randomx = (rand.nextInt(21) + 1) * 22 + 7
- ;
- 235
- randomy = (rand.nextInt(20) + 1) *22 + 12
- ;
- 236 while(flag)
- 237 {
- 238 for
- (
- int
- i = 0;i < body_length; i++
- )
- 239 {
- 240 if
- (body[i].x == randomx && body[i].y ==
- randomy)
- 241 {
- 242
- randomx = (rand.nextInt(21) + 1) * 22 + 7
- ;
- 243
- randomy = (rand.nextInt(20) + 1) *22 + 12
- ;
- 244
- flag =
- true;
- 245 break;
- 246 }
- 247 else
- 248 {
- 249 if
- (i == body_length - 1
- )
- 250 {
- 251
- flag =
- false;
- 252 }
- 253 }
- 254 }
- 255 }
- 256 }
- 257
- 258 public void
- HitWall(){
- //判断是否撞墙
- 259 if
- (current_direction == "L"
- )
- 260 {
- 261 if
- (head.x < 7
- )
- 262 {
- 263 new
- AePlayWave("over.wav"
- ).start();
- 264
- isrun =
- false;
- 265 int
- result=JOptionPane.showConfirmDialog(
- null
- , "Game over! Try again?", "Information"
- , JOptionPane.YES_NO_OPTION);
- 266 if
- (result==
- JOptionPane.YES_NO_OPTION)
- 267 {
- 268
- direction = "R";
- //默认向右走
- 269
- current_direction = "R";
- //当前方向
- 270
- first_launch =
- false;
- 271
- iseaten =
- false;
- 272
- isrun =
- true;
- 273
- body_length = 5
- ;
- 274
- head =
- new
- Tile(227,100
- );
- 275
- Score.setText("6"
- );
- 276
- hour =0
- ;
- 277
- min =0
- ;
- 278
- sec =0
- ;
- 279 for
- (
- int
- i = 0; i < MAX_SIZE;i++
- )
- 280 {
- 281
- body[i].x = 0
- ;
- 282
- body[i].y = 0
- ;
- 283 }
- 284
- 285
- run =
- new Thread();
- 286 run.start();
- 287
- System.out.println("Start again"
- );
- 288 }
- 289 else
- 290 {
- 291 run.stop();
- 292 }
- 293 }
- 294 }
- 295 if
- (current_direction == "R"
- )
- 296 {
- 297 if
- (head.x > 489
- )
- 298 {
- 299 new
- AePlayWave("over.wav"
- ).start();
- 300
- isrun =
- false;
- 301 int
- result=JOptionPane.showConfirmDialog(
- null
- , "Game over! Try again?", "Information"
- , JOptionPane.YES_NO_OPTION);
- 302 if
- (result==
- JOptionPane.YES_NO_OPTION)
- 303 {
- 304
- direction = "R";
- //默认向右走
- 305
- current_direction = "R";
- //当前方向
- 306
- first_launch =
- false;
- 307
- iseaten =
- false;
- 308
- isrun =
- true;
- 309
- body_length = 5
- ;
- 310
- head =
- new
- Tile(227,100
- );
- 311
- Score.setText("6"
- );
- 312
- hour =0
- ;
- 313
- min =0
- ;
- 314
- sec =0
- ;
- 315 for
- (
- int
- i = 0; i < MAX_SIZE;i++
- )
- 316 {
- 317
- body[i].x = 0
- ;
- 318
- body[i].y = 0
- ;
- 319 }
- 320
- 321
- run =
- new Thread();
- 322 run.start();
- 323
- System.out.println("Start again"
- );
- 324 }
- 325 else
- 326 {
- 327 run.stop();
- 328 }
- 329 }
- 330 }
- 331 if
- (current_direction == "U"
- )
- 332 {
- 333 if
- (head.y < 12
- )
- 334 {
- 335 new
- AePlayWave("over.wav"
- ).start();
- 336
- isrun =
- false;
- 337 int
- result=JOptionPane.showConfirmDialog(
- null
- , "Game over! Try again?", "Information"
- , JOptionPane.YES_NO_OPTION);
- 338 if
- (result==
- JOptionPane.YES_NO_OPTION)
- 339 {
- 340
- direction = "R";
- //默认向右走
- 341
- current_direction = "R";
- //当前方向
- 342
- first_launch =
- false;
- 343
- iseaten =
- false;
- 344
- isrun =
- true;
- 345
- body_length = 5
- ;
- 346
- head =
- new
- Tile(227,100
- );
- 347
- Score.setText("6"
- );
- 348
- hour =0
- ;
- 349
- min =0
- ;
- 350
- sec =0
- ;
- 351 for
- (
- int
- i = 0; i < MAX_SIZE;i++
- )
- 352 {
- 353
- body[i].x = 0
- ;
- 354
- body[i].y = 0
- ;
- 355 }
- 356
- 357
- run =
- new Thread();
- 358 run.start();
- 359
- System.out.println("Start again"
- );
- 360 }
- 361 else
- 362 {
- 363 run.stop();
- 364 }
- 365 }
- 366 }
- 367 if
- (current_direction == "D"
- )
- 368 {
- 369 if
- (head.y > 472
- )
- 370 {
- 371 new
- AePlayWave("over.wav"
- ).start();
- 372
- isrun =
- false;
- 373 int
- result=JOptionPane.showConfirmDialog(
- null
- , "Game over! Try again?", "Information"
- , JOptionPane.YES_NO_OPTION);
- 374 if
- (result==
- JOptionPane.YES_NO_OPTION)
- 375 {
- 376
- direction = "R";
- //默认向右走
- 377
- current_direction = "R";
- //当前方向
- 378
- first_launch =
- false;
- 379
- iseaten =
- false;
- 380
- isrun =
- true;
- 381
- body_length = 5
- ;
- 382
- head =
- new
- Tile(227,100
- );
- 383
- Score.setText("6"
- );
- 384
- hour =0
- ;
- 385
- min =0
- ;
- 386
- sec =0
- ;
- 387 for
- (
- int
- i = 0; i < MAX_SIZE;i++
- )
- 388 {
- 389
- body[i].x = 0
- ;
- 390
- body[i].y = 0
- ;
- 391 }
- 392
- 393
- run =
- new Thread();
- 394 run.start();
- 395
- System.out.println("Start again"
- );
- 396 }
- 397 else
- 398 {
- 399 run.stop();
- 400 }
- 401 }
- 402 }
- 403 }
- 404
- 405 public void
- HitSelf(){
- //判断是否撞到自己身上
- 406 for
- (
- int
- i = 0;i < body_length; i++
- )
- 407 {
- 408 if
- (body[i].x == head.x && body[i].y ==
- head.y)
- 409 {
- 410 new
- AePlayWave("over.wav"
- ).start();
- 411
- isrun =
- false;
- 412 int
- result=JOptionPane.showConfirmDialog(
- null
- , "Game over! Try again?", "Information"
- , JOptionPane.YES_NO_OPTION);
- 413 if
- (result==
- JOptionPane.YES_NO_OPTION)
- 414 {
- 415
- direction = "R";
- //默认向右走
- 416
- current_direction = "R";
- //当前方向
- 417
- first_launch =
- false;
- 418
- iseaten =
- false;
- 419
- isrun =
- true;
- 420
- body_length = 5
- ;
- 421
- head =
- new
- Tile(227,100
- );
- 422
- Score.setText("6"
- );
- 423
- hour =0
- ;
- 424
- min =0
- ;
- 425
- sec =0
- ;
- 426 for
- (
- int
- j = 0; j < MAX_SIZE;j++
- )
- 427 {
- 428
- body[j].x = 0
- ;
- 429
- body[j].y = 0
- ;
- 430 }
- 431
- 432
- run =
- new Thread();
- 433 run.start();
- 434
- System.out.println("Start again"
- );
- 435 }
- 436 else
- 437 {
- 438 run.stop();
- 439 }
- 440 break;
- 441 }
- 442 }
- 443 }
- 444
- 445 public boolean EatFood(){
- 446 if
- (head.x == randomx && head.y ==
- randomy)
- 447 {
- 448
- iseaten =
- true;
- 449 return true;
- 450 }
- 451 else
- 452 {
- 453 return false;
- 454 }
- 455 }
- 456
- 457 public void Thread(){
- 458 long
- millis = 300;
- //每隔300毫秒刷新一次
- 459
- run =
- new Thread() {
- 460 public void run() {
- 461 while
- (
- true)
- 462 {
- 463 try {
- 464 Thread.sleep(millis);
- 465
- }
- catch (InterruptedException ex) {
- 466 ex.printStackTrace();
- 467 }
- 468
- 469
- temp.x =
- head.x;
- 470
- temp.y =
- head.y;
- 471 //头部移动
- 472 if
- (direction == "L"
- )
- 473 {
- 474
- head.x -= 22
- ;
- 475 }
- 476 if
- (direction == "R"
- )
- 477 {
- 478
- head.x += 22
- ;
- 479 }
- 480 if
- (direction == "U"
- )
- 481 {
- 482
- head.y -= 22
- ;
- 483 }
- 484 if
- (direction == "D"
- )
- 485 {
- 486
- head.y += 22
- ;
- 487 }
- 488
- current_direction = direction;
- //刷新当前前进方向
- 489 //身体移动
- 490 for
- (
- int
- i = 0;i < body_length;i++
- )
- 491 {
- 492
- temp2.x =
- body[i].x;
- 493
- temp2.y =
- body[i].y;
- 494
- body[i].x =
- temp.x;
- 495
- body[i].y =
- temp.y;
- 496
- temp.x =
- temp2.x;
- 497
- temp.y =
- temp2.y;
- 498 }
- 499
- 500 if(EatFood())
- 501 {
- 502
- body_length ++
- ;
- 503
- body[body_length-1].x =
- temp2.x;
- 504
- body[body_length-1].y =
- temp2.y;
- 505
- Score.setText("" + (body_length+1
- ) );
- 506 new
- AePlayWave("eat.wav"
- ).start();
- 507 }
- 508
- 509 repaint();
- 510
- 511 HitWall();
- 512 HitSelf();
- 513 }
- 514 }
- 515 };
- 516
- 517 run.start();
- 518 }
- 519
- 520 public static void main(String[] args) {
- 521
- SnakeDemo t =
- new SnakeDemo();
- 522 t.Thread();
- 523
- 524
- JFrame game =
- new JFrame();
- 525
- Image img=Toolkit.getDefaultToolkit().getImage("title.png");
- //窗口图标
- 526 game.setIconImage(img);
- 527
- game.setTitle("Snake By XJX"
- );
- 528 game.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
- 529 // game.setSize(502, 507);
- 530
- game.setSize(602, 507
- );
- 531
- game.setResizable(
- false);
- 532
- game.setLocationRelativeTo(
- null);
- 533
- 534 game.add(t);
- 535
- game.setVisible(
- true);
- 536 }
- 537
- 538 //计时器类
- 539 class
- Timer
- extends Thread{
- 540 public Timer(){
- 541 this.start();
- 542 }
- 543 @Override
- 544 public void run() {
- 545 // TODO Auto-generated method stub
- 546 while
- (
- true){
- 547 if(isrun){
- 548
- sec +=1
- ;
- 549 if
- (sec >= 60
- ){
- 550
- sec = 0
- ;
- 551
- min +=1
- ;
- 552 }
- 553 if
- (min>=60
- ){
- 554
- min=0
- ;
- 555
- hour+=1
- ;
- 556 }
- 557 showTime();
- 558 }
- 559
- 560 try {
- 561
- Thread.sleep(1000
- );
- 562
- }
- catch (InterruptedException e) {
- 563 // TODO Auto-generated catch block
- 564 e.printStackTrace();
- 565 }
- 566
- 567 }
- 568 }
- 569
- 570 private void showTime(){
- 571
- String strTime =""
- ;
- 572 if
- (hour < 10
- )
- 573
- strTime = "0"+hour+":"
- ;
- 574 else
- 575
- strTime = ""+hour+":"
- ;
- 576
- 577 if
- (min < 10
- )
- 578
- strTime = strTime+"0"+min+":"
- ;
- 579 else
- 580
- strTime =strTime+ ""+min+":"
- ;
- 581
- 582 if
- (sec < 10
- )
- 583
- strTime = strTime+"0"+
- sec;
- 584 else
- 585
- strTime = strTime+""+
- sec;
- 586
- 587 //在窗体上设置显示时间
- 588 Time.setText(strTime);
- 589 }
- 590 }
- 591 }
- 592
- 593 class
- AePlayWave
- extends Thread {
- 594 private String filename;
- 595 private final int
- EXTERNAL_BUFFER_SIZE = 524288;
- // 128Kb
- 596
- 597 public AePlayWave(String wavfile) {
- 598
- filename =
- wavfile;
- 599 }
- 600
- 601 public void run() {
- 602
- File soundFile =
- new File(filename);
- 603
- AudioInputStream audioInputStream =
- null;
- 604 try {
- 605
- audioInputStream =
- AudioSystem.getAudioInputStream(soundFile);
- 606
- }
- catch (UnsupportedAudioFileException e1) {
- 607 e1.printStackTrace();
- 608 return;
- 609
- }
- catch (IOException e1) {
- 610 e1.printStackTrace();
- 611 return;
- 612 }
- 613
- 614
- AudioFormat format =
- audioInputStream.getFormat();
- 615
- SourceDataLine auline =
- null;
- 616
- DataLine.Info info =
- new
- DataLine.Info(SourceDataLine.
- class, format);
- 617
- 618 try {
- 619
- auline =
- (SourceDataLine) AudioSystem.getLine(info);
- 620 auline.open(format);
- 621
- }
- catch (LineUnavailableException e) {
- 622 e.printStackTrace();
- 623 return;
- 624
- }
- catch (Exception e) {
- 625 e.printStackTrace();
- 626 return;
- 627 }
- 628
- 629 auline.start();
- 630 int
- nBytesRead = 0
- ;
- 631 byte
- [] abData =
- new byte[EXTERNAL_BUFFER_SIZE];
- 632
- 633 try {
- 634 while
- (nBytesRead != -1
- ) {
- 635
- nBytesRead = audioInputStream.read(abData, 0
- , abData.length);
- 636 if
- (nBytesRead >= 0
- )
- 637
- auline.write(abData, 0
- , nBytesRead);
- 638 }
- 639
- }
- catch (IOException e) {
- 640 e.printStackTrace();
- 641 return;
- 642
- }
- finally {
- 643 auline.drain();
- 644 auline.close();
- 645 }
- 646 }
- 647
- }
来源: http://www.bubuko.com/infodetail-2170763.html