JAVA小游戏----贪吃蛇

一、绘制网格界面

public class SnakeFrame extends JFrame {
	
		// 方格的宽度和长度
		public static final int BLOCK_WIDTH = 15;
		public static final int BLOCK_HEIGHT = 15;
		// 界面的方格的行数和列数
		public static final int ROW = 20;
		public static final int COL = 20;
		
		static SnakeFrame sf = new SnakeFrame();
		JPanel jp = new JPanel();

	public static void main(String[] args) {
		sf.launch();
	}
	
	public void launch(){
		
		setTitle("贪吃蛇");
		setLocation(30, 40);
		//边界判断很迷,暂时不知道怎么解决
		setSize(BLOCK_WIDTH*(COL+1), BLOCK_HEIGHT*(ROW+2));
		setVisible(true);
		
		add(new SnakePanel());
		this.setResizable(false);
		
	}
	
	//用JPanel面板来绘制,可以避免闪烁问题
	public class SnakePanel extends JPanel{
		@Override
		public void paint(Graphics g){
			//画横线
			for(int i=0;i<=ROW;i++){
				g.drawLine(0,i*BLOCK_HEIGHT,BLOCK_WIDTH*COL,i*BLOCK_HEIGHT);
			}
			//画竖线
			for(int i=0;i<=COL;i++){
				g.drawLine(i*BLOCK_WIDTH,0,i*BLOCK_WIDTH,BLOCK_HEIGHT*ROW);
			}
		}
	}

}
界面如下:

二、画蛇,用链表实现

import java.awt.Graphics;

public class Snake {
	/*
	 * 用链表实现蛇,蛇头的位置和方向就能确定蛇的位置
	 */
	// 一节蛇的大小,和网格一个格子一样大
	private static final int BLOCK_WIDTH = SnakeFrame.BLOCK_WIDTH;
	private static final int BLOCK_HEIGHT = SnakeFrame.BLOCK_HEIGHT;

	private Node head = null;// 蛇头
	private Node tail = null;// 蛇尾

	public enum Direction {// 用枚举设置蛇的方向
		R, L, D, U
	}
	
	public Snake(){//蛇的构造函数
		Node node = new Node(3,4,Direction.D);
		head = node;
		tail = node;
	}
	
	public void draw(Graphics g){//绘制蛇
		if(head == null) return;
		for(Node node = head;node!=null;node=node.next){
			node.draw(g);
		}
	}

	public class Node {
		// 结点位置(左上角)
		private int row;
		private int col;
		// 蛇头方向
		private Direction dir;

		public Node pre;// 上一个节点
		public Node next;// 下一个节点

		public Node(int row, int col, Direction dir) {// 构造结点,参数为位置和方向
			this.row = row;
			this.col = col;
			this.dir = dir;
			this.pre = null;
			this.next = null;
		}
		
		//绘制结点
		public void draw(Graphics g) {
			g.fillRect(row*BLOCK_WIDTH, col*BLOCK_HEIGHT, BLOCK_WIDTH, BLOCK_HEIGHT);
		}
	}

}

最后在SnakeFrame中new一个snake,在JPanel的paint()中添加snake.draw(),就在界面中画了一个静止的蛇头


三、让蛇动起来

1.在Snake中写一个move()函数

public void move() {// 通过删除结点增加结点来移动
		addNodeInHead();// 从头部插入结点
		deleteNodeInTail();// 从尾部删除结点
	}
	
	public void addNodeInHead() {
		Node node = null;
		// 根据头结点方向来确定增加结点的位置
		switch (head.dir) {
		case L:
			node = new Node(head.row - 1, head.col, head.dir);// 横减
		case R:
			node = new Node(head.row + 1, head.col, head.dir);// 横加
		case U:
			node = new Node(head.row, head.col - 1, head.dir);// 纵减
		case D:
			node = new Node(head.row, head.col + 1, head.dir);// 纵加
		}

		head.pre = node;
		node.next = head;
		head = node;
	}
	
	public void deleteNodeInTail() {
		Node node = tail;
		tail = node.pre;
		node = null;
		tail.next = null;
	}

在Snake的draw()函数中添加move(),每次绘制后移动

2.在SnakeFrame中写一个PaintThread类

