贪吃蛇小游戏Java

1.小组成员

陈倩

2.选题与前期调查

选题

贪吃蛇

前期调查

根据小时候玩贪吃蛇的经验知道贪吃蛇游戏的几个选项:开始,暂停,重玩,退出。
贪吃蛇小游戏Java

3.系统功能设计

1.蛇身:设置蛇的颜色,一节蛇身的大小,随机出现的位置,吃到一个食物蛇身增加一节。
2.食物:设置食物的颜色,大小,随机出现的位置。
3.蛇的移动方向:通过↑,↓,←,→键来控制蛇的移动方向。
4.四个按钮:开始,暂停,重玩,退出。
5.分数:记录得分,吃到一个食物时分数加10。
6.GameOver:贪吃蛇吃到自己的尾巴或撞到边界。

4.功能框架图

贪吃蛇小游戏Java

5.关键代码

游戏界面(GameUi)

`package com.java.snake;

import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.LinkedList;
import java.util.Random;

import javax.swing.*;

public class GameUi extends JFrame {
int flag = 1;
JLabel jl = new JLabel();//GameOver标签
JLabel fs = new JLabel();
JButton start = new JButton("开始");
JButton stop = new JButton("暂停");
JButton restart = new JButton("重玩");
JButton exit = new JButton("退出");
boolean p = true;

JPanel pan = new JPanel();//新建pan对象

GridLayout grid = new GridLayout(1, 5);//网格布局为1行,5列

Random r1 = new Random();
Random r2 = new Random();
//食物的坐标
int a = (r1.nextInt(53) + 1) * 10 - 4;
int b = (r2.nextInt(35) + 6) * 10 - 1;

int score = 0;
int foodNumber = 0;

final int HW = 9;//使用final修饰HW后,不能再对它的值进行修改,食物与一节蛇身的宽度与高度
int x = (r1.nextInt(35) + 10) * 10 - 4;
int y = (r2.nextInt(35) + 6) * 10 - 1;
LinkedList snake = new LinkedList();
int direction = 1;
SnakeBody tail;
SnakeBody head;

class Mytask implements Runnable{
@Override
public void run() {
// TODO Auto-generated method stub
while (true) {
head = snake.getFirst();
/*
* 判断蛇是否吃到食物,如果吃到食物则产生一个随机数,若产生的随机数在蛇的身体上则重新再产生一个随机数
/
if (head.getX() == a && head.getY() == b) {
SnakeBody c = new SnakeBody();
snake.add(c);
++foodNumber;
score += 10;
fs.setText("分数:" + score);//setText将fs对象上面的文字设定为分数:
/
判断生成的食物是不是在蛇的身体里 */
for (int i = 0; i < snake.size(); i++) {
SnakeBody d = snake.get(i);
if (d.getX() == a && d.getY() == b) {
a = (r1.nextInt(53) + 1) * 10 - 4;
b = (r2.nextInt(35) + 6) * 10 - 1;
}
}
}

           int x1 = head.getX();
           int y1 = head.getY();
           /* 判断是否触到边缘 */
           if (x1 < 6 || x1 > 536 || y1 < 59 || y1 > 419) {

               gameover();
               break ;
           }
           /* 判断是否吃到自己的身体 */
           else {
               for (int i = 3; i < snake.size(); i++) {
                   SnakeBody d = snake.get(i);
                   if (d.getX() == x1 && d.getY() == y1) {
                       gameover();
                       break ;
                   }
               }
           }
           if (p != false) {
               moving(direction);
               update(getGraphics());
           }

           try {
               //Thread.sleep(500 - foodNumber / 2 * 100);
               //可设置等级,等级不同可以有不同的速度
               Thread.sleep(67);//暂停67ms来设置贪吃蛇的移动速度
           } catch (Exception e) {
        	   //中断标志已经被清除了,sleep是会擦除中断标志的
           }
           
       }
   }

   private void gameover() {
       // TODO Auto-generated method stub
       jl.setText("GAME OVER");
       jl.setBounds(150, 150, 400,100);//x,y,组件长度,高度
       jl.setForeground(Color.red);//文本颜色
       jl.setFont(new Font("宋体", Font.BOLD, 55));//创建font对象,使用“宋体”字体,加粗Font.BOLD,字体大小为55
       add(jl);
       update(getGraphics());//更新图像
   }

}

Thread timer = new Thread(new Mytask()); //创建线程对象,把实现了Runnable接口的对象作为参数传入

public GameUi() {
// TODO Auto-generated constructor stub
this.setTitle("我的贪吃蛇");
this.setSize(552, 435);
this.setResizable(false);
this.setLocationRelativeTo(null);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
initSnakeBody();
initEvent();
fs.setText("分数:" + score);

   add(pan, BorderLayout.NORTH);//整个pan放在北侧
   pan.setLayout(grid);
   //在上面建立的pan对象,放入一下按钮
   pan.add(start);
   pan.add(stop);
   pan.add(restart);
   pan.add(exit);
   pan.add(fs);
   this.requestFocus();//就是把焦点设置在这个按钮this上
   start.addActionListener(new ActionListener() {
       @Override
       public void actionPerformed(ActionEvent e) {
           // TODO Auto-generated method stub
           if (e.getSource() == start) {//e.getSource(),就是获得这个按钮
               p = true;

}
GameUi g = getUi();
g.requestFocus();
}

   });
   stop.addActionListener(new ActionListener() {

       @Override
       public void actionPerformed(ActionEvent e) {
           // TODO Auto-generated method stub
           if (e.getSource() == stop)
               p = false;
       }
   });
   restart.addActionListener(new ActionListener() {

       @Override
       public void actionPerformed(ActionEvent e) {
           // TODO Auto-generated method stub
           if (e.getSource() == restart) {
               new GameUi();
               dispose();//销毁程序中指定的图形界面资源
           }
       }
   });
   exit.addActionListener(new ActionListener() {

       @Override
       public void actionPerformed(ActionEvent e) {
           // TODO Auto-generated method stub
           if (e.getSource() == exit)
               System.exit(EXIT_ON_CLOSE);//使用System exit方法退出应用程序
       }
   });
   timer.start();

}

protected GameUi getUi() {
return this;
}

@Override
/* 画边缘,蛇身,食物 */
public void paint(Graphics g) {
// TODO Auto-generated method stub
super.paint(g);
Graphics2D g_2d = (Graphics2D) g;
g_2d.setColor(Color.BLACK);
g_2d.setStroke(new BasicStroke(2f));//设置画笔的宽度. 越大,边框越粗
//起始端点x,y坐标,终点端点x,y的坐标
g_2d.drawLine(5, 58, 547, 58);// 上面的那根线
g_2d.drawLine(5, 58, 5, 430);// 左边的那根线
g_2d.drawLine(5, 430, 547, 430);// 下面的那根线
g_2d.drawLine(547, 58, 547, 430);// 右边的那根线
g_2d.setColor(Color.black);
//画蛇身
for (int i = 0; i < snake.size(); i++) {
SnakeBody b = snake.get(i);
g.fillRect(b.getX(), b.getY(), HW, HW);
}
//画食物
g.setColor(Color.red);
g.fillRect(a, b, HW, HW);//a,b左上角的坐标,宽度高度
}

Image ImageBuffer = null;
Graphics GraImage = null;

@Override
public void update(Graphics g) {
// TODO Auto-generated method stub
ImageBuffer = createImage(this.getWidth(), this.getHeight());
GraImage = ImageBuffer.getGraphics(); // 获取图形缓冲区的图形上下文
paint(GraImage); // 用paint方法中编写的绘图过程对图形缓冲区绘图
GraImage.dispose(); // 释放图形上下文资源
g.drawImage(ImageBuffer, 0, 0, this); // 将图形缓冲区绘制到屏幕上
}

/* 初始化蛇身 */
public void initSnakeBody() {
// TODO Auto-generated method stub
for (int i = 0; i < 5; i++) {
SnakeBody b = new SnakeBody();
b.setX(x + i * HW + i);
b.setY(y);
snake.add(b);
}
tail = snake.getLast();
head = snake.getFirst();
}

/* 蛇移动的时候身体的变化 */
public void moving(int direction) {
tail = snake.removeLast();
head = snake.getFirst();
switch (direction) {
// 1:左;2:上;3:右;4:下
case 1:
tail.setX(head.getX() - HW - 1);
tail.setY(head.getY());
break;
case 2:
tail.setX(head.getX());
tail.setY(head.getY() - HW - 1);
break;
case 3:
tail.setX(head.getX() + HW + 1);
tail.setY(head.getY());
break;
case 4:
tail.setX(head.getX());
tail.setY(head.getY() + HW + 1);
break;
}
snake.addFirst(tail);//在蛇身的首部插入元素tail
}

/* 方向控制 */
public void initEvent() {
this.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent event) {
// TODO Auto-generated method stub
switch (event.getKeyCode()) {
case KeyEvent.VK_UP:
if (direction == 2 || direction == 4) {
break;
}
direction = 2;
break;
case KeyEvent.VK_DOWN:
if (direction == 2 || direction == 4) {
break;
}
direction = 4;
break;
case KeyEvent.VK_LEFT:
if (direction == 1 || direction == 3) {
break;
}
direction = 1;
break;
case KeyEvent.VK_RIGHT:
if (direction == 1 || direction == 3) {
break;
}
direction = 3;
break;
}
}
});
}
}`

蛇身(SnakeBody)

`package com.java.snake;

import java.awt.Color;

public class SnakeBody {
private int x;
private int y;
private Color color;
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public Color getColor() {
return color;
}
public void setColor(Color color) {
this.color = color;
}
}`

Test

package com.java.snake;

public class Test {

/**
 * @param args
 */
public static void main(String[] args) {
    // TODO Auto-generated method stub
    new GameUi();

}

}

6.运行结果

贪吃蛇小游戏Java

贪吃蛇小游戏Java

7.界面

GUI

8.开发工具

Eclipse

上一篇:github pages与travis ci运作原理


下一篇:译:SQL Server的Missing index DMV的 bug可能会使你失去理智---慎重看待缺失索引DMV中的信息