简易贪吃蛇(JavaSE实现)

本文详细介绍了如何使用Java实现一个简单的贪吃蛇游戏。从创建窗体和画布,到画网格、画蛇及蛇的移动,再到游戏结束的判断,以及食物的生成和吃食物的逻辑,一步步剖析了游戏的实现过程。此外,还添加了暂停和开始功能,并展示了游戏结束的艺术字和食物的随机生成。整个过程结合了图形界面、键盘监听和多线程技术,是Java初学者很好的实践项目。
摘要由CSDN通过智能技术生成

以前的Java练手,尽量写的细一些,希望有人有所收获。

思路

一:创建窗体和画布

二:画网格

(1) 确定画竖线39条,横线27条

(2) 使用两个for循环画出网格


三:画蛇并且移动

(1) 在paint方法中使用for循环遍历集合并调用画蛇的方法

(2) 定义一个蛇移动的方法,注意:继承键盘监听器,在按压键盘的方法中完成上下左右对蛇的状态的控制.

(3) 写一个蛇移动的方法,根据蛇的状态改变坐标

(4) 在实现runable接口,完成run方法对蛇移动方法的调用

(5) 获取焦点,添加键盘监听,启动线程


四:游戏的结束

(1) 写一个游戏结束的方法,方法的返回值是boolean,参数是蛇对象,根据if条件判断什么时候该结束游戏,游戏结束返回true,否则返回flase

(2) 在paint方法中根据游戏结束的方法的返回值来确定画游戏结束字体

(3) 将run方法中的while循环条件修改成方法的返回值


五:画食物

(1) 随机生成食物坐标

(2) 循环判断食物和集合中的每一个蛇的坐标是否一致,不一致就要重新生成.并重新比较


六:吃食物

(1) 蛇头和食物坐标一致表示吃食物

(2) 吃食物蛇集合就应该增加一个蛇对象

(3) New的蛇对象的坐标是前一个蛇对象保留下的坐标

(4) 返回去在蛇移动的时候就应该修改成先保留在移动

(5) 迟到食物,食物开关标识flase,与此同时在run方法中if判断食物消失,调用创建食物的方法,创建食物,食物标识就应该改为true


七:蛇身移动

(1) 蛇身移动之前应该保留坐标

(2) 赋值的坐标是前一个蛇对象保留下的坐标


初版程序与注释

SnakeJFrame.java

package snake;

import javax.swing.JFrame;

public class SnakeJFrame extends JFrame{
	public SnakeJFrame() {
		this.setTitle("贪吃蛇");//设置窗体标题
		this.setSize(1000, 700);//设置窗体大小
		this.setLocationRelativeTo(null);//居中
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//关闭程序与停止dos运行没有设置的话,默认点关闭时只是隐藏窗体,在后台进程中还可以看到,如果有多个窗口,只是销毁调用dispose的窗口,其他窗口仍然存在,整个应用程序还是处于运行状态。
		this.setResizable(false);//设置此窗体不可由用户调整大小
		
		SnakeJPanel panel=new SnakeJPanel();
		this.add(panel);
		
		this.setVisible(true);//设置可见
	}
	public static void main(String[] args) {
		new SnakeJFrame();
	}
}

SnakeJPanel.java

package snake;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;

import javax.swing.JPanel;

public class SnakeJPanel extends JPanel implements KeyListener,Runnable{
	//网格大小25*25  横着画38   竖着画26个
	int size=25;
	int across=38;//横格
	int vertical=26;//竖格

	//定义一个集合存放蛇
	ArrayList snakes=new ArrayList();
	
	//定义蛇可能走的四个方向
	int UP=0;
	int DOWN=1;
	int LEFT=2;
	int RIGHT=3;
	
	//定义蛇的初始方向
	int StartF=-1;
	
	//创建一个线程
	Thread t=new Thread(this);
	
	//设置一个开关来声明是否有食物(标识窗体中是否有食物)
	boolean hadFood=true;
	//创建食物坐标
	int food_x;
	int food_y;
	
	public SnakeJPanel() {
		//在构造方法中生成蛇
		Snake snake=new Snake((int)(Math.random()*across)*size+4, (int)(Math.random()*vertical)*size+4);
		snakes.add(snake);
		setFocusable(true);//获取键盘焦点
		addKeyListener(this);//添加键盘监听
		t.start();
		creat_food();//创建食物
	}
	
	@Override
	public void paint(Graphics g) {
		super.paint(g);//paint(g)函数会重绘图像,要加上super.paint(g),表示在原来图像的基础上,再画图。如果不加super.paint(g),重绘时,会将原有的绘制清空,再根据paing(g)函数绘制。
		//画网格
		//画横线  用竖格变量
		for (int i = 0; i <=vertical; i++) {
			g.drawLine(4, 4+size*i, 4+across*size, 4+size*i);//在此图形的坐标系中,使用当前颜色在点 (x1, y1) 和 (x2, y2) 之间画一条线。
		}
		//画竖线  用横格变量
		for (int i = 0; i <=across; i++) {
			g.drawLine(4+size*i, 4, 4+size*i, 4+vertical*size);
		}
		//画蛇
		for (int i = 0; i < snakes.size(); i++) {
			Snake snake=(Snake) snakes.get(i);
			snake.drawSnake(g);
		}
		//游戏结束
		if(GameOver((Snake)snakes.get(0))){
			//写艺术字
			for (int i = 0; i < 10; i++) {
				g.setFont(new Font("微软雅黑", Font.BOLD, 70));
				g.setColor(new Color((int)(Math.random()*255), (int)(Math.random()*255), (int)(Math.random()*255)));
				g.drawString("游戏结束", 300-i, 300-i);
			}
		}
		//画食物
		if(hadFood){
			g.fillRect(food_x, food_y, size, size);
		}
		/*
		//画边框
		Graphics2D g2=(Graphics2D) g;
		g2.setColor(Color.BLACK);
		g2.setStroke(new BasicStroke(8));
		g2.drawRect(0, 0, 958, 658);
		*/
	}


