java贪吃蛇

java贪吃蛇_第1张图片


思路  :主要是模拟蛇的运动。只要对蛇头进行操作,然后让前一种状态先的蛇头位置复制给现在蛇身的第二个部分,让前一状态的蛇的第二个部分的位置复制给现在蛇身的第三个部分......以此类推,从而达到模拟蛇运动的状态。


GluttonousSnake.java

package xjj;
//贪吃蛇图形界面
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Observable;
import java.util.Observer;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.border.TitledBorder;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

public class GluttonousSnake extends JFrame implements ActionListener {
	private JButton upButton, downButton, leftButton, rightButton;//控制方向按钮
	private JTextField score;//分数
	private SnakeCanvas snake;//蛇的模型

	public GluttonousSnake() {
		super("贪吃蛇");//设置标题
		this.setSize(725, 515);//设置大小
		this.setDefaultCloseOperation(EXIT_ON_CLOSE);//设置退出按键
		this.setLocationRelativeTo(null);//设置窗口居中
		JPanel p = new JPanel();//控制按钮和显示分数面板
		p.setBorder(new TitledBorder("控制和显示区"));//设置这个面板的标题
		this.getContentPane().add(p, "East");//设置此面板的位置
		p.setLayout(new GridLayout(4, 1));//设置此面板的布局方式,为网格布局方式
		JPanel p2 = new JPanel();//在此面板中添加显示分数的面板
		p2.setLayout(new FlowLayout());//设置为流布局方式
		p2.add(new JLabel("得分:"));
		score = new JTextField("0");
		score.setEditable(false);
		p2.add(score);
		p.add(p2);
		//添加按钮,有图片的并添加事件监听
		upButton = new JButton("", new ImageIcon("up.png"));
		upButton.setActionCommand("up");
		upButton.addActionListener(this);
		downButton = new JButton("", new ImageIcon("down.png"));
		downButton.setActionCommand("down");
		downButton.addActionListener(this);
		leftButton = new JButton("", new ImageIcon("left.png"));
		leftButton.setActionCommand("left");
		leftButton.addActionListener(this);
		rightButton = new JButton("", new ImageIcon("right.png"));
		rightButton.setActionCommand("right");
		rightButton.addActionListener(this);
		p.add(upButton);
		JPanel p1 = new JPanel();
		p1.setLayout(new GridLayout(1, 2));
		p1.add(leftButton);
		p1.add(rightButton);
		p.add(p1);
		p.add(downButton);

		addMenu();//添加菜单
		start();
		this.setResizable(false);
		this.setVisible(true);

	}

	private void start() {
		snake = new SnakeCanvas();
		this.getContentPane().add(snake);
	}

	private void addMenu() {
		JMenuBar menubar = new JMenuBar();
		this.setJMenuBar(menubar);
		JMenu game = new JMenu("游戏");
		JMenu help = new JMenu("帮助");
		JMenuItem jitemNew = new JMenuItem("新游戏");
		jitemNew.setActionCommand("new");
		jitemNew.addActionListener(this);
		JMenuItem jitemPause = new JMenuItem("暂停");
		jitemPause.setActionCommand("pause");
		jitemPause.addActionListener(this);
		JMenuItem jitemExit = new JMenuItem("退出");
		jitemExit.setActionCommand("exit");
		jitemExit.addActionListener(this);
		game.add(jitemNew);
		game.add(jitemPause);
		game.addSeparator();//菜单里设置分隔线
		game.add(jitemExit);
		menubar.add(game);
		menubar.add(help);
	}

	public static void main(String[] args) {
		new GluttonousSnake();
	}

	public void actionPerformed(ActionEvent e) {
		if (e.getActionCommand().equalsIgnoreCase("exit")) {
			System.exit(EXIT_ON_CLOSE);
		}
		if (e.getSource() instanceof JButton) {
			if (e.getActionCommand().equalsIgnoreCase("up")) {//响应向上按钮按下事件
				snake.setDirect(1);//设置蛇头运动方向
				snake.repaint();//对蛇模型重新画
				snake.timer.start();//定时器开始
				return;
			}
			if (e.getActionCommand().equalsIgnoreCase("down")) {
				snake.setDirect(2);
				snake.repaint();
				snake.timer.start();
				return;
			}
			if (e.getActionCommand().equalsIgnoreCase("left")) {
				snake.setDirect(3);
				snake.repaint();
				snake.timer.start();
				return;
			}
			if (e.getActionCommand().equalsIgnoreCase("right")) {
				snake.setDirect(4);
				snake.repaint();
				snake.timer.start();
				return;
			}
		}
		if (e.getSource() instanceof JMenuItem) {
			if (e.getActionCommand().equalsIgnoreCase("new")) {
				//this.getContentPane().remove(snake);
				snake.init();
				snake.repaint();
				snake.timer.start();
			}
			if (e.getActionCommand().equalsIgnoreCase("pause")) {
				snake.timer.stop();
				JOptionPane.showMessageDialog(this, "继续请按“确定”");
				snake.timer.start();
			}
		}
	}

	


}


MapCanvas.java

package xjj;

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics;
//蛇运行的地图
public class MapCanvas extends Canvas{

	public void paint(Graphics g) {
		g.setColor(Color.red);
		for(int i=30;i<=450;i+=30){
			g.drawLine(0,i,450,i);
		}
		for(int i=30;i<=450;i+=30){
			g.drawLine(i,0,i,450);
		}
		g.drawLine(0, 0, 450, 0);
		g.drawLine(0, 450, 450, 450);
		g.drawLine(0, 0, 0, 450);
		g.drawLine(450, 0, 450, 450);
	}

}

