使用java swing实现贪吃蛇

贪吃蛇是一个大家耳熟能详的小游戏,有很多语言的版本,游戏玩法很简单。

这里使用canvas画板实现。

首先定义一个Snake类,该类是一个列表,存放了蛇上的坐标点,以及蛇的节点的绘制、清除、蛇的移动方向等

class Snake extends Arraylist<Point>{

...........

}

接着创建画板GameCanvas类继承Canvas类,该类是程序主要构成,大部分操作放在该类中,包括监听键盘按键,游戏的开始、结束、暂停等操作

class GameCanvas extends Canvas{

...........

}

对于程序的窗口也需要一个类SnakeGame类,该类继承了JFrame,显示程序的主界面,同时显示开始按钮和分数提示等等信息,在窗体中把GameCanvas类添加到窗体中

public class SnakeFrame extends JFrame{

.......

public SnakeFrame(){

JPanel pane=new JPanel(null);

canvas = new GameCanvas(this);

pane.add(canvas);

}

}

运行效果图如下:


程序完整代码如下:

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
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.Iterator;
import java.util.LinkedList;


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

public class SnakeFrame extends JFrame{
	/**
	 * 
	 */
	private static final long serialVersionUID = 2487843782670565160L;
	static Color BGCOLOR =Color.BLACK;//定义背景色
	static Color SNAKECOLOR =Color.BLUE;//定义蛇的颜色
	static Color BEANCOLOR =Color.RED;//食物的颜色
	static Color EATEDBEANCOLOR =Color.CYAN;//吃的时候食物的颜色
	private String info="请使用键盘上的<上下左右>按钮控制方向-空格暂停-ESC退出";
	private JLabel helplab=new JLabel(info);
	private JLabel scorelab=new JLabel("得分:0");
	private JButton beginbnt=new JButton("开始游戏");
	private GameCanvas canvas;
	
	public void setLable(String str){
		scorelab.setText(str);
	}
	public SnakeFrame() {
		setTitle("-贪吃蛇-");//设置标题
		this.setSize(600,400);//设置窗体大小
		JPanel pane=new JPanel(null);//定义窗体面板
		beginbnt.setBounds(430, 150, 100, 50);//设置开始按钮
		pane.add(beginbnt);
		beginbnt.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				canvas.resetGame();
				beginbnt.setFocusable(false);//按钮失去焦点
				canvas.requestFocus();//画布获得焦点
			}
		});
		//设置帮助信息
		helplab.setBounds(10, 320, 400, 30);
		pane.add(helplab);
		//设置分数显示标签
		scorelab.setBounds(430, 250, 200, 30);
		pane.add(scorelab);
		//创建游戏面板
		canvas = new GameCanvas(this);
		canvas.setBounds(10, 10, 400, 300);
		//添加到窗体
		pane.add(canvas);
		setContentPane(pane);
		//窗体不可变大小
		this.setResizable(false);
		//居中
		this.setLocationRelativeTo(null);
		//关闭窗体程序结束
		setDefaultCloseOperation(EXIT_ON_CLOSE);
	}
	
	public static void main(String[] args) {
		SnakeFrame sFrame=new SnakeFrame();
		sFrame.setVisible(true);
	}
}

/**
 * 
 * @author cslg.yao
 *
 */
class GameCanvas extends Canvas{
	/**
	 * 
	 */
	private static final long serialVersionUID = 8444419077424283797L;
	private int horizontalCount,verticalCount;//明确横向和纵向大小
	private int x,y;
	private Snake snake;//蛇列表
	private LinkedList<Point> eatedBean = new LinkedList<>();
	private Iterator<Point> snakeSq;
	public Timer timer;//定时器,自动移动
	private int direction=2;//方向
	private int score;//得分
	private Point bean= new Point(), eatBean;
	private boolean mark;
	private Graphics2D g;
	private boolean hasStoped =true;
	private SnakeFrame game;
	