	@Override
	public void keyPressed(KeyEvent e) {
		if(e.getKeyCode()==KeyEvent.VK_LEFT){//判断按键是否为←, VK_LEFT是左方向键默认的值
			if(StartF==-1 || StartF==UP ||StartF==DOWN){
				StartF=LEFT;
			}
		}
		if(e.getKeyCode()==KeyEvent.VK_RIGHT){
			if(StartF==-1 || StartF==UP ||StartF==DOWN){
				StartF=RIGHT;
			}
		}
		if(e.getKeyCode()==KeyEvent.VK_UP){
			if(StartF==-1 || StartF==LEFT ||StartF==RIGHT){
				StartF=UP;
			}
		}
		if(e.getKeyCode()==KeyEvent.VK_DOWN){
			if(StartF==-1 || StartF==LEFT ||StartF==RIGHT){
				StartF=DOWN;
			}
		}
	}

	@Override
	public void run() {
		while (!GameOver((Snake)snakes.get(0))) {
			moveSnake();//蛇头的移动
			moveSnake2();//蛇身的移动
			eatFood();//吃到食物
			if(!hadFood){
				creat_food();
			}
			try {
				Thread.sleep(100);//每100毫秒重绘一次
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			repaint();
		}
	}
	
	//定义蛇头移动的方法
	//把蛇头的坐标保存下作为蛇身移动用
	//定义一个蛇移动的方法
	public void moveSnake(){
		if(StartF==LEFT){
			Snake snake=(Snake) snakes.get(0);
			snake.Oldx=snake.x;//将蛇移动之前的坐标留下
			snake.Oldy=snake.y;//将蛇移动之前的坐标留下
			snake.x-=size;
		}
		if(StartF==RIGHT){
			Snake snake=(Snake) snakes.get(0);
			snake.Oldx=snake.x;//将蛇移动之前的坐标留下
			snake.Oldy=snake.y;//将蛇移动之前的坐标留下
			snake.x+=size;
		}
		if(StartF==UP){
			Snake snake=(Snake) snakes.get(0);
			snake.Oldx=snake.x;//将蛇移动之前的坐标留下
			snake.Oldy=snake.y;//将蛇移动之前的坐标留下
			snake.y-=size;
		}
		if(StartF==DOWN){
			Snake snake=(Snake) snakes.get(0);
			snake.Oldx=snake.x;//将蛇移动之前的坐标留下
			snake.Oldy=snake.y;//将蛇移动之前的坐标留下
			snake.y+=size;
		}
	}
	//蛇身移动的方法
	public void moveSnake2(){
		for (int i = 1; i < snakes.size(); i++) {
			//在移动之前将坐标保留,做下一个蛇身移动
			Snake snake=(Snake) snakes.get(i);
			snake.Oldx=snake.x;
			snake.Oldy=snake.y;
			//前一个蛇的坐标
			Snake snake2=(Snake) snakes.get(i-1);
			snake.x=snake2.Oldx;
			snake.y=snake2.Oldy;
		}
	}
	
	//写一个方法判断游戏结束
	public boolean GameOver(Snake snake){
		if(snake.x<0 || snake.x>925 || snake.y<0 || snake.y>625){
			return true;//游戏结束返回true
		}
		return false;//游戏没结束返回false
	}
	
	//创建食物的方法
	public void creat_food(){
		food_x=(int) (Math.random()*across)*size+4;
		food_y=(int) (Math.random()*vertical)*size+4;
		for (int i = 0; i < snakes.size(); i++) {
			Snake snake=(Snake) snakes.get(i);
			if(food_x==snake.x && food_y==snake.y){
				food_x=(int) (Math.random()*across)*size+4;
				food_y=(int) (Math.random()*vertical)*size+4;
				i=0;
			}
		}
		hadFood=true;
	}
	
	//定义一个蛇吃食物的方法
	public void eatFood(){
		//蛇头和食物完全重合标识吃到食物
		Snake snake=(Snake) snakes.get(0);
		if(snake.x==food_x && snake.y==food_y){
			Snake snake2=(Snake) snakes.get(snakes.size()-1);
			Snake snake3=new Snake(snake2.Oldx, snake2.Oldy);
			snakes.add(snake3);
			hadFood=false;
			//蛇身肯定是新new一个snake对象,蛇吃食物的一瞬间,前一次移动的最后一格坐标是吃了食物后的最后一格坐标
		}
	}
	//keyTyped,keyReleased,keyPressed实现KeyListener类时生成的函数 作用是监听键盘 我们是需要用第二 即键盘按下时的反映
	@Override
	public void keyTyped(KeyEvent e) {
		// TODO Auto-generated method stub

	}

	@Override
	public void keyReleased(KeyEvent e) {
		// TODO Auto-generated method stub

	}
}

Snake.java

package snake;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;

public class Snake {
	int x,y;//定义蛇的坐标
	int Oldx,Oldy;//定义两个变量来保存蛇在走之前留下的坐标
	public Snake(int x,int y) {
		this.x=x;
		this.y=y;
	}
	//画蛇的方法
	public void drawSnake(Graphics g){
		g.setColor(Color.red);
		g.fillRect(x, y, 25, 25);//用预定的颜色填充一个矩形,得到一个着色的矩形块。
	}
}

实现过程

创建窗体和画布

SnakeJFrame.java

package snank;

import javax.swing.JFrame;

public class SnakeJFrame extends JFrame{
	public SnakeJFrame() {
		this.setTitle("贪吃蛇");
		this.setSize(978, 700);
		this.setLocationRelativeTo(null);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		this.setResizable(false);
		
		this.setVisible(true);
	}
	