SnakeCanvas.java

package xjj;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;

import javax.swing.JOptionPane;
import javax.swing.Timer;
//蛇模型
public class SnakeCanvas extends MapCanvas implements ActionListener {
	private int number = 5;//蛇身的初始长度
	public Timer timer;//定时器
	private Body[] bodys;//蛇身
	private Body food;//食物
	public int score=0;//分数
	private int speed=250;//定时器延时事件
	int direct = 3;//蛇头初始方向
	private int[][] mapflag = new int[455][455];//地图标记
	//初始化
	public void init(){
		this.direct=3;
		this.number=5;
		this.bodys = new Body[this.number];
		mapflag = new int[455][455];
		for (int i = 0, x = 300; i < this.number; i++, x += 30) {
			bodys[i] = new Body(x, 180);
			mapflag[bodys[i].x][bodys[i].y] = 2;//如果是蛇体  设标记为2
		}
		food = creatFood();//创建食物   
		
	}
	public SnakeCanvas() {
		init();
		timer = new Timer(speed, this);//创建定时器对象
		timer.start();//定时器启动
	}

	private class Body {//蛇头成员
		int x, y;

		Body(int x, int y) {
			this.x = x;
			this.y = y;
		}
	}

	public void paint(Graphics g) {//画图
		super.paint(g);
		if(bodys==null){
			return ;
		}
		for (int i = 0; i < this.number; i++) {
			if(i==0){//设置蛇头颜色不同
				g.setColor(Color.blue);
			}else{
				g.setColor(Color.black);
			}
			mapflag[bodys[i].x][bodys[i].y] = 2;
			g.fillOval(bodys[i].x, bodys[i].y, 30, 30);//画蛇体
		}

		g.setColor(Color.red);
		g.fillOval(food.x, food.y, 30, 30);//画食物
	}

	public Body creatFood() {
		int x = 0, y = 0;
		do {//随机生成食物位置

			Random r = new Random();//创建随机数对象
			x = r.nextInt(450);//在0到所给的数中随机产生一个伪随机数
			y = r.nextInt(450);
			//System.out.println(mapflag[x][y]+"!");
		} while (x % 30 != 0 || y % 30 != 0 ||  mapflag[x][y]==2 );//保证位置不是蛇身的部分,并且确保整齐性
		//System.out.println(x + " " + y);
		mapflag[x][y] = 1;//将食物标记为1,下面就可以通过标记的不同来判断是吃到食物还是自身,从而进行不同的操作
		return new Body(x, y);
	}

	public void actionPerformed(ActionEvent e) {
		if(bodys==null){
			return ;
		}
		if(!isMove()){//如果移动失败,游戏结束
			JOptionPane.showMessageDialog(this, "Game Over !");
			bodys=null;
			timer.stop();
			return ;
		}
		repaint();
	}
	//蛇移动,原理:仅需对蛇头进行操作,然后将蛇头之前的位置赋值给现在蛇身的第二个部分,
	//让之前的第二个部分复制个现在的第三个部分。。。。以此类推,模拟蛇运动(这是关键)
	public void move(int x,int y) {
		Body[] b=new Body[bodys.length];
		for(int i=0;i<this.number;i++){
			b[i]=new Body(bodys[i].x,bodys[i].y);
		}
		this.bodys[0].x=x;
		this.bodys[0].y=y;
		for(int i=1;i<this.number;i++){
			this.bodys[i]=b[i-1];
		}
		setMapflag();
		
	}

	private void setMapflag() {//地图标记的刷新
		mapflag=new int[455][455];
		mapflag[food.x][food.y]=1;
		for(int i=0;i<this.number;i++){
			mapflag[bodys[i].x][bodys[i].y]=2;
		}
	}
	//判断是否移动成功
	public boolean isMove() {
		if(bodys==null){
			return false;
		}
		int x=bodys[0].x;
		int y=bodys[0].y;
		switch (this.direct) {//通过方向的不同对蛇头进行不同的操作
		case 1:
			y -= 30;
			break;
		case 2:
			y += 30;
			break;
		case 3:
			x -= 30;
			break;
		case 4:
			x += 30;
			break;
		}
		if(x<0||y>=450||x>=450||y<0){//越界问题
			return false;
		}
		if(mapflag[x][y]==1){//标记为1 ,则为蛇头,要添加蛇身长度
			this.number++;
			addSnake(x,y);//添加蛇长
//			System.out.println("*");
			return true;
		}else if(mapflag[x][y]==2){//标记为2,则为蛇体,即自己吃到自己,游戏结束
//			System.out.println("^");
			return false;
		}else{
//			System.out.println("%");
			move(x,y);
			return true;
		}
	}
	//添加蛇身,类似move();
	private void addSnake(int x, int y) {
		this.score++;
		Body[] b=new Body[bodys.length];
		for(int i=0;i<this.number-1;i++){
			b[i]=new Body(bodys[i].x,bodys[i].y);
		}
		bodys=new Body[this.number];
		this.bodys[0]=new Body(x,y);
		for(int i=1;i<this.number;i++){
			this.bodys[i]=b[i-1];
		}
		setMapflag();
		food = creatFood();
	}

	public void setDirect(int i) {//设置蛇头方向
		this.direct = i;
	}

}


你可能感兴趣的:(java,贪吃蛇)