	public GameCanvas(SnakeFrame gamefrm) {
		this();
		game=gamefrm;
	}
	public GameCanvas() {
		//设置绘制的尺寸范围
		this.horizontalCount=25;
		this.verticalCount=20;
		this.x=400/25;
		this.y=300/20;
		this.addKeyListener(new KeyHandler());
		//开始
		timer = new Timer(180, new TimerHandler());
		snake = new Snake();
		hasStoped =false;
		setBackground(SnakeFrame.BGCOLOR);
	}
	
	private class KeyHandler extends KeyAdapter{
		
		public void keyPressed(KeyEvent e){
			if (e.getKeyCode()==10) {
				resetGame();
			}else if (e.getKeyCode() == 27) {
				timer.stop();
				if (JOptionPane.showConfirmDialog(null, "你确定退出吗?")==0) {
					System.exit(0);
				}
				timer.start();
			}
			else if (e.getKeyCode()==37 && snake.snakeDirection !=2) {
				direction=4;
			}
			else if (e.getKeyCode()==39 && snake.snakeDirection !=4) {
				direction=2;
			}
			else if (e.getKeyCode()==38 && snake.snakeDirection !=3) {
				direction=1;
			}
			else if (e.getKeyCode()==40 && snake.snakeDirection !=1) {
				direction=3;
			}else if (e.getKeyCode()==32) {
				if (!hasStoped) {
					if (!mark) {
						timer.stop();
						mark=true;
					}else {
						timer.start();
						mark=false;
					}
				}
			}
		}
	}
	
	private class TimerHandler implements ActionListener{
		@Override
		public synchronized void actionPerformed(ActionEvent e) {
			Point temp=(Point)snake.get(snake.size()-1);
			snakeSq=snake.iterator();
			while (snakeSq.hasNext()) {
				Point tempPoint = (Point)snakeSq.next();
				if (temp.equals(tempPoint)&&snakeSq.hasNext()!=false) {
					timer.stop();
					stopGame();
					JOptionPane.showMessageDialog(null,"游戏结束!");
				}
			}
			//判断游戏结束
			if ((temp.x ==0 &&direction==4)||(temp.x==horizontalCount-1 &&direction==2)||(temp.y==0&&direction==1)||(temp.y==verticalCount-1&&direction==3) ) {
				timer.stop();
				stopGame();
				JOptionPane.showMessageDialog(null,"游戏结束!");
			}
			if (direction!=snake.snakeReDirection) {
				moveSnake(direction);
			}
			snake.drawSnake(getGraphics(),x,y);
			
			drawBeanAndEBean(getGraphics());
		}
		
	}
	/**
	 * 游戏结束
	 */
	public void stopGame(){
		this.hasStoped = true;
		this.timer.stop();
		Graphics2D g=(Graphics2D)GameCanvas.this.getGraphics();
		g.setColor(SnakeFrame.BGCOLOR);
		super.paint(g);
	}
	/**
	 * 游戏开始
	 */
	public void resetGame(){
		System.gc();
		this.hasStoped=false;
		Graphics2D g=(Graphics2D)GameCanvas.this.getGraphics();
		g.setColor(SnakeFrame.BGCOLOR);
		super.paint(g);
		this.snake = new Snake();
		this.createBean(bean);
		this.eatedBean.clear();
		snake.drawSnake(getGraphics(),x,y);
		this.timer.start();
		this.direction=2;
		this.score=0;
	}
	/**
	 * 蛇的移动
	 * @param direction
	 */
	private void moveSnake(int direction){
		//判断是否吃到食物
		if (snake.checkBeanIn(this.bean)) {
			this.score+=100;
			game.setLable("得分:"+this.score+" ");
			//添加到吃过的食物列表
			this.eatedBean.add(new Point(this.bean));
			//创建一个新的食物
			this.createBean(this.bean);
		}
		//
		snake.changeDirection((Point)snake.get(snake.size()-1),direction);
		
		Point p=(Point)snake.get(0);
		if (eatedBean.size()!=0) {
			if (eatedBean.getFirst().equals(p)) {
				eatedBean.remove(0);
			}else {
				snake.clearEndSnakePiece(getGraphics(),p.x,p.y,x,y);
				snake.removeTail();
			}
		}else {
			snake.clearEndSnakePiece(getGraphics(),p.x,p.y,x,y);
			snake.removeTail();
		}
	}
	