	public static void main(String[] args) {
		new SnakeJFrame();
	}
}

画网格

(1) 确定画竖线39条,横线27条

(2) 使用两个for循环画出网格

SnakeJFrame.java

package snank;

import javax.swing.JFrame;

public class SnakeJFrame extends JFrame{
	public SnakeJFrame() {
		this.setTitle("贪吃蛇");
		this.setSize(978, 700);
		this.setLocationRelativeTo(null);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		this.setResizable(false);
		
		SnakeJPanel panel=new SnakeJPanel();
		this.add(panel);

		this.setVisible(true);
	}

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

SnakeJFrame.java已完成。

SnakeJPanel.java

package snank;

import java.awt.Graphics;

import javax.swing.JPanel;

public class SnakeJPanel extends JPanel{
	int size = 25;
	int across = 38;
	int vertical = 26;
	
	public void paint(Graphics g) {
		super.paint(g);
		for (int i = 0; i <=vertical; i++) {
			g.drawLine(6, 6+size*i, 6+across*size, 6+size*i);
		}
		for (int i = 0; i <=across; i++) {
			g.drawLine(6+size*i, 6, 6+size*i, 6+vertical*size);
		}
	}
}

画蛇并且移动

(1) 在paint方法中使用for循环遍历集合并调用画蛇的方法

SnakeJFrame.java

package snank;

import javax.swing.JFrame;

public class SnakeJFrame extends JFrame{
	public SnakeJFrame() {
		this.setTitle("贪吃蛇");
		this.setSize(978, 700);
		this.setLocationRelativeTo(null);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		this.setResizable(false);
		
		SnakeJPanel panel=new SnakeJPanel();
		this.add(panel);

		this.setVisible(true);
	}

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

SnakeJPanel.java

package snank;

import java.awt.Graphics;
import java.util.ArrayList;

import javax.swing.JPanel;

public class SnakeJPanel extends JPanel{
	int size = 25;
	int across = 38;
	int vertical = 26;
	
	ArrayList snakes = new ArrayList();
	
	public void paint(Graphics g) {
		super.paint(g);
		for (int i = 0; i <=vertical; i++) {
			g.drawLine(6, 6+size*i, 6+across*size, 6+size*i);
		}
		for (int i = 0; i <=across; i++) {
			g.drawLine(6+size*i, 6, 6+size*i, 6+vertical*size);
		}
		
		for (int i = 0; i < snakes.size(); i++) {
			Snake snake=(Snake) snakes.get(i);
			snake.drawSnake(g);
		}
	}
	
	public SnakeJPanel() {
		Snake snake=new Snake((int)(Math.random()*across)*size+6, (int)(Math.random()*vertical)*size+6);
		snakes.add(snake);
	}
	
}

Snake.java

package snank;

import java.awt.Color;
import java.awt.Graphics;

public class Snake {
	int x,y;
	
	public Snake(int x,int y) {
		this.x=x;
		this.y=y;
	}
	
	public void drawSnake(Graphics g) {
		g.setColor(Color.red);
		g.fillRect(x, y, 25, 25);
	}
}

(2) 定义一个蛇移动的方法,注意:继承键盘监听器,在按压键盘的方法中完成上下左右对蛇的状态的控制.

(3) 写一个蛇移动的方法,根据蛇的状态改变坐标

(4) 在实现runable接口,完成run方法对蛇移动方法的调用

(5) 获取焦点,添加键盘监听,启动线程

SnakeJFrame.java

package snank;

import javax.swing.JFrame;

public class SnakeJFrame extends JFrame{
	public SnakeJFrame() {
		this.setTitle("贪吃蛇");
		this.setSize(978, 700);
		this.setLocationRelativeTo(null);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		this.setResizable(false);
		
		SnakeJPanel panel=new SnakeJPanel();
		this.add(panel);

		this.setVisible(true);
	}

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

SnakeJPanel.java

package snank;

import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;

import javax.swing.JPanel;

public class SnakeJPanel extends JPanel implements KeyListener,Runnable{
	int size = 25;
	int across = 38;
	int vertical = 26;
	
	ArrayList snakes = new ArrayList();
	
