Java用swing实现的贪吃蛇

规则:
使用方向键盘控制蛇头,如果与原来方向相同或相反, 则无法改变。
按空格可以再pause和continue之间切换。
玩一次就得运行一次。

文件结构:
在这里插入图片描述

运行截图:
在这里插入图片描述
速度可以调:
在这里插入图片描述
可以在githu边上下载
github传送门

完整代码:
SnakeGame.java

package snake_1_1;

import java.awt.EventQueue;
import javax.swing.JFrame;
/**
 * 
 * @version 1.1 2019-5-11
 * 
 */

public class SnakeGame
{
	public static void main(String[] args) 
	{
		EventQueue.invokeLater(()->
		{
			SnakeFrame frame = new SnakeFrame();
			frame.setTitle("贪吃蛇");
			frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
			frame.setVisible(true);
		});
	}
}

Node.java

package snake_1_1;

class Node
{
	public static final int W = 20;
	public static final int H = 20;
	int x;
	int y;
	
	public Node(int x, int y)
	{
		this.x = x;
		this.y = y;
	}
}

Snake.java

package snake_1_1;

import java.util.ArrayList;

class Snake
{
	boolean isRun;  //是否在运动
	ArrayList<Node> body;  //蛇体
	Node food;   //食物
	int derection; //方向
	int score;  // 分数
	int status;  // 状态
	int speed;  // 速度
	public static final int SLOW = 500;
	public static final int MID = 300;
	public static final int FAST = 100;
	public static final int RUNNING = 1;
	public static final int PAUSED = 2;
	public static final int GAMEOVER = 3;
	public static final int LEFT = 1;
	public static final int UP = 2;
	public static final int RIGHT = 3;
	public static final int DOWN = 4;
	
	public Snake()
	{
		speed = Snake.SLOW;
		score = 0;
		isRun = false;
		status = Snake.PAUSED;
		derection = Snake.RIGHT;
		body = new ArrayList<Node>();
		body.add(new Node(60,20));
		body.add(new Node(40,20));
		body.add(new Node(20,20));
		makeFood();
	}
	
	//判断食物是否被蛇吃掉
	//如果食物在蛇运行方向的正前方, 并且 与蛇头接触 ,则被吃掉
	private boolean isEaten()
	{
		Node head = body.get(0);
		if (derection == Snake.RIGHT && (head.x + Node.W) == food.x
				&& head.y == food.y)
			return true;
		else if(derection == Snake.LEFT && (head.x - Node.W) == food.x 
				&& head.y == food.y)
			return true;
		else if(derection == Snake.UP && (head.y - Node.H) == food.y 
				&& head.x == food.x)
			return true;
		else if(derection == Snake.DOWN && (head.y + Node.H) == food.y 
				&& head.x == food.x)
			return true;
		else
			return false;			
	}
	
	//是否碰撞
	public boolean isCollsion() 
	{
		Node head = body.get(0);
		
		//碰壁
		if(derection == Snake.RIGHT && head.x == 280)
			return true;
		else if(derection == Snake.UP && head.y == 0)
			return true;
		else if(derection == Snake.LEFT && head.x == 0)
			return true;
		else if(derection == Snake.DOWN && head.y == 380)
			return true;
		
		//蛇头碰到身体
		Node temp = null;
		int i;
		for(i =3; i < body.size(); i++)
		{
			temp = body.get(i);
			if (temp.x == head.x && temp.y == head.y)
				return true;
		}
		if(i < body.size())
			return true;
		return false;
	}
	
	//在随机的地方产生食物
	public void makeFood()
	{
		boolean isInBody = true;
		int ax = 0, ay = 0;
		int X = 0, Y = 0;
		while(isInBody)
		{
			isInBody = false;
			ax = (int)(Math.random() * 15);
			ay = (int)(Math.random() * 20);
			X = ax*Node.W;
			Y = ax*Node.H;
			for(Node temp :body)
			{
				if(X== temp.x && Y == temp.y)
					isInBody = true;
			}
		}
		food = new Node( X, Y); 
	}
	
	//改变运行方向
	public void changeDerection(int newDer)
	{
		if(derection % 2 !=  newDer % 2)      //如果与原来方向相同或相反, 则无法改变
		{
			derection = newDer;
		}
	}
	
