贪吃蛇代码

package fenglook;	
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Image;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.border.EmptyBorder;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
public class Myopl extends JPanel implements ActionListener{
private boolean start;//当前游戏状态
private int speed;//速度
private boolean exist;//当前是否存在食物
private int foodType;//食物种类
private int x;//豆子的横坐标
private int y;//豆子的纵坐标
private ArrayList<int[]> localList;//蛇
public String direction;//方向
private String direction2;//引导方向
public boolean flag;
Random rand = new Random();
private ImageIcon up;//向上的头
private ImageIcon down;//向下的头
private ImageIcon right;//向右的头
private ImageIcon left;//向左的头
private ImageIcon body;//身体
private ImageIcon food;//食物
private ImageIcon title;//抬头
Timer time;
private int score;//当前得分情况
private int num;//吃到的食物个数
//private Image offScreenImage;  //图形缓存

//图片绘制
@Override
public void paint(Graphics g) {
	direction = direction2;
	g.setColor(Color.WHITE);//设置白色
	g.fillRect(0, 0, 900, 700);
	
	//绘制游戏框
	//标题框
	g.drawRect(25, 30, 800, 75);//绘制游戏框
	title.paintIcon(this, g, 25, 10);
	//内容框
	g.setColor(Color.black);
	g.fillRect(25, 75, 850, 600);//绘制内容框
	//绘制食物的坐标位置
	if(!exist) {//如果当前不存在豆子,随机绘制一个豆子	
		if(num % 5 == 0) {
			foodType = 1;
		}else {
			foodType = 0;
		}
		boolean isProduce = true;
		while(isProduce) {
			isProduce = false;
			x = rand.nextInt(33) * 25 + 25;		
			y = rand.nextInt(23) * 25 + 75;			
			for (int[] arr:localList) {
				if(x == arr[0] && y == arr[1]) {	
					isProduce = true;
					break;	
				}
			}
			
		}			
		System.out.println(x + "---" + y);
	}
	
	 if(eat()) {
        exist = false;
	 }else {
		exist = true;
	 }
	 
	if(foodType == 0) {
		//绘制食物
		g.setColor(Color.blue);
//		g.fillRect(x, y, 25, 25);
		g.drawImage(food.getImage(),x, y, 25, 25,null);
	}else {
		//绘制食物
		g.setColor(Color.WHITE);
		g.fillRect(x, y, 25, 25);
//		g.drawImage(food.getImage(),x, y, 25, 25,null);
	}

	//绘制头
	g.setColor(Color.red);
//	g.fillRect(localList.get(0)[0], localList.get(0)[1], 25, 25);	
	ImageIcon head = null;
	//判断当前方向
	if(direction.equals("R")) {
		 head = right;
	}else if(direction.equals("L")) {
		 head = left;
	}else if(direction.equals("U")) {
		 head = up;
	}else if(direction.equals("D")) {
		 head = down;
	}		
	g.drawImage(head.getImage(), localList.get(0)[0], localList.get(0)[1], 25, 25,null);
	head.paintIcon(this, g,localList.get(0)[0], localList.get(0)[1]);
	
	//绘制身体
	g.setColor(Color.white);
	for (int i = 1; i < localList.size(); i++) {
//		g.fillRect(localList.get(i)[0], localList.get(i)[1], 25, 25);
//		g.drawImage(body.getImage(), localList.get(i)[0], localList.get(i)[1], 25, 25,null);
		body.paintIcon(this, g, localList.get(i)[0], localList.get(i)[1]);
	}
//	g.fillRect(localList.get(1)[0], localList.get(1)[1], 25, 25);
//	g.fillRect(localList.get(2)[0], localList.get(2)[1], 25, 25);
		
	//绘制分数和长度
	//长度
	g.setColor(Color.GREEN);
	g.setFont(new Font("宋体", Font.BOLD, 18));
	g.drawString("长度:" + (localList.size() - 1), 25, 30);
	
	//分数
	g.drawString("分数:" + score, 25, 48);
	
	if(!start) {//如果游戏未启动,结束移动和重绘
		g.setColor(Color.white);
		g.setFont(new Font("宋体", Font.BOLD, 30));
		g.drawString("暂停/开始(请按任意键开始,空格键暂停)", 150, 300);
		time.stop();
	}else {
		time.start();
	}
		
//	speed();
	//移动后进行下一次绘制		
//  move();//移动
//	repaint();//重新绘制		
}

解决闪烁问题
如果为JFrame 为重量级  程序不会调用update()方法
如果为Frame 为轻量级  重写update()方法 做双缓冲
如果为JPanel 不会闪烁
//  @Override
//    public void update(Graphics g)
//    {
//    	System.out.println("update");
//           if(offScreenImage == null)
//              offScreenImage = this.createImage(900, 700);  //新建一个图像缓存空间,这里图像大小为800*600
//              Graphics gImage = offScreenImage.getGraphics();  //把它的画笔拿过来,给gImage保存着
//              paint(gImage);                                   //将要画的东西画到图像缓存空间去
//              g.drawImage(offScreenImage, 0, 0, null);         //然后一次性显示出来
//    }

@Override
public void actionPerformed(ActionEvent e) {	    
    //移动后进行下一次绘制		
    move();//移动
    repaint();//重新绘制		
	
}

/**
 * 绘制速度
 */
//private void speed() {
//	try {//按一定速度进行移动
//		Thread.sleep(speed);//控制移动速度
//	} catch (InterruptedException e) {
//		// TODO 自动生成的 catch 块
//		e.printStackTrace();
//	}
//}

/**
 * 初始化图片
 */
private void drawImage() {
	up = new ImageIcon("images\\up.png");
	down = new ImageIcon("images\\down.png");
	right = new ImageIcon("images\\right.png");
	left = new ImageIcon("images\\left.png");
	body = new ImageIcon("images\\body.png");
	food = new ImageIcon("images\\food.png");
	title = new ImageIcon("images\\title.jpg");
}

private boolean eat() {
	if(localList.get(0)[0] == x && localList.get(0)[1] == y) {//如果当前蛇头吃到了豆子
		System.out.println("eat");
		num++;
		if(foodType == 0) {
			score += 10;
		}else {
			score += (rand.nextInt(5) * 10 + 10);
		}
		int last = localList.size() - 1;//蛇尾			
		//在蛇尾后面添加一节身体
		localList.add(new int[] {localList.get(last)[0],localList.get(last)[1]});
		return true;
	}
	return false;
}

//移动方法
public void move() {
	//判断是否游戏结束
	if(isbody()) {
		System.out.println("game over");
		start = false;//结束游戏移动
		JOptionPane.showMessageDialog(null,"游戏已结束!");
		time.stop();
		init();		
	}
		
	if(flag && localList != null) {//如果长度不为空且游戏未结束				
		int last = localList.size() - 1;//记录蛇尾
		
		for (int i = last; i > 0; i--) {//从蛇尾开始,每节身体移动到前一节身体的位置上
			localList.set(i,new int[] {localList.get(i - 1)[0],localList.get(i - 1)[1]});
		}
		
		//记录头位置
		int[] local = localList.get(0);
		//判断当前方向,并进行模拟移动,判断是否与边界重合
		if(direction.equals("R")) {
			if(local[0] >= 850) {
				local[0] = 25;
			}else {
				local[0] += 25;
			}
			
		}else if(direction.equals("L")) {
			if(local[0] <= 25) {
				local[0] = 850;
			}else {
				local[0] -= 25;
			}
			
		}else if(direction.equals("U")) {
			
			if(local[1] <= 75) {
				local[1] = 650;
			}else {
				local[1] -= 25;
			}
			
		}else if(direction.equals("D")) {
			if(local[1] >= 650) {
				local[1] = 75;
			}else {
				local[1] += 25;
			}
			
		}			
					
		//更改头的位置
		localList.set(0, local);		
	}	
}

//判断下一步是否为蛇身
private boolean isbody() {
	// TODO 自动生成的方法存根
	//记录头位置
	int x = localList.get(0)[0];
	int y = localList.get(0)[1];

	//判断当前方向,并进行模拟移动,判断是否与边界重合
	if(direction.equals("R")) {
		x += 25;
	}else if(direction.equals("L")) {
		x -= 25;
	}else if(direction.equals("U")) {
		y -= 25;
	}else if(direction.equals("D")) {
		y += 25;
	}			
	
	for (int i = 1; i < localList.size(); i++) {
		if(localList.get(i)[0] == x && localList.get(i)[1] == y) {
			return true;
		}
	}
	return false;

}

判断下一步是否为边界
//private boolean isborder() {
//	// TODO 自动生成的方法存根
//	//记录头位置
//	// TODO 自动生成的方法存根
//	//记录头位置
//	int x = localList.get(0)[0];
//	int y = localList.get(0)[1];
//
//	//判断当前方向,并进行模拟移动,判断是否与边界重合
//	if(direction.equals("R")) {
//		x += 25;
//	}else if(direction.equals("L")) {
//		x -= 25;
//	}else if(direction.equals("U")) {
//		y -= 25;
//	}else if(direction.equals("D")) {
//		y += 25;
//	}	
//			
//	if(x < 25 || x > (33 * 25 + 25)) {
//		return true;//当x坐标超出边界,则返回true
//	}
//	if(y < 105 || y > (23 * 25 + 105)) {
//		return true;//当y坐标超出边界,则返回true
//	}
//	return false;//蛇头移动后未超出边界,返回false
//	
//}

/**
 * Create the frame.
 */
public Myopl(int speed) {
	
	this.speed = speed; //初始化速度
	
	//初始化游戏面板的基本信息
	this.setSize(900, 700);
	this.setLocation(0, 30);
	this.setFocusable(true);
	
	init();//初始化界面
	drawImage();//绘制图片
	moveByKey();//给界面添加一个键盘监听
			
}

/*
 * 键盘监听
 * 通过键盘输入上下左右来控制当前蛇头移动的方向
 * 先判断当前蛇头方向,再来改变引导方向
 * 当进行绘制时再修改蛇的方向
 * 保证不会因为在短时间内快速变换方向导致蛇头逆向转向
 */
private void moveByKey() {
	addKeyListener(new KeyAdapter() {
		@Override
		public void keyPressed(KeyEvent e) {
			int key = e.getKeyCode();
			//边界值判断
			switch(key) {
			case 65:
			case 37:{//向左走
				if(!direction.equals("R")) {
					direction2 = "L";
					
				}
				break;
			}				
			case 87:
			case 38:{//向上走
				if(!direction.equals("D")) {
					direction2 = "U";
				}				
				break;
			}				
			case 68:
			case 39:{//向右走
				if(!direction.equals("L")) {
					direction2 = "R";
				}
				break;
			}
			case 83:
			case 40:{//向下走
				if(!direction.equals("U")) {
					direction2 = "D";
				}					
				break;
			}
			case KeyEvent.VK_SPACE:{//如果当前键盘输入为空格
				start = !start;//调整游戏状态
				System.out.println("暂停/开始");
				repaint();//重绘
			}
			}
			
			//任意键开始
			if(!start && key != KeyEvent.VK_SPACE) {//如果当前状态为暂停状态,且键盘输入不是空格
				start = true;
				repaint();//重绘
				
			}				
		}
	});
}

/**
 * 初始化游戏基本信息
 */
private void init() {
	start = false;
	exist = true;
	direction2 = "U";
	flag = true;
	localList = new ArrayList<int[]>();
	localList.add(0,new int[] {75,125});//蛇头
	localList.add(1,new int[] {75,150});//蛇身1
	localList.add(2,new int[] {75,175});//蛇身2
	//创建第一个食物的位置
	//通过循环保证当前生成的食物不在身体所在的坐标上
	boolean isProduce = true;
	while(isProduce) {//循环生成食物坐标
	isProduce = false;//结束本次循环
	x = rand.nextInt(33) * 25 + 25;		
	y = rand.nextInt(23) * 25 + 75;			
	for (int[] arr:localList) {//循环遍历蛇头及蛇身的坐标
	if(x == arr[0] && y == arr[1]) {//如果食物坐标和蛇的某一节坐标重合
	isProduce = true;//跳转循环状态,继续下一次食物生成
	break;	
			}
	}
		//蛇身遍历完成,没有重合坐标,结束食物坐标生成					
}
	time = new Timer(speed, this);
	setLayout(null);
	score = 0;
	num = 0;
	foodType = 0;
repaint();	
}
}
package fenglook;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
 
public class Aqopm {
	public static void main(String[] args) {
		
		int speed = 0;
		String showInputDialog = null;//初始化时间
		//得到速度
		while(true) {
			showInputDialog = JOptionPane.showInputDialog("蛇移动速度(1 - 5)","3");
			
			if(showInputDialog == null) {
				showInputDialog = "3";//默认速度
				break;
			}
			if(showInputDialog.length() > 1) {
				continue;
			}
			char[] a = showInputDialog.toCharArray();
			if(a[0] >= '1' && a[0] <= '5') { 
				break;
			}
		}
			
		speed = Integer.parseInt(showInputDialog) * 50;
		
		
		 Myopl snakeJPanel = new  Myopl(speed);
		
		//创建一个JFrame窗口,将游戏面板添加进行窗口中
		JFrame jFrame = new JFrame();
		//设置窗口的某些属性
		jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		jFrame.setSize(920, 750);
	    jFrame.add(snakeJPanel);
	    jFrame.setLocationRelativeTo(null);
	    jFrame.setVisible(true);
	}
 
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值