	int UP=0;
	int DOWN=1;
	int LEFT=2;
	int RIGHT=3;
	
	int StartF=-1;
	
	Thread t = new Thread(this);
	
	public void paint(Graphics g) {
		super.paint(g);
		for (int i = 0; i <=vertical; i++) {
			g.drawLine(6, 6+size*i, 6+across*size, 6+size*i);
		}
		for (int i = 0; i <=across; i++) {
			g.drawLine(6+size*i, 6, 6+size*i, 6+vertical*size);
		}
		
		for (int i = 0; i < snakes.size(); i++) {
			Snake snake=(Snake) snakes.get(i);
			snake.drawSnake(g);
		}
	}
	
	public SnakeJPanel() {
		Snake snake=new Snake((int)(Math.random()*across)*size+6, (int)(Math.random()*vertical)*size+6);
		snakes.add(snake);
		setFocusable(true);
		addKeyListener(this);
		t.start();
	}
	
	public void keyPressed(KeyEvent e) {
		if(e.getKeyCode()==KeyEvent.VK_LEFT){
			if(StartF==-1 || StartF==UP ||StartF==DOWN){
				StartF=LEFT;
			}
		}
		if(e.getKeyCode()==KeyEvent.VK_RIGHT){
			if(StartF==-1 || StartF==UP ||StartF==DOWN){
				StartF=RIGHT;
			}
		}
		if(e.getKeyCode()==KeyEvent.VK_UP){
			if(StartF==-1 || StartF==LEFT ||StartF==RIGHT){
				StartF=UP;
			}
		}
		if(e.getKeyCode()==KeyEvent.VK_DOWN){
			if(StartF==-1 || StartF==LEFT ||StartF==RIGHT){
				StartF=DOWN;
			}
		}
	}
	@Override
	public void keyTyped(KeyEvent e) {
		// TODO 自动生成的方法存根	
	}
	@Override
	public void keyReleased(KeyEvent e) {
		// TODO 自动生成的方法存根	
	}
	
	public void run() {
		while (!GameOver((Snake)snakes.get(0))) {
			moveSnake();
			moveSnake2();
			
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			repaint();
		}
	}
	
	private boolean GameOver(snank.Snake snake) {
		// TODO 自动生成的方法存根
		return false;
	}

	public void moveSnake(){
		if(StartF==LEFT){
			Snake snake=(Snake) snakes.get(0);
			snake.Oldx=snake.x;
			snake.Oldy=snake.y;
			snake.x-=size;
		}
		if(StartF==RIGHT){
			Snake snake=(Snake) snakes.get(0);
			snake.Oldx=snake.x;
			snake.Oldy=snake.y;
			snake.x+=size;
		}
		if(StartF==UP){
			Snake snake=(Snake) snakes.get(0);
			snake.Oldx=snake.x;
			snake.Oldy=snake.y;
			snake.y-=size;
		}
		if(StartF==DOWN){
			Snake snake=(Snake) snakes.get(0);
			snake.Oldx=snake.x;
			snake.Oldy=snake.y;
			snake.y+=size;
		}
	}
	
	public void moveSnake2(){
		for (int i = 1; i < snakes.size(); i++) {
			Snake snake=(Snake) snakes.get(i);
			snake.Oldx=snake.x;
			snake.Oldy=snake.y;
			Snake snake2=(Snake) snakes.get(i-1);
			snake.x=snake2.Oldx;
			snake.y=snake2.Oldy;
		}
	}
}

Snake.java

package snank;

import java.awt.Color;
import java.awt.Graphics;

public class Snake {
	int x,y;
	int Oldx,Oldy;
	
	public Snake(int x,int y) {
		this.x=x;
		this.y=y;
	}
	
	public void drawSnake(Graphics g) {
		g.setColor(Color.red);
		g.fillRect(x, y, 25, 25);
	}
}

Snake.java已完成。

游戏的结束

(1) 写一个游戏结束的方法,方法的返回值是boolean,参数是蛇对象,根据if条件判断什么时候该结束游戏,游戏结束返回true,否则返回flase

(2) 在paint方法中根据游戏结束的方法的返回值来确定画游戏结束字体

(3) 将run方法中的while循环条件修改成方法的返回值

SnakeJPanel.java

package snank;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;

import javax.swing.JPanel;

public class SnakeJPanel extends JPanel implements KeyListener,Runnable{
	int size = 25;
	int across = 38;
	int vertical = 26;
	
	ArrayList snakes = new ArrayList();
	
	int UP=0;
	int DOWN=1;
	int LEFT=2;
	int RIGHT=3;
	
	int StartF=-1;
	
	Thread t = new Thread(this);
	
	public void paint(Graphics g) {
		super.paint(g);
		for (int i = 0; i <=vertical; i++) {
			g.drawLine(6, 6+size*i, 6+across*size, 6+size*i);
		}
		for (int i = 0; i <=across; i++) {
			g.drawLine(6+size*i, 6, 6+size*i, 6+vertical*size);
		}
		
		for (int i = 0; i < snakes.size(); i++) {
			Snake snake=(Snake) snakes.get(i);
			snake.drawSnake(g);
		}
		if(GameOver((Snake)snakes.get(0))){
			//写艺术字
			for (int i = 0; i < 10; i++) {
				g.setFont(new Font("微软雅黑", Font.BOLD, 70));
				g.setColor(new Color((int)(Math.random()*255), (int)(Math.random()*255), (int)(Math.random()*255)));
				g.drawString("游戏结束", 300-i, 300-i);
			}
		}
	}
	