public class PaintThread implements Runnable{
		@Override
		public void run() {
			while(true){
				repaint();//自动调用paint()
				try {
					Thread.sleep(500);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}

然后在lanuch()中添加new Thread(new PaintThread()).start();,在界面启动的时候即启动线程

3.用键盘控制蛇的移动

a.在SnakeFrame中写一个键盘监听类,继承键盘适配器

public class KeyMonitor extends KeyAdapter {

		@Override
		public void keyPressed(KeyEvent e) {
			snake.keyPressed(e);
		}
	}

b.在Snake类中写好keyPressed()函数

public void keyPressed(KeyEvent e) {
		int key = e.getKeyCode();// 获取key的值
		switch (key) {
		case KeyEvent.VK_LEFT:
			if (head.dir != Direction.L) {
				head.dir = Direction.L;
			}
			break;
		case KeyEvent.VK_RIGHT:
			if (head.dir != Direction.R) {
				head.dir = Direction.R;
			}
			break;
		case KeyEvent.VK_UP:
			if (head.dir != Direction.U) {
				head.dir = Direction.U;
			}
			break;
		case KeyEvent.VK_DOWN:
			if (head.dir != Direction.D) {
				head.dir = Direction.D;
			}
			break;
		}
	}

c.launch()函数中添加键盘监听事件

sp.setFocusable(true);//获取屏幕焦点,在键盘监听无效时添加
sp.addKeyListener(new KeyMonitor());//添加键盘监听事件
this.add(sp);

这样就实现了用键盘控制蛇的移动

四、建立食物类,随机生成食物并显示

import java.awt.Graphics;
import java.util.Random;

public class Food {
	//所在位置(左上角)
	private int row;
	private int col;
	//大小(不变)
	private static final int BLOCK_WIDTH = SnakeFrame.BLOCK_WIDTH;
	private static final int BLOCK_HEIGHT = SnakeFrame.BLOCK_HEIGHT;
	
	Random r = new Random();
	
	public Food(){
		this.row = r.nextInt(SnakeFrame.ROW);
		this.col = r.nextInt(SnakeFrame.COL);
	}
	
	public void draw(Graphics g){
		g.fillRect(row*BLOCK_WIDTH, col*BLOCK_HEIGHT, BLOCK_WIDTH, BLOCK_HEIGHT);
	}

}

在SnakeFrame中new一个food,在paint()中添加food的draw(),即可在界面生成食物

五、蛇吃食物,蛇变长,食物重新出现

这里使用Rectangle类来获取食物的位置

Food类中写一个获取位置的函数

public Rectangle getRect(){//检测食物的位置“储存于Rantangle”中
    	//构造一个新的 Rectangle ,其左上角被指定为 (x,y) ,其宽度和高度由同名参数指定
        return new Rectangle(col*BLOCK_WIDTH, row*BLOCK_HEIGHT, BLOCK_WIDTH, BLOCK_HEIGHT);
    }

在Snake类中定义一个eatFood(),Snake中也要有一个getRect()函数

public void eatFood(Food food){
		if (this.getRect().intersects(food.getRect())) {
			addNodeInHead();//蛇长长
			food.reAppear();//蛇重新出现
		}
	}
	
public Rectangle getRect(){//检测蛇头的位置“储存于Rantangle”中
        return new Rectangle(head.row*BLOCK_WIDTH, head.col*BLOCK_HEIGHT, BLOCK_WIDTH, BLOCK_HEIGHT);
    }

在paint()调用eatFood(),即可实现蛇吃食物的功能

六、碰撞检测(Snake类中)

public boolean isDead() {
		// 蛇头边界检查
		if (head.row < 0 || head.col < 0 || head.row > SnakeFrame.ROW || head.col > SnakeFrame.COL) {
			return true;
		}

		// 是否与蛇身相撞
		for (Node node = head.next; node != null; node = node.next) {
			if (node.row == head.row && node.col == head.col) {
				return true;
			}
		}

		return false;
	}

在调用repaint()前先判断断蛇是否死亡

至此,贪吃蛇基本功能实现


后续可自行添加开始游戏界面、暂停功能、重新开始、计分、关卡等功能

源码下载:https://download.csdn.net/download/trancybao/10485564









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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值