贪吃蛇源码奉献(Java)

最终效果图如下,程序没有使用任何图片资源:



程序功能简介:

  1. 首先实现积分的功能,每次吃一个就加1分
  2. 开始和结束按钮,以及在游戏失败之后(包括跑出蓝色外框,以及蛇体自身碰撞)
  3. 加速和减速,设置了键盘事件,通过w加速蛇的移动,s减速蛇的移动



Snake.java

package game;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.Random;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.Timer;

public class Snake extends JFrame {
    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    private JButton start;
    private JButton exit;
    private JPanel mainframe;
    private JPanel control;
    private SnakePanel board;
    private BorderLayout border;
    private FlowLayout flow;
    private int row;
    private int column;
    private Direction direction;
    private ActionListener actionlistener;
    private KeyAdapter keylistener;
    private Timer time;
    private Random rand;
    private ArrayList<Place> snakeBody;
    private Place food;
    private boolean caneat;
    private ActionListener timelistener;
    private int speed;
    private JTextField score;

    /**
     * default set the board to 20 * 10
     */
    public Snake() {
        this("Snake", 20, 10);
    }

    public Snake(String title, int row, int column) {
        super(title);
        // this.setUndecorated(true);
        this.row = row;
        this.column = column;
        initial(row, column);
        // this.pack();
        setSize(300, (int) (300 * this.row * 1.0 / this.column));
        this.setResizable(false);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationByPlatform(true);
        this.setVisible(true);
        this.requestFocus();
    }

    private void initial(int row, int column) {
        snakeBody = new ArrayList<Place>();
        /**
         * initial the snake body! to length 3
         */
        loadSnakeBody();
        direction = Direction.UP;
        speed = 1000;
        caneat = false;
        createComponent();
        layOut();
        listener();
        food();
    }

    private void loadSnakeBody() {
        snakeBody.clear();
        snakeBody.add(new Place(row / 2 - 1, column / 2));
        snakeBody.add(new Place(row / 2, column / 2));
        snakeBody.add(new Place(row / 2 + 1, column / 2));
    }

    /**
     * create the component which used in Snake.
     */
    private void createComponent() {
        start = new JButton("Start");
        exit = new JButton("Exit");
        mainframe = new JPanel();
        control = new JPanel();
        border = new BorderLayout();
        board = new SnakePanel(snakeBody, row, column);
        flow = new FlowLayout();
        rand = new Random();
        food = new Place(-1, -1);
        board.setFood(food);
        score = new JTextField();
        score.setEditable(false);
    }

    /**
     * The Snake game's layout.
     */
    private void layOut() {
        getContentPane().add(mainframe);
        mainframe.setLayout(border);
        mainframe.add(control, BorderLayout.NORTH);
        control.setLayout(flow);
        control.add(start);
        control.add(score);
        control.add(exit);
        score.setPreferredSize(new Dimension(70, 30));
        score.setText("0");
        mainframe.add(board, BorderLayout.CENTER);
    }

    /**
     * register all listeners to the snake game.
     */
    private void listener() {
        /*
         * action listener for the button of start)(for start) and end(for exit)
         */
        actionlistener = new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                String command = e.getActionCommand();
                if (command.equals("Exit")) {
                    System.exit(0);
                } else if (command.equals("Start")) {
                    time.start();
                    requestFocus();
                }
            }
        };
        /*
         * The keyboard listener to direction key(the key in here is you can not
         * get the reverse direction) and speed key(w for high speed, s for low
         * speed).
         */
        keylistener = new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                int code = e.getKeyCode();
                if (code == KeyEvent.VK_LEFT && direction != Direction.RIGHT) {
                    direction = Direction.LEFT;
                } else if (code == KeyEvent.VK_RIGHT && direction != Direction.LEFT) {
                    direction = Direction.RIGHT;
                } else if (code == KeyEvent.VK_UP && direction != Direction.DOWN) {
                    direction = Direction.UP;
                } else if (code == KeyEvent.VK_DOWN && direction != Direction.UP) {
                    direction = Direction.DOWN;
                } else if (code == KeyEvent.VK_W) {
                    speed -= 100;
                    time.setDelay(speed);
                    System.out.println(speed);
                } else if (code == KeyEvent.VK_S) {
                    speed += 100;
                    time.setDelay(speed);
                    System.out.println(speed);
                }
            }
        };
        timelistener = new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                move();
                repaint();
            }
        };
        /**
         * here set the timer to the speed of 1 grid/sec
         */
        time = new Timer(speed, timelistener);
        this.addKeyListener(keylistener);
        start.addActionListener(actionlistener);
        exit.addActionListener(actionlistener);
    }

    /*
     * used for checking the validity of the place where food come out. insure
     * the food not come out above the snake's body.
     */
    private boolean isMoveValid(int x, int y) {
        boolean flag = true;
        for (Place a : snakeBody) {
            if (a.getX() == x && a.getY() == y) {
                flag = false;
            }
        }
        return flag;
    }

    /*
     * come out the food
     */
    private void food() {
        int food_row = rand.nextInt(row);
        int food_column = rand.nextInt(column);
        while (!isMoveValid(food_row, food_column)) {
            food_row = rand.nextInt(row);
            food_column = rand.nextInt(column);
        }
        food.setX(food_row);
        food.setY(food_column);
    }

    /*
     * judge whether the snake is alive now!
     */
    private boolean isAlive() {
        if (snakeBody.get(0).getX() >= 0 && snakeBody.get(0).getX() < row && snakeBody.get(0).getY() >= 0
                && snakeBody.get(0).getY() < column && checkBody()) {
            return true;
        } else {
            return false;
        }
    }

    /*
     * check the snake's head whether or not touch its body!
     */
    private boolean checkBody() {
        for (int i = 4; i < snakeBody.size(); i++) {
            if (snakeBody.get(0).equals(snakeBody.get(i))) {
                return false;
            }
        }
        return true;
    }

    /*
     * snake's body moves forward without head which with special considering.
     */
    private void dealWithBody() {
        for (int i = snakeBody.size() - 1; i >= 1; i--) {
            snakeBody.get(i).setX(snakeBody.get(i - 1).getX());
            snakeBody.get(i).setY(snakeBody.get(i - 1).getY());
        }
    }

    /**
     * The Snake's actual move.
     */
    private void move() {
        Place oldhead = new Place(snakeBody.get(0).getX(), snakeBody.get(0).getY());
        if (isAlive()) {
            caneat = food.equals(snakeBody.get(snakeBody.size() - 1));
            dealWithBody();
            if (direction == Direction.UP) {
                snakeBody.get(0).setX(oldhead.getX() - 1);
                snakeBody.get(0).setY(oldhead.getY());
            } else if (direction == Direction.DOWN) {
                snakeBody.get(0).setX(oldhead.getX() + 1);
                snakeBody.get(0).setY(oldhead.getY());
            } else if (direction == Direction.LEFT) {
                snakeBody.get(0).setX(oldhead.getX());
                snakeBody.get(0).setY(oldhead.getY() - 1);
            } else if (direction == Direction.RIGHT) {
                snakeBody.get(0).setX(oldhead.getX());
                snakeBody.get(0).setY(oldhead.getY() + 1);
            }
            if (caneat) {
                snakeBody.add(new Place(food.getX(), food.getY()));
                score.setText(String.valueOf(Integer.valueOf(score.getText()) + 1));
                food();
            }
        } else {
            time.stop();
            // JOptionPane.showMessageDialog(this, "You Lose! Come on!");
            int choice = JOptionPane.showConfirmDialog(this, "try again!", "Message", JOptionPane.YES_NO_OPTION);
            if (JOptionPane.YES_OPTION == choice) {
                /**
                 * ready for the restart the game.
                 */
                loadSnakeBody();
                score.setText("0");
            }
        }
    }

    public static void main(String[] args) {
        Snake test = new Snake("test", 30, 15);
    }

}