	public SnakeJPanel() {
		Snake snake=new Snake((int)(Math.random()*across)*size+6, (int)(Math.random()*vertical)*size+6);
		snakes.add(snake);
		setFocusable(true);
		addKeyListener(this);
		t.start();
	}
	
	public void keyPressed(KeyEvent e) {
		if(e.getKeyCode()==KeyEvent.VK_LEFT){
			if(StartF==-1 || StartF==UP ||StartF==DOWN){
				StartF=LEFT;
			}
		}
		if(e.getKeyCode()==KeyEvent.VK_RIGHT){
			if(StartF==-1 || StartF==UP ||StartF==DOWN){
				StartF=RIGHT;
			}
		}
		if(e.getKeyCode()==KeyEvent.VK_UP){
			if(StartF==-1 || StartF==LEFT ||StartF==RIGHT){
				StartF=UP;
			}
		}
		if(e.getKeyCode()==KeyEvent.VK_DOWN){
			if(StartF==-1 || StartF==LEFT ||StartF==RIGHT){
				StartF=DOWN;
			}
		}
	}
	@Override
	public void keyTyped(KeyEvent e) {
		// TODO 自动生成的方法存根	
	}
	@Override
	public void keyReleased(KeyEvent e) {
		// TODO 自动生成的方法存根	
	}
	
	public void run() {
		while (!GameOver((Snake)snakes.get(0))) {
			moveSnake();
			moveSnake2();
			
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			repaint();
		}
	}
	
	public boolean GameOver(Snake snake){
		if(snake.x<0 || snake.x>956 || snake.y<0 || snake.y>656){
			return true;
		}
		return false;
	}

	public void moveSnake(){
		if(StartF==LEFT){
			Snake snake=(Snake) snakes.get(0);
			snake.Oldx=snake.x;
			snake.Oldy=snake.y;
			snake.x-=size;
		}
		if(StartF==RIGHT){
			Snake snake=(Snake) snakes.get(0);
			snake.Oldx=snake.x;
			snake.Oldy=snake.y;
			snake.x+=size;
		}
		if(StartF==UP){
			Snake snake=(Snake) snakes.get(0);
			snake.Oldx=snake.x;
			snake.Oldy=snake.y;
			snake.y-=size;
		}
		if(StartF==DOWN){
			Snake snake=(Snake) snakes.get(0);
			snake.Oldx=snake.x;
			snake.Oldy=snake.y;
			snake.y+=size;
		}
	}
	
	public void moveSnake2(){
		for (int i = 1; i < snakes.size(); i++) {
			Snake snake=(Snake) snakes.get(i);
			snake.Oldx=snake.x;
			snake.Oldy=snake.y;
			Snake snake2=(Snake) snakes.get(i-1);
			snake.x=snake2.Oldx;
			snake.y=snake2.Oldy;
		}
	}
}

画食物

(1) 随机生成食物坐标

(2) 循环判断食物和集合中的每一个蛇的坐标是否一致,不一致就要重新生成.并重新比较

package snank;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;

import javax.swing.JPanel;

public class SnakeJPanel extends JPanel implements KeyListener,Runnable{
	int size = 25;
	int across = 38;
	int vertical = 26;
	
	ArrayList snakes = new ArrayList();
	
	int UP=0;
	int DOWN=1;
	int LEFT=2;
	int RIGHT=3;
	
	int StartF=-1;
	
	Thread t = new Thread(this);
	
	boolean hadFood=true;

	int food_x;
	int food_y;
	
	public void paint(Graphics g) {
		super.paint(g);
		for (int i = 0; i <=vertical; i++) {
			g.drawLine(6, 6+size*i, 6+across*size, 6+size*i);
		}
		for (int i = 0; i <=across; i++) {
			g.drawLine(6+size*i, 6, 6+size*i, 6+vertical*size);
		}
		
		for (int i = 0; i < snakes.size(); i++) {
			Snake snake=(Snake) snakes.get(i);
			snake.drawSnake(g);
		}
		if(GameOver((Snake)snakes.get(0))){
			//写艺术字
			for (int i = 0; i < 10; i++) {
				g.setFont(new Font("微软雅黑", Font.BOLD, 70));
				g.setColor(new Color((int)(Math.random()*255), (int)(Math.random()*255), (int)(Math.random()*255)));
				g.drawString("游戏结束", 300-i, 300-i);
			}
		}
		if(hadFood){
			g.fillRect(food_x, food_y, size, size);
		}
	}
	
	public SnakeJPanel() {
		Snake snake=new Snake((int)(Math.random()*across)*size+6, (int)(Math.random()*vertical)*size+6);
		snakes.add(snake);
		setFocusable(true);
		addKeyListener(this);
		t.start();
		creat_food();
	}
	
