首页 > 代码库 > Java版贪吃蛇小游戏的实现

Java版贪吃蛇小游戏的实现

使用的IDE eclipse

JDK版本 1.6

辅助类 Coordinate.java

package com.nn.util;    /**  *坐标点   */  public class Coordinate {      public int x;      public int y;        public Coordinate(int newX, int newY) {          x = newX;          y = newY;      }        public boolean equals(Coordinate other) {          if (x == other.x && y == other.y) {              return true;          }          return false;      }        @Override      public String toString() {          return "Coordinate: [" + x + "," + y + "]";      }  }  

接口 Direction

package com.nn.entity;    public interface Direction {        public class Dir{          public static final int UP = 1;                    public static final int DOWN = 2;                    public static final int LEFT = 3;                    public static final int RIGHT = 4;      }  }  

实体类 Snake.java

package com.nn.entity;    import java.util.ArrayList;    import com.nn.entity.Direction.Dir;  import com.nn.util.Coordinate;      public class Snake{            //小方块x坐标      private int x;            //小方块y坐标      private int y;            //宽度      public static final int TILE_W = 10;            //高度      public static final int TILE_H = 10;            //下一个方向      private int mNextDirection = Dir.RIGHT;        //游戏是否结束      private boolean isEnd;             //存放贪吃蛇      private ArrayList<Coordinate> mSnakeTrail = new ArrayList<Coordinate>();            //存放豆子      private ArrayList<Coordinate> mAppleList = new ArrayList<Coordinate>();        public Snake()      {          initNewGame();      }            //初始化新游戏      public void initNewGame()      {          //初始化蛇身          mSnakeTrail.add(new Coordinate(5, 7));          mSnakeTrail.add(new Coordinate(6, 7));          mSnakeTrail.add(new Coordinate(7, 7));          mSnakeTrail.add(new Coordinate(8, 7));          mSnakeTrail.add(new Coordinate(9, 7));          mSnakeTrail.add(new Coordinate(10, 7));             //初始化豆子          mAppleList.add(new Coordinate(20,3));                    //设置初始状态为false          isEnd = false;      }        public ArrayList<Coordinate> getmSnakeTrail() {          return mSnakeTrail;      }            public ArrayList<Coordinate> getmAppleList() {          return mAppleList;      }                  public boolean isEnd() {          return isEnd;      }        public int getmNextDirection() {          return mNextDirection;      }        public void setEnd(boolean isEnd) {          this.isEnd = isEnd;      }              }  

frame类 继承JFrame SnakeFrame.java

package com.nn.ui;    import java.awt.Dimension;  import java.awt.Toolkit;    import javax.swing.JFrame;    /**  *游戏界面  */  public class SnakeFrame extends JFrame{        private static final long serialVersionUID = 1L;      //宽度      private static final int width = 530;            //高度      private static final int height = 450;            //高度偏移量      private static final int offset = 15;        public SnakeFrame(){          init();      }            /**      * 初始化游戏界面      */      private void init()      {          this.setTitle("Java版贪吃蛇_1.0");          //frame的高度 宽度          this.setSize(width, height);          //窗口居中显示          Toolkit toolkit = Toolkit.getDefaultToolkit();          Dimension screen = toolkit.getScreenSize();          int w = screen.width;          int h = screen.height;          //计算左上角坐标点的x y值          this.setLocation((w-this.getWidth())/2, (h-this.getHeight())/2-offset);          //设置默认关闭的操作          this.setDefaultCloseOperation(EXIT_ON_CLOSE);          //设置窗口大小不可改变          this.setResizable(false);          //设置可见性          this.setVisible(true);                    this.setLayout(null);      }  }  

panel j继承JPanel  SnakePanel.java

package com.nn.ui;    import java.awt.Color;  import java.awt.Font;  import java.awt.Graphics;  import java.awt.event.ActionEvent;  import java.awt.event.ActionListener;  import java.util.ArrayList;    import javax.swing.JButton;  import javax.swing.JPanel;    import com.nn.control.PlayControl;  import com.nn.entity.Snake;  import com.nn.util.Coordinate;    public class SnakePanel extends JPanel{        private static final long serialVersionUID = 1L;            //panel的宽度      private static final int width = 400;            //panel的高度      private static final int height = 400;            //坐标点x      private static final int x = 10;            //坐标点y      private static final int y = 10;            //方块尺寸      private static final int SIZE = 10;            //是否开启网格      private boolean isOpen = false;            private Snake snake;            //开启作弊      private JButton girdButton;            private JButton aboutButton;            //暂停 继续按钮      private JButton PauseButton;            //重新开始游戏      private JButton StartButton;            public Snake getSnake() {          return snake;      }            private ArrayList<Coordinate> mSnakeTrail = null;            private ArrayList<Coordinate> mAppleList = null;            public SnakePanel() {          snake  = new Snake();          this.setLayout(null);          StartButton = new JButton("重新开始");          StartButton.setLocation(420,100);          StartButton.setSize(90,26);          this.add(StartButton);          PauseButton = new JButton("暂停游戏");          PauseButton.setLocation(420, 150);          PauseButton.setSize(90,26);          this.add(PauseButton);          girdButton = new JButton("开启网格");          girdButton.setLocation(420, 200);          girdButton.setSize(90,26);          this.add(girdButton);          aboutButton = new JButton("关于游戏");          aboutButton.setLocation(420, 250);          aboutButton.setSize(90,26);          this.add(aboutButton);          girdButton.addActionListener(new GirdActionListener());          aboutButton.addActionListener(new AboutActionListerner());      }        class GirdActionListener implements ActionListener{          int i = 1;          public void actionPerformed(ActionEvent e) {              if(i%2==1)              {                  girdButton.setText("关闭网格");                  isOpen = false;                  i++;              }              else if(i%2==0){                  girdButton.setText("开启网格");                  isOpen = true;                  i++;              }          }                }            class AboutActionListerner implements ActionListener{            public void actionPerformed(ActionEvent e) {                        }                }            @Override      public void paintComponent(Graphics g) {          super.paintComponent(g);          creatGameWindow(g);          if(snake.isEnd())          {              paintWords(g);          }          //将焦点定在Jpanel上          this.requestFocus();      }      /**      * 安装玩家控制器      * @param control      */      public void setGameControl(PlayControl control){          this.addKeyListener(control);      }        private void creatGameWindow(Graphics g) {          g.setColor(Color.BLACK);          g.drawRect(x, y, width, height);          g.setColor(Color.WHITE);          g.fillRect(x+1, y+1, width-1, height-1);          g.setColor(Color.GRAY);          /***************test******************/          paintLine(g);          /***************test******************/                    mSnakeTrail = snake.getmSnakeTrail();          mAppleList = snake.getmAppleList();          if(mSnakeTrail==null)           {              return;          }          g.setColor(Color.BLACK);          for(int i=0;i<mSnakeTrail.size();i++){              g.fillRect(this.x+mSnakeTrail.get(i).x*SIZE, this.y+mSnakeTrail.get(i).y*SIZE, Snake.TILE_W, Snake.TILE_H);          }                    //画豆子          g.fillRect(this.x+mAppleList.get(0).x*SIZE, this.y+mAppleList.get(0).y*SIZE, Snake.TILE_W, Snake.TILE_H);      }            //画网格      private void paintLine(Graphics g)      {          for(int i = 1;i < 40;i++)          {              g.drawLine(this.x, i*10+this.y, 400+this.x, i*10+this.y);          }          for(int i = 1;i < 40;i++)          {              g.drawLine(i*10+this.x,this.y,i*10+this.x,400+this.y);          }      }            //结束提示      private  void paintWords(Graphics g){          Font font = new Font("宋体", Font.BOLD, 64);          g.setFont(font);          g.setColor(Color.RED);          g.drawString("游戏结束",60,220);      }  }  

最关键的类 控制类 PlayControl.java

package com.nn.control;    import java.awt.event.KeyEvent;  import java.awt.event.KeyListener;  import java.util.ArrayList;  import java.util.Random;  import com.nn.entity.Direction.Dir;  import com.nn.ui.SnakePanel;  import com.nn.util.Coordinate;      public class PlayControl implements KeyListener{            private SnakePanel panel;            //蛇头在list中索引      private int headIndex;            /**      * 贪吃蛇列表      */      ArrayList<Coordinate> mSnakeTrail;            /*      * 豆子列表      */      private ArrayList<Coordinate> mAppleList;            //新产生的豆子      Coordinate newCoordinate;            private int mNextDirection;            //是否绘制出结束提示      private boolean isDraw = false;              private Random random = new Random();            public PlayControl(SnakePanel panel)      {          this.panel = panel;                    mSnakeTrail = panel.getSnake().getmSnakeTrail();          mAppleList = panel.getSnake().getmAppleList();          mNextDirection = panel.getSnake().getmNextDirection();          headIndex = mSnakeTrail.size()-1;          Thread thread = new Thread(runnable);          thread.start();      }      //响应键盘按下事件      public void keyPressed(KeyEvent e) {          if(isDraw){              return;          }          switch (e.getKeyCode()) {          case KeyEvent.VK_UP:              if(mNextDirection!=Dir.DOWN)              {                  mNextDirection = Dir.UP;                  //moveUp();              }              break;                        case KeyEvent.VK_DOWN:              if(mNextDirection!=Dir.UP)              {                  mNextDirection = Dir.DOWN;                  //moveDown();              }              break;                        case KeyEvent.VK_LEFT:              if(mNextDirection!=Dir.RIGHT)              {                  mNextDirection = Dir.LEFT;                  //moveLeft();              }              break;                        case KeyEvent.VK_RIGHT:              if(mNextDirection!=Dir.LEFT)              {                  mNextDirection = Dir.RIGHT;                  //moveRight();              }              break;            }      }            @Override      public void keyReleased(KeyEvent e) {                }          @Override      public void keyTyped(KeyEvent e) {                }            //向上移动      private void moveUp()      {          if(!isEndGame()){              //每移动一次  先在头部加一块 list增加一个元素              mSnakeTrail.add(new Coordinate(mSnakeTrail.get(headIndex).x, mSnakeTrail.get(headIndex).y-1));              //如果判断吃到豆子              if(isEat()){                  //吃到豆子的处理                  afterEatApple();              }              //否则 移除第一个元素              else {                  mSnakeTrail.remove(0);              }              //重新绘制              panel.repaint();          }      }            //向下移动      private void moveDown()      {          if(!isEndGame()){              mSnakeTrail.add(new Coordinate(mSnakeTrail.get(headIndex).x, mSnakeTrail.get(headIndex).y+1));              if(isEat()){                  afterEatApple();              }              else {                  mSnakeTrail.remove(0);              }              panel.repaint();          }      }            //向左移动      private void moveLeft()      {          if(!isEndGame()){              mSnakeTrail.add(new Coordinate(mSnakeTrail.get(headIndex).x-1, mSnakeTrail.get(headIndex).y));              if(isEat())              {                  afterEatApple();              }              else {                  mSnakeTrail.remove(0);              }              panel.repaint();          }      }            //向右移动      private void moveRight()      {          if(!isEndGame()){              mSnakeTrail.add(new Coordinate(mSnakeTrail.get(headIndex).x+1, mSnakeTrail.get(headIndex).y));              if(isEat())              {                  afterEatApple();              }              else {                  mSnakeTrail.remove(0);              }              panel.repaint();          }      }                  //增加一个坐标点到存放蛇的list 添加到list的末尾      private void afterEatApple(){          //每增加一个  索引值加1 重新开始游戏时要回复初始值          headIndex++;          mAppleList.add(new Coordinate(random.nextInt(40), random.nextInt(40)));          mAppleList.remove(0);          newCoordinate = mAppleList.get(0);          //System.out.println("蛇身长度:"+mSnakeTrail.size());      }            //判断蛇是否吃到豆子      private boolean isEat()      {          return mSnakeTrail.get(mSnakeTrail.size()-1).equals(mAppleList.get(0));      }            //判断是否到边界或者碰到自己的身体      private boolean isEndGame(){          int x = mSnakeTrail.get(headIndex).x;          int y = mSnakeTrail.get(headIndex).y;          if(touchBody()||x<0||x>39||y<0||y>39){              afterEndGame();              return true;          }          return false;      }            //碰到自己身体      private boolean touchBody(){          for(int i =0;i<mSnakeTrail.size()-1;i++)          {              if(mSnakeTrail.get(headIndex).equals(mSnakeTrail.get(i))){                  return true;              }          }          return false;      }            //游戏结束处理      private void afterEndGame()      {          mSnakeTrail.remove(headIndex);          panel.getSnake().setEnd(true);          panel.repaint();          this.isDraw = true;      }            Runnable runnable = new Runnable() {          public void run() {              moveRight();              while(!isEndGame())              {                  if(mNextDirection==Dir.UP) moveUp();                  else if(mNextDirection==Dir.DOWN) moveDown();                  else if(mNextDirection==Dir.LEFT) moveLeft();                  else if(mNextDirection==Dir.RIGHT) moveRight();                                    try {                      Thread.sleep(200);                  } catch (InterruptedException e) {                      e.printStackTrace();                  }              }          }                };  }  

最后是测试类 SnakeTest.java

package com.nn.main;    import com.nn.control.PlayControl;  import com.nn.ui.SnakeFrame;  import com.nn.ui.SnakePanel;    /**  *启动游戏   *  */  public class SnakeTest {            public static void main(String[] args) {      SnakeFrame frame = new SnakeFrame();      SnakePanel panel = new SnakePanel();       PlayControl playControl = new PlayControl(panel);      panel.setGameControl(playControl);      //setContentPane()把panel设置为JFrame的内容面板      frame.setContentPane(panel);  }  }  

大致说下思路,panel面板增加控制器获得游戏控制权,控制器根据输入在列表中更新蛇身所在位置的坐标,并通知panel重绘,直至游戏结束,鼠标监听事件return。当然程序有不恰当的地方,比如说控制层和业务层混杂在了一起,代码中存在硬编码,代码的复用性不高,只是个练习的小程序,还有很多不完善的地方。