	public void move()
	{
		if(isEaten())    // 如果食物被吃掉
		{
			body.add(0,food);  // 把食物当成蛇头成为新的蛇体
			score += 10;
			makeFood();
		}
		else if(isCollsion())
		{
			isRun = false;
			status = Snake.GAMEOVER;	//结束
		}
		else if(isRun)	//正常运行  (不吃食物,不碰壁, 不碰到蛇身)
		{
			Node head = body.get(0);
			int X = head.x;
			int Y = head.y;
			switch(derection)
			{
			case RIGHT:
				X += Node.W;
				break;
			case LEFT:
				X -= Node.W;
				break;
			case UP:
				Y -= Node.H;
				break;
			case DOWN:
				Y += Node.H;
				break;
			}
			body.add(0,new Node(X,Y));
			body.remove(body.size()-1);   //去掉蛇尾
		}
	}
}

StatusRunnable.java

package snake_1_1;

import javax.swing.JLabel;

//记录状态的线程
class StatusRunnable implements Runnable
{
	private JLabel statusLabel;
	private JLabel scoreLabel;
	private Snake snake;
	
	public StatusRunnable(Snake snake, JLabel statusLabel, JLabel scoreLabel)
	{
		this.statusLabel = statusLabel;
		this.scoreLabel = scoreLabel;
		this.snake = snake;
	}
	
	public void run()
	{
		String sta = "";
		String spe = "";
		
		while(true)
		{
			switch(snake.status)
			{
			case Snake.RUNNING:
				sta = "running";
				break;
			case Snake.PAUSED:
				sta = "Paused";
				break;
			case Snake.GAMEOVER:
				sta = "GameOver";
				break;
			}
			statusLabel.setText(sta);
			scoreLabel.setText("" + snake.score);
			try {
				Thread.sleep(100);
			}catch(Exception e) {}	 		
		}
	}
}

SnakeRunnable.java

package snake_1_1;

import javax.swing.JComponent;

//蛇运动以及记录分数的线程
class SnakeRunnable implements Runnable
{
	private Snake snake;
	private JComponent component;
	int i = 0;
	
	public SnakeRunnable(Snake snake, JComponent component)
	{
		this.snake = snake;
		this.component = component;
	}
	public void run()
	{
		while(true)
		{
			try {
				snake.move();
				component.repaint();
				Thread.sleep(snake.speed);
			}catch(Exception e) {}
		}
	}
}

SnakePanel.java

package snake_1_1;

import javax.swing.JPanel;
import java.awt.Graphics;
import java.awt.Color;

//画板,蛇活动的地方
public class SnakePanel extends JPanel
{
	Snake snake;
	public SnakePanel(Snake snake)
	{
		this.snake = snake;
	}
	
	public void paintComponent(Graphics g)
	{
		super.paintComponent(g);
		for(Node node : snake.body)
		{
			g.setColor(Color.BLACK);
			g.fillRect(node.x, node.y, Node.W,Node.H);
		}
		Node food = snake.food;
		g.setColor(Color.RED);
		g.fillRect(food.x,food.y,Node.W, Node.H);
	}
}

SnakeFrame.java

package snake_1_1;

import java.awt.Color;
import java.awt.Component;

import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.util.ArrayList;

import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;

public class SnakeFrame extends JFrame
{
	private JLabel statusLabel;
	private JLabel speedLabel;
	private JLabel scoreLabel;
	private JPanel snakePanel;
	private Snake snake;
	private JMenuBar bar;		//菜单栏
	private JMenu gameMenu;		
	private JMenu helpMenu;
	private JMenu speedMenu;
	private JMenuItem newItem;
	private JMenuItem pauseItem;
	private JMenuItem beginItem;
	private JMenuItem aboutItem;		//没用上
	private JMenuItem slowItem;
	private JMenuItem midItem;
	private JMenuItem fastItem;
	