	public void keyPressed(KeyEvent e) {
		if(e.getKeyCode()==KeyEvent.VK_LEFT){
			if(StartF==-1 || StartF==UP ||StartF==DOWN){
				StartF=LEFT;
			}
		}
		if(e.getKeyCode()==KeyEvent.VK_RIGHT){
			if(StartF==-1 || StartF==UP ||StartF==DOWN){
				StartF=RIGHT;
			}
		}
		if(e.getKeyCode()==KeyEvent.VK_UP){
			if(StartF==-1 || StartF==LEFT ||StartF==RIGHT){
				StartF=UP;
			}
		}
		if(e.getKeyCode()==KeyEvent.VK_DOWN){
			if(StartF==-1 || StartF==LEFT ||StartF==RIGHT){
				StartF=DOWN;
			}
		}
	}
	@Override
	public void keyTyped(KeyEvent e) {
		// TODO 自动生成的方法存根	
	}
	@Override
	public void keyReleased(KeyEvent e) {
		// TODO 自动生成的方法存根	
	}
	
	public void run() {
		while (!GameOver((Snake)snakes.get(0))) {
			moveSnake();
			moveSnake2();
			
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			repaint();
		}
	}
	
	public boolean GameOver(Snake snake){
		if(snake.x<0 || snake.x>956 || snake.y<0 || snake.y>656){
			return true;
		}
		return false;
	}

	public void moveSnake(){
		if(StartF==LEFT){
			Snake snake=(Snake) snakes.get(0);
			snake.Oldx=snake.x;
			snake.Oldy=snake.y;
			snake.x-=size;
		}
		if(StartF==RIGHT){
			Snake snake=(Snake) snakes.get(0);
			snake.Oldx=snake.x;
			snake.Oldy=snake.y;
			snake.x+=size;
		}
		if(StartF==UP){
			Snake snake=(Snake) snakes.get(0);
			snake.Oldx=snake.x;
			snake.Oldy=snake.y;
			snake.y-=size;
		}
		if(StartF==DOWN){
			Snake snake=(Snake) snakes.get(0);
			snake.Oldx=snake.x;
			snake.Oldy=snake.y;
			snake.y+=size;
		}
	}
	
	public void moveSnake2(){
		for (int i = 1; i < snakes.size(); i++) {
			Snake snake=(Snake) snakes.get(i);
			snake.Oldx=snake.x;
			snake.Oldy=snake.y;
			Snake snake2=(Snake) snakes.get(i-1);
			snake.x=snake2.Oldx;
			snake.y=snake2.Oldy;
		}
	}
	
	public void creat_food(){
		food_x=(int) (Math.random()*across)*size+6;
		food_y=(int) (Math.random()*vertical)*size+6;
		for (int i = 0; i < snakes.size(); i++) {
			Snake snake=(Snake) snakes.get(i);
			if(food_x==snake.x && food_y==snake.y){
				food_x=(int) (Math.random()*across)*size+6;
				food_y=(int) (Math.random()*vertical)*size+6;
				i=0;
			}
		}
		hadFood=true;
	}
}

吃食物

(1) 蛇头和食物坐标一致表示吃食物

(2) 吃食物蛇集合就应该增加一个蛇对象

(3) New的蛇对象的坐标是前一个蛇对象保留下的坐标

(4) 返回去在蛇移动的时候就应该修改成先保留在移动

(5) 迟到食物,食物开关标识flase,与此同时在run方法中if判断食物消失,调用创建食物的方法,创建食物,食物标识就应该改为true

package snank;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;

import javax.swing.JPanel;

public class SnakeJPanel extends JPanel implements KeyListener,Runnable{
	int size = 25;
	int across = 38;
	int vertical = 26;
	
	ArrayList snakes = new ArrayList();
	
	int UP=0;
	int DOWN=1;
	int LEFT=2;
	int RIGHT=3;
	
	int StartF=-1;
	
	Thread t = new Thread(this);
	
	boolean hadFood=true;

	int food_x;
	int food_y;
	
	public void paint(Graphics g) {
		super.paint(g);
		for (int i = 0; i <=vertical; i++) {
			g.drawLine(6, 6+size*i, 6+across*size, 6+size*i);
		}
		for (int i = 0; i <=across; i++) {
			g.drawLine(6+size*i, 6, 6+size*i, 6+vertical*size);
		}
		
		for (int i = 0; i < snakes.size(); i++) {
			Snake snake=(Snake) snakes.get(i);
			snake.drawSnake(g);
		}
		if(GameOver((Snake)snakes.get(0))){
			//写艺术字
			for (int i = 0; i < 10; i++) {
				g.setFont(new Font("微软雅黑", Font.BOLD, 70));
				g.setColor(new Color((int)(Math.random()*255), (int)(Math.random()*255), (int)(Math.random()*255)));
				g.drawString("游戏结束", 300-i, 300-i);
			}
		}
		if(hadFood){
			g.fillRect(food_x, food_y, size, size);
		}
	}
	
	public SnakeJPanel() {
		Snake snake=new Snake((int)(Math.random()*across)*size+6, (int)(Math.random()*vertical)*size+6);
		snakes.add(snake);
		setFocusable(true);
		addKeyListener(this);
		t.start();
		creat_food();
	}
	