	/**
	 * 绘制食物
	 * @param g
	 */
	private void drawBeanAndEBean(Graphics g){
		//设置食物的颜色
		g.setColor(SnakeFrame.BEANCOLOR);
		this.drawPiece(g,this.bean.x,this.bean.y);
		//设置正在吃的食物颜色
		g.setColor(SnakeFrame.EATEDBEANCOLOR);
		
		snakeSq =eatedBean.iterator();
		while (snakeSq.hasNext()) {
			Point tempPoint = (Point) snakeSq.next();
			this.drawPiece(g,tempPoint.x,tempPoint.y);
		}
	}
	
	/**
	 * 绘制填充的矩形块
	 * @param g
	 * @param x
	 * @param y
	 */
	private void drawPiece(Graphics g,int x,int y){
		g.fillRect(this.x*x+1, this.y*y+1, this.x-2, this.y-2);
	}
	/**
	 * 随机创建食物
	 * @param temp
	 */
	private void createBean(Point temp){
		while(true){
			temp.x =(int)(Math.random()*this.horizontalCount);
			temp.y =(int)(Math.random()*this.verticalCount);
			snakeSq =snake.iterator();
			while (snakeSq.hasNext()) {
				if (snakeSq.next().equals(new Point(temp.x,temp.y))) {
					break;
				}
			}
			break;
		}
	}
}


class Snake extends ArrayList<Point>{
	/**
	 * 
	 */
	private static final long serialVersionUID = -2545954212854332230L;
	public int snakeDirection=2;
	public int snakeReDirection=4;
	
	public Snake() {
		/**
		 * 添加默认节点
		 */
		this.add(new Point(3, 3));
		this.add(new Point(4, 3));
		this.add(new Point(5, 3));
	}
	
	/**
	 * 根据方向添加蛇的节点
	 * @param temp
	 * @param direction
	 */
	public void changeDirection(Point temp,int direction){
		this.snakeDirection =direction;
		switch (direction) {
		case 1://向上
			this.snakeReDirection =3;
			this.add(new Point(temp.x, temp.y-1));
			break;
		case 2://向右
			this.snakeReDirection =4;
			this.add(new Point(temp.x+1, temp.y));
			break;
		case 3://向下
			this.snakeReDirection =1;
			this.add(new Point(temp.x, temp.y+1));
			break;
		case 4://向左
			this.snakeReDirection =2;
			this.add(new Point(temp.x-1, temp.y));
			break;
		default:
			break;
		}
	}
	
	/**
	 * 清除
	 * @param bean
	 * @return
	 */
	public boolean checkBeanIn(Point bean) {
		Point temp =(Point)this.get(this.size()-1);
		if (temp.equals(bean)) {
			return true;
		}
		return false;
	}
	/**
	 * 删除
	 */
	public void removeTail(){
		this.remove(0);
	}
	