	public SnakeFrame()
	{
		init();
		ActionListener actionListener = event ->
		{
			if(event.getSource() == pauseItem)
				snake.isRun = false;
			else if(event.getSource() == beginItem)
				snake.isRun = true;
			else if(event.getSource() == newItem)
				newGame();
			//菜单控制运行速度
			else if(event.getSource() == slowItem)
			{
				snake.speed = Snake.SLOW;
				speedLabel.setText("slow");
			}
			else if(event.getSource() == midItem)
			{
				snake.speed = Snake.MID;
				speedLabel.setText("mid");
			}
			else if(event.getSource() == fastItem)
			{
				snake.speed = Snake.FAST;
				speedLabel.setText("fast");
			}
		};
		
		pauseItem.addActionListener(actionListener);
		beginItem.addActionListener(actionListener);
		newItem.addActionListener(actionListener);
		slowItem.addActionListener(actionListener);
		midItem.addActionListener(actionListener);
		fastItem.addActionListener(actionListener);
		aboutItem.addActionListener(actionListener);
		
		addKeyListener(new KeyAdapter()
			{
				public void keyPressed(KeyEvent event)
				{
					switch(event.getKeyCode())
					{
					//方向键改变蛇运行的方向
					case KeyEvent.VK_DOWN:
						snake.changeDerection(Snake.DOWN);
						break;
					case KeyEvent.VK_UP:
						snake.changeDerection(Snake.UP);
						break;
					case KeyEvent.VK_LEFT:
						snake.changeDerection(Snake.LEFT);
						break;
					case KeyEvent.VK_RIGHT:
						snake.changeDerection(Snake.RIGHT);
						break;
					case KeyEvent.VK_SPACE:
						if(snake.isRun == true)
						{
							snake.isRun = false;
							snake.status = Snake.PAUSED;
							break;
						}
						else
						{
							snake.isRun = true;
							snake.status = Snake.RUNNING;
							break;
						}
					}
				}
			});
		
	}
	private void init()
	{
		snake = new Snake();
		setSize(380,460);
		setLayout(null);			//清空布局管理器
		this.setResizable(false);
		
		bar = new JMenuBar();
		
		gameMenu = new JMenu("Game");		
		gameMenu.add((newItem = new JMenuItem("New Game")));
		gameMenu.add((pauseItem = new JMenuItem("Pause")));
		gameMenu.add((beginItem = new JMenuItem("continue")));
		
		helpMenu = new JMenu("help");		
		helpMenu.add((aboutItem = new JMenuItem("about")));
		
		speedMenu = new JMenu("speed");
		speedMenu.add(( slowItem = new JMenuItem("slow")));
		speedMenu.add(( midItem  = new JMenuItem("mid")));
		speedMenu.add(( fastItem = new JMenuItem("fast")));
		
		bar.add(gameMenu);
		bar.add(helpMenu);
		bar.add(speedMenu);
		setJMenuBar(bar);
		
		statusLabel = new JLabel();
		speedLabel = new JLabel();
		scoreLabel = new JLabel();
		snakePanel = new JPanel();
		
		snakePanel.setBounds(0, 0, 300, 400);	   // 从左上角(0,0)开始 ,大小 300 * 400	
		snakePanel.setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY));
		add(snakePanel);
		statusLabel.setBounds(310,25,60,20);
		add(statusLabel);
		speedLabel.setBounds(310, 75, 60, 20);
		add(speedLabel);
		scoreLabel.setBounds(310, 125, 60, 20);
		add(scoreLabel);
		
		JLabel temp = new JLabel("状态");
		temp.setBounds(310, 5, 60, 20);
		add(temp);
		temp = new JLabel("速度");
		temp.setBounds(310,55,60,20);
		add(temp);
		temp = new JLabel("分数");
		temp.setBounds(310, 105, 60, 20);
		add(temp);			
	}
	private void newGame()
	{
		this.remove(snakePanel);
		this.remove(statusLabel);
		this.remove(scoreLabel);
		speedLabel.setText("slow");
		statusLabel = new JLabel();
		scoreLabel = new JLabel();
		snakePanel = new SnakePanel(snake);
		snakePanel.setBounds(0,0,300,400);
		snakePanel.setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY));  //加个边框
		
		Runnable r1 = new SnakeRunnable(snake,snakePanel);
		Runnable r2 = new StatusRunnable(snake,statusLabel,scoreLabel);
		Thread t1 = new Thread(r1);
		Thread t2 = new Thread(r2);
		t1.start();
		t2.start();
		add(snakePanel);
		statusLabel.setBounds(310,25,60,20);
		add(statusLabel);
		scoreLabel.setBounds(310,125,60,20);
		add(scoreLabel);
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值