	public void keyPressed(KeyEvent e) {
		if(e.getKeyCode()==KeyEvent.VK_LEFT){
			if(StartF==-1 || StartF==UP ||StartF==DOWN){
				StartF=LEFT;
			}
		}
		if(e.getKeyCode()==KeyEvent.VK_RIGHT){
			if(StartF==-1 || StartF==UP ||StartF==DOWN){
				StartF=RIGHT;
			}
		}
		if(e.getKeyCode()==KeyEvent.VK_UP){
			if(StartF==-1 || StartF==LEFT ||StartF==RIGHT){
				StartF=UP;
			}
		}
		if(e.getKeyCode()==KeyEvent.VK_DOWN){
			if(StartF==-1 || StartF==LEFT ||StartF==RIGHT){
				StartF=DOWN;
			}
		}
	}
	@Override
	public void keyTyped(KeyEvent e) {
		// TODO 自动生成的方法存根	
	}
	@Override
	public void keyReleased(KeyEvent e) {
		// TODO 自动生成的方法存根	
	}
	
	public void run() {
		while (!GameOver((Snake)snakes.get(0))) {
			moveSnake();
			moveSnake2();
			eatFood();
			if(!hadFood){
				creat_food();
			}
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			repaint();
		}
	}
	
	public boolean GameOver(Snake snake){
		if(snake.x<0 || snake.x>956 || snake.y<0 || snake.y>656){
			return true;
		}
		return false;
	}

	public void moveSnake(){
		if(StartF==LEFT){
			Snake snake=(Snake) snakes.get(0);
			snake.Oldx=snake.x;
			snake.Oldy=snake.y;
			snake.x-=size;
		}
		if(StartF==RIGHT){
			Snake snake=(Snake) snakes.get(0);
			snake.Oldx=snake.x;
			snake.Oldy=snake.y;
			snake.x+=size;
		}
		if(StartF==UP){
			Snake snake=(Snake) snakes.get(0);
			snake.Oldx=snake.x;
			snake.Oldy=snake.y;
			snake.y-=size;
		}
		if(StartF==DOWN){
			Snake snake=(Snake) snakes.get(0);
			snake.Oldx=snake.x;
			snake.Oldy=snake.y;
			snake.y+=size;
		}
	}
	
	public void moveSnake2(){
		for (int i = 1; i < snakes.size(); i++) {
			Snake snake=(Snake) snakes.get(i);
			snake.Oldx=snake.x;
			snake.Oldy=snake.y;
			Snake snake2=(Snake) snakes.get(i-1);
			snake.x=snake2.Oldx;
			snake.y=snake2.Oldy;
		}
	}
	
	public void creat_food(){
		food_x=(int) (Math.random()*across)*size+6;
		food_y=(int) (Math.random()*vertical)*size+6;
		for (int i = 0; i < snakes.size(); i++) {
			Snake snake=(Snake) snakes.get(i);
			if(food_x==snake.x && food_y==snake.y){
				food_x=(int) (Math.random()*across)*size+6;
				food_y=(int) (Math.random()*vertical)*size+6;
				i=0;
			}
		}
		hadFood=true;
	}
	
	public void eatFood(){
		Snake snake=(Snake) snakes.get(0);
		if(snake.x==food_x && snake.y==food_y){
			Snake snake2=(Snake) snakes.get(snakes.size()-1);
			Snake snake3=new Snake(snake2.Oldx, snake2.Oldy);
			snakes.add(snake3);
			hadFood=false;
			
		}
	}
}

修订版

SnakeJFrame.java

package snank;

import javax.swing.JFrame;

public class SnakeJFrame extends JFrame{
	public SnakeJFrame() {
		this.setTitle("贪吃蛇");
		this.setSize(978, 700);
		this.setLocationRelativeTo(null);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		this.setResizable(false);
		
		SnakeJPanel panel=new SnakeJPanel();
		this.add(panel);

		this.setVisible(true);
	}

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

SnakeJPanel.java

package snank;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;

import javax.swing.JPanel;

public class SnakeJPanel extends JPanel implements KeyListener,Runnable{
	int size = 25;
	int across = 38;
	int vertical = 26;
	
	ArrayList snakes = new ArrayList();
	
	int UP=0;
	int DOWN=1;
	int LEFT=2;
	int RIGHT=3;
	int Shop=-1;
	
	int StartF=-1;
	
	Thread t = new Thread(this);
	
	boolean hadFood=true;

	int food_x;
	int food_y;
	
	int temp = 0;
	
	public void paint(Graphics g) {
		super.paint(g);
		for (int i = 0; i <=vertical; i++) {
			g.drawLine(6, 6+size*i, 6+across*size, 6+size*i);
		}
		for (int i = 0; i <=across; i++) {
			g.drawLine(6+size*i, 6, 6+size*i, 6+vertical*size);
		}
		
		for (int i = 0; i < snakes.size(); i++) {
			Snake snake=(Snake) snakes.get(i);
			snake.drawSnake(g);
			g.setColor(Color.GREEN); 
		}
		if(GameOver((Snake)snakes.get(0))){
			//写艺术字
			for (int i = 0; i < 10; i++) {
				g.setFont(new Font("微软雅黑", Font.BOLD, 70));
				g.setColor(new Color((int)(Math.random()*255), (int)(Math.random()*255), (int)(Math.random()*255)));
				g.drawString("游戏结束", 300-i, 300-i);
			}
		}
		if(hadFood){
			g.fillRect(food_x, food_y, size, size);
		}
		if(StartF == -1) {
			if(temp==0) {
				for (int j = 0; j < 10; j++) {
					g.setFont(new Font("微软雅黑", Font.BOLD, 70));
					g.setColor(new Color((int)(Math.random()*255), (int)(Math.random()*255), (int)(Math.random()*255)));
					g.drawString("按方向键游戏开始", 180-j, 320-j);
				}
			}else {
				for (int j = 0; j < 10; j++) {
					g.setFont(new Font("微软雅黑", Font.BOLD, 70));
					g.setColor(new Color((int)(Math.random()*255), (int)(Math.random()*255), (int)(Math.random()*255)));
					g.drawString("游戏暂停", 300-j, 300-j);
				}
			}
		}
	}
	