Direction.java

package game;

/**
 * this file contains the definition of the direction.
 * */
public enum Direction {
	UP,
	DOWN,
	LEFT,
	RIGHT
}

SnakePanel.java

package game;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.util.ArrayList;

import javax.swing.JPanel;

/**
 * in this file draw the background and the moving snake.
 */
public class SnakePanel extends JPanel {
    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    private ArrayList<Place> snakeBody;
    private Place food;
    private int row;
    private int column;

    public SnakePanel(ArrayList<Place> a) {
        this.snakeBody = a;
        this.row = 20;
        this.column = 10;
    }

    public SnakePanel(ArrayList<Place> snakeBody, int row, int column) {
        this.snakeBody = snakeBody;
        this.row = row;
        this.column = column;
    }

    public void setA(ArrayList<Place> snakeBody) {
        this.snakeBody = snakeBody;
    }

    public void setFood(Place food) {
        this.food = food;
    }

    @Override
    public void paint(Graphics g) {
        Graphics2D gg = (Graphics2D) g;
        int squre = (this.getWidth() - 50) / column;
        /**
         * from the point (25, 10) draw the game's background.
         */
        /*
         * below draw the background gird.
         */
        int x = 25;
        int y = 10;
        for (int i = 0; i < row; i++) {
            for (int j = 0; j < column; j++) {
                gg.setStroke(new BasicStroke(0.5f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 1.0f,
                        new float[] { 5f, 5f }, 0f));
                gg.setColor(Color.yellow);
                gg.drawRect(x + j * squre, y + i * squre, squre, squre);
            }
        }
        /*
         * below draw the snake with three color for head, body and tail.
         */
        for (int i = 0; i < snakeBody.size(); i++) {
            if (0 == i) {
                gg.setColor(Color.red);
                gg.fillRect(x + snakeBody.get(i).getY() * squre, y + snakeBody.get(i).getX() * squre, squre, squre);
            } else if (snakeBody.size() - 1 == i) {
                gg.setColor(Color.pink);
                gg.fillRect(x + snakeBody.get(i).getY() * squre, y + snakeBody.get(i).getX() * squre, squre, squre);
            } else {
                gg.setColor(Color.green);
                gg.fillRect(x + snakeBody.get(i).getY() * squre, y + snakeBody.get(i).getX() * squre, squre, squre);
            }
        }
        /*
         * draw the snake's food with green color circle shape.
         */
        if (null != food) {
            gg.setColor(Color.green);
            gg.fillOval(x + food.getY() * squre, 10 + food.getX() * squre, squre, squre);
        }
        gg.setStroke(new BasicStroke(5f));
        gg.setColor(Color.blue);
        gg.drawRect(24, 9, squre * column + 2, squre * row + 2);
        gg.dispose();
    }
}


Place.java

package game;

/**
 * here lays the snake's body coordinate information.
 * */
public class Place {
	private int x;
	private int y;
	public Place(){
		this(0, 0);
	}
	public Place(int x, int y) {
		this.x = x;
		this.y = y;
	}
	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;
	}
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + x;
		result = prime * result + y;
		return result;
	}
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Place other = (Place) obj;
		if (x != other.x)
			return false;
		if (y != other.y)
			return false;
		return true;
	}
	
	
}



  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值