	/**
	 * 绘制蛇
	 * @param g
	 * @param x
	 * @param y
	 */
	public void drawSnake(Graphics g,int x,int y){
		g.setColor(SnakeFrame.SNAKECOLOR);
		Iterator<Point> snakeSq = this.iterator();
		while (snakeSq.hasNext()) {
			Point p = (Point) snakeSq.next();
			g.fillRect(x*p.x+1, y*p.y+1, x-2, y-2);
		}
	}
	/**
	 * 清除节点
	 * @param g
	 * @param x1
	 * @param y1
	 * @param x2
	 * @param y2
	 */
	public void clearEndSnakePiece(Graphics g,int x1,int y1,int x2,int y2){
		g.setColor(SnakeFrame.BGCOLOR);
		g.fillRect(x1*x2+1, y1*y2+1, x2-2, y2-2);
		
	}
	
}


  • 5
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是使用Java实现贪吃蛇的简单代码示例: ```java import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Point; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.util.ArrayList; import java.util.Random; import javax.swing.JFrame; import javax.swing.JPanel; public class SnakeGame extends JPanel implements Runnable, KeyListener { private static final long serialVersionUID = 1L; // 游戏区域宽度和高度 private static final int WIDTH = 500; private static final int HEIGHT = 500; // 蛇的大小和速度 private static final int SIZE = 10; private static final int SPEED = 40; // 游戏是否结束标志 private boolean gameOver = false; // 蛇的初始位置和方向 private ArrayList<Point> snake = new ArrayList<Point>(); private int direction = KeyEvent.VK_RIGHT; // 食物的位置 private Point food; // 随机数生成器 private Random random = new Random(); public SnakeGame() { setPreferredSize(new Dimension(WIDTH, HEIGHT)); setBackground(Color.BLACK); setFocusable(true); addKeyListener(this); // 初始化蛇的位置 snake.add(new Point(100, 100)); snake.add(new Point(90, 100)); snake.add(new Point(80, 100)); // 初始化食物的位置 food = new Point(random.nextInt(WIDTH / SIZE) * SIZE, random.nextInt(HEIGHT / SIZE) * SIZE); } public void run() { while (!gameOver) { try { Thread.sleep(SPEED); } catch (InterruptedException e) { e.printStackTrace(); } // 移动蛇的位置 Point head = snake.get(0); Point newHead = new Point(head); switch (direction) { case KeyEvent.VK_UP: newHead.y -= SIZE; break; case KeyEvent.VK_DOWN: newHead.y += SIZE; break; case KeyEvent.VK_LEFT: newHead.x -= SIZE; break; case KeyEvent.VK_RIGHT: newHead.x += SIZE; break; } snake.add(0, newHead); snake.remove(snake.size() - 1); // 判断是否吃到食物 if (newHead.equals(food)) { food.setLocation(random.nextInt(WIDTH / SIZE) * SIZE, random.nextInt(HEIGHT / SIZE) * SIZE); } else { snake.remove(snake.size() - 1); } // 判断游戏是否结束 if (newHead.x < 0 || newHead.x >= WIDTH || newHead.y < 0 || newHead.y >= HEIGHT || snake.contains(newHead)) { gameOver = true; } // 重新绘制游戏界面 repaint(); } } public void keyPressed(KeyEvent e) { switch (e.getKeyCode()) { case KeyEvent.VK_UP: case KeyEvent.VK_DOWN: case KeyEvent.VK_LEFT: case KeyEvent.VK_RIGHT: direction = e.getKeyCode(); break; } } public void keyReleased(KeyEvent e) { } public void keyTyped(KeyEvent e) { } public void paintComponent(Graphics g) { super.paintComponent(g); // 绘制食物 g.setColor(Color.RED); g.fillRect(food.x, food.y, SIZE, SIZE); // 绘制蛇 g.setColor(Color.GREEN); for (Point p : snake) { g.fillRect(p.x, p.y, SIZE, SIZE); } // 绘制游戏结束信息 if (gameOver) { g.setColor(Color.WHITE); g.drawString("Game Over!", WIDTH / 2 - 40, HEIGHT / 2); } } public static void main(String[] args) { JFrame frame = new JFrame("Snake Game"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setContentPane(new SnakeGame()); frame.pack(); frame.setVisible(true); Thread thread = new Thread((SnakeGame)frame.getContentPane()); thread.start(); } } ``` 运行该代码,即可开始玩贪吃蛇游戏。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值