	public SnakeJPanel() {
		Snake snake=new Snake((int)(Math.random()*across)*size+6, (int)(Math.random()*vertical)*size+6);
		snakes.add(snake);
		setFocusable(true);
		addKeyListener(this);
		t.start();
		creat_food();
	}
	
	public void keyPressed(KeyEvent e) {
		if(e.getKeyCode()==KeyEvent.VK_LEFT){
			if(StartF==-1 || StartF==UP ||StartF==DOWN){
				StartF=LEFT;
			}
		}
		if(e.getKeyCode()==KeyEvent.VK_RIGHT){
			if(StartF==-1 || StartF==UP ||StartF==DOWN){
				StartF=RIGHT;
			}
		}
		if(e.getKeyCode()==KeyEvent.VK_UP){
			if(StartF==-1 || StartF==LEFT ||StartF==RIGHT){
				StartF=UP;
			}
		}
		if(e.getKeyCode()==KeyEvent.VK_DOWN){
			if(StartF==-1 || StartF==LEFT ||StartF==RIGHT){
				StartF=DOWN;
			}
		}
		if(e.getKeyCode()==KeyEvent.VK_SPACE) {
			if(StartF==LEFT ||StartF==RIGHT || StartF==UP ||StartF==DOWN) {
				StartF=Shop;
				temp++;
			}
		}
	}
	@Override
	public void keyTyped(KeyEvent e) {
		// TODO 自动生成的方法存根	
	}
	@Override
	public void keyReleased(KeyEvent e) {
		// TODO 自动生成的方法存根	
	}
	
	public void run() {
		while (!GameOver((Snake)snakes.get(0))) {
			moveSnake();
			moveSnake2();
			eatFood();
			if(!hadFood){
				creat_food();
			}
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			repaint();
		}
	}
	
	public boolean GameOver(Snake snake){
		if(snake.x<0 || snake.x>950 || snake.y<0 || snake.y>650){
			return true;
		}
		return false;
	}

	public void moveSnake(){
		if(StartF==LEFT){
			Snake snake=(Snake) snakes.get(0);
			snake.Oldx=snake.x;
			snake.Oldy=snake.y;
			snake.x-=size;
		}
		if(StartF==RIGHT){
			Snake snake=(Snake) snakes.get(0);
			snake.Oldx=snake.x;
			snake.Oldy=snake.y;
			snake.x+=size;
		}
		if(StartF==UP){
			Snake snake=(Snake) snakes.get(0);
			snake.Oldx=snake.x;
			snake.Oldy=snake.y;
			snake.y-=size;
		}
		if(StartF==DOWN){
			Snake snake=(Snake) snakes.get(0);
			snake.Oldx=snake.x;
			snake.Oldy=snake.y;
			snake.y+=size;
		}
	}
	
	public void moveSnake2(){
		for (int i = 1; i < snakes.size(); i++) {
			Snake snake=(Snake) snakes.get(i);
			snake.Oldx=snake.x;
			snake.Oldy=snake.y;
			Snake snake2=(Snake) snakes.get(i-1);
			snake.x=snake2.Oldx;
			snake.y=snake2.Oldy;
		}
	}
	
	public void creat_food(){
		food_x=(int) (Math.random()*across)*size+6;
		food_y=(int) (Math.random()*vertical)*size+6;
		for (int i = 0; i < snakes.size(); i++) {
			Snake snake=(Snake) snakes.get(i);
			if(food_x==snake.x && food_y==snake.y){
				food_x=(int) (Math.random()*across)*size+6;
				food_y=(int) (Math.random()*vertical)*size+6;
				i=0;
			}
		}
		hadFood=true;
	}

	public void eatFood(){
		Snake snake=(Snake) snakes.get(0);
		if(snake.x==food_x && snake.y==food_y){
			Snake snake2=(Snake) snakes.get(snakes.size()-1);
			Snake snake3=new Snake(snake2.Oldx, snake2.Oldy);
			snakes.add(snake3);
			hadFood=false;
			
		}
	}
}

Snake.java

package snank;

import java.awt.Color;
import java.awt.Graphics;

public class Snake {
	int x,y;
	int Oldx,Oldy;
	
	public Snake(int x,int y) {
		this.x=x;
		this.y=y;
	}
	
	public void drawSnake(Graphics g) {
		g.setColor(Color.red);
		g.fillRect(x, y, 25, 25);
	}
	
	public void drawFood(Graphics g) {
		g.setColor(new Color((int)(Math.random()*255), (int)(Math.random()*255), (int)(Math.random()*255)));
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值