贪吃蛇实现小方法

在二维空间中,用点亮的方法来标记蛇的位置,通过预估下一个移动位置是否被点亮来做碰撞检测。

整条蛇可以用链表来做,C++ 里面 Vector 也不错,主要移动工作在于不断的在头部添加新节点,同时删除尾部节点。当蛇吃到 food 的时候,尾部节点保留。


参考 pudn 上作者 hsy 的 Java 代码实现方法,引用如下:

/*   
 *12.24日,完成了蛇撞到自己的检测.修改方法是在蛇的初始化的时候,用双循环来置FALSE;  
 * 在重写代码的时候,我借鉴了别人的思路:将整个游戏的界面定义为一个布尔型的二维数组.  
 * 用一个LinkedList来储存蛇.当蛇移动的时候,在蛇的头部增加一个节点,然后删除最后一个节点.  
 * 因为只是做练习,所以没做游戏界面,比如菜单栏,计分栏什么的.另外还有一个问题,就是当两次点击回车时,蛇的移动速度会变快  
 */   
import javax.swing.*;   
import java.awt.*;   
import java.awt.event.*;   
import java.util.*;   
   
public class GreedySnake {   
    public static void main(String args[]) {   
        GameFrame frame = new GameFrame();   
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);   
        frame.setResizable(false);   
        frame.show();   
        JOptionPane.showMessageDialog(null, "上,下左,右控制蛇的方向\n回车开始,S暂停");   
    }   
}   
   
class GameFrame extends JFrame {   
    public GameFrame() {   
        setSize(294, 482);   
        setTitle("贪吃蛇DEMO");   
        this.setLocation(360, 100);   
        Container c = getContentPane();   
        GamePanel panel = new GamePanel();   
        c.add(panel, BorderLayout.CENTER);   
    }   
}   
   
class GamePanel extends JPanel implements KeyListener {   
    static int panelWidth = 294;   
   
    static int panelHeight = 450;   
   
    int rectX = 15;   
   
    int rectY = 15;   
   
    Snake snake;   
   
    Node n;   
   
    public GamePanel() {   
        snake = new Snake(this, panelWidth / rectX, panelHeight / rectY);   
        setBackground(Color.WHITE);   
        setSize(panelWidth, panelHeight);   
        setFocusable(true);   
        addKeyListener(this);   
    }   
   
    public void paintComponent(Graphics g) {   
        super.paintComponent(g);   
        Graphics2D g2 = (Graphics2D) g;   
        LinkedList list = snake.snakeList;   
        Iterator it = list.iterator();   
        g2.setColor(Color.black);   
        while (it.hasNext()) {   
            n = (Node) it.next();   
            drawNode(g2, n);   
        }   
        g2.setColor(Color.ORANGE);   
        Node f = snake.food;   
        drawNode(g2, f);   
        snake.drawMap(g2);// 绘制地图    
    }   
   
    public void keyPressed(KeyEvent e) {   
        int keycode = e.getKeyCode();   
        if (keycode == KeyEvent.VK_ENTER) {   
            begin();   
        } else if (keycode == KeyEvent.VK_UP) {   
            snake.changeDirection(Snake.up);   
        } else if (keycode == KeyEvent.VK_DOWN) {   
            snake.changeDirection(Snake.down);   
        } else if (keycode == KeyEvent.VK_LEFT) {   
            snake.changeDirection(Snake.left);   
        } else if (keycode == KeyEvent.VK_RIGHT) {   
            snake.changeDirection(Snake.right);   
        } else if (keycode == KeyEvent.VK_S) {   
            Snake.run = false;   
        }   
    }   
   
    public void keyReleased(KeyEvent e) {   
    }   
   
    public void keyTyped(KeyEvent e) {   
    }   
   
    public void drawNode(Graphics2D g, Node n) {   
        g.fillRect(n.x * rectX, n.y * rectY, rectX - 2, rectY - 2);   
    }   
   
    public void begin() {   
        Snake.run = true;   
        SnakeThread thread = new SnakeThread(snake);   
        thread.start();   
    }   
}   
   
class Node {   
    int x;   
   
    int y;   
   
    public Node(int x, int y) {   
        this.x = x;   
        this.y = y;   
    }   
}   
   
class SnakeThread extends Thread {   
    Snake snake;   
   
    public SnakeThread(Snake s) {   
        snake = s;   
    }   
   
    public void run() {   
        Snake.run = true;   
   
        while (Snake.run) {   
            try {   
                snake.move();   
                sleep(200);   
            } catch (InterruptedException e) {   
            }   
        }   
        Snake.run = false;   
    }   
}   
   
class Snake {   
    GamePanel panel;   
   
    Node food;   
   
    boolean[][] all;   
   
    public static boolean run;   
   
    int maxX;   
   
    int maxY;   
   
    public static int left = 1;   
   
    public static int up = 2;   
   
    public static int right = 3;   
   
    public static int down = 4;   
   
    int direction = 4;   
   
    LinkedList snakeList = new LinkedList();   
   
    public Snake(GamePanel p, int maxX, int maxY) {   
        panel = p;   
        this.maxX = maxX;   
        this.maxY = maxY;   
        all = new boolean[maxX][maxY];   
        for (int i = 0; i < maxX; i++) {   
            for (int j = 0; j < maxY; j++) {   
                all[i][j] = false;   
            }   
        }   
        int arrayLength = maxX > 20 ? 10 : maxX / 2;   
        for (int i = 0; i < arrayLength; i++) {   
            int x = maxX / 10 + i;   
            int y = maxY / 10;   
            snakeList.addFirst(new Node(x, y));   
            all[x][y] = true;   
        }   
        food = createFood();   
        all[food.x][food.y] = true;   
    }   
   
    // 蛇移动的方法    
    public void move() {   
        Node n = (Node) snakeList.getFirst();   
        int x = n.x;   
        int y = n.y;   
   
        if (direction == 3) {   
            x++;   
        } else if (direction == 4) {   
            y++;   
        } else if (direction == 1) {   
            x--;   
        } else if (direction == 2) {   
            y--;   
        }   
        // 实现对蛇撞到自身的检测    
        if ((0 <= x && x <= GamePanel.panelWidth / 15 - 1)   
                && (0 <= y && y <= GamePanel.panelHeight / 15 - 1)) {   
            if (all[x][y]) {   
                if (x == food.x && y == food.y) {   
                    snakeList.addFirst(food);   
                    food = createFood();   
                    all[food.x][food.y] = true;   
                } else {   
                    JOptionPane.showMessageDialog(null, "你撞到自己了");   
                    System.exit(0);   
                }   
            } else {   
                snakeList.addFirst(new Node(x, y));   
                all[x][y] = true;   
                Node l = (Node) snakeList.getLast();   
                snakeList.removeLast();   
                all[l.x][l.y] = false;   
            }   
        } else {   
            JOptionPane.showMessageDialog(null, "越界了,游戏结束");   
            System.exit(0);   
        }   
        panel.repaint();   
    }   
   
    public Node createFood() {   
        int x = 0;   
        int y = 0;   
        do {   
            Random r = new Random();   
            x = r.nextInt(maxX - 10);   
            y = r.nextInt(maxY - 10);   
   
        } while (all[x][y]);   
        return new Node(x, y);   
    }   
//设置蛇不能回头    
    public void changeDirection(int newDirection) {   
        if (direction % 2 != newDirection % 2) {   
            direction = newDirection;   
        }   
    }   
   
    public void drawMap(Graphics2D g) {   
        for (int i = 0; i < maxX; i++) {   
            for (int j = 0; j < maxY; j++) {   
                if (all[i][j] == true) {   
                    g.setColor(Color.red);   
                    g.fillRect(i, j, 4, 4);   
                }   
            }   
        }   
    }   
}   

/*  
 *12.24日,完成了蛇撞到自己的检测.修改方法是在蛇的初始化的时候,用双循环来置FALSE; 
 * 在重写代码的时候,我借鉴了别人的思路:将整个游戏的界面定义为一个布尔型的二维数组. 
 * 用一个LinkedList来储存蛇.当蛇移动的时候,在蛇的头部增加一个节点,然后删除最后一个节点. 
 * 因为只是做练习,所以没做游戏界面,比如菜单栏,计分栏什么的.另外还有一个问题,就是当两次点击回车时,蛇的移动速度会变快 
 */ 
import javax.swing.*; 
import java.awt.*; 
import java.awt.event.*; 
import java.util.*; 
 
public class GreedySnake { 
	public static void main(String args[]) { 
		GameFrame frame = new GameFrame(); 
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
		frame.setResizable(false); 
		frame.show(); 
		JOptionPane.showMessageDialog(null, "上,下左,右控制蛇的方向\n回车开始,S暂停"); 
	} 
} 
 
class GameFrame extends JFrame { 
	public GameFrame() { 
		setSize(294, 482); 
		setTitle("贪吃蛇DEMO"); 
		this.setLocation(360, 100); 
		Container c = getContentPane(); 
		GamePanel panel = new GamePanel(); 
		c.add(panel, BorderLayout.CENTER); 
	} 
} 
 
class GamePanel extends JPanel implements KeyListener { 
	static int panelWidth = 294; 
 
	static int panelHeight = 450; 
 
	int rectX = 15; 
 
	int rectY = 15; 
 
	Snake snake; 
 
	Node n; 
 
	public GamePanel() { 
		snake = new Snake(this, panelWidth / rectX, panelHeight / rectY); 
		setBackground(Color.WHITE); 
		setSize(panelWidth, panelHeight); 
		setFocusable(true); 
		addKeyListener(this); 
	} 
 
	public void paintComponent(Graphics g) { 
		super.paintComponent(g); 
		Graphics2D g2 = (Graphics2D) g; 
		LinkedList list = snake.snakeList; 
		Iterator it = list.iterator(); 
		g2.setColor(Color.black); 
		while (it.hasNext()) { 
			n = (Node) it.next(); 
			drawNode(g2, n); 
		} 
		g2.setColor(Color.ORANGE); 
		Node f = snake.food; 
		drawNode(g2, f); 
		snake.drawMap(g2);// 绘制地图 
	} 
 
	public void keyPressed(KeyEvent e) { 
		int keycode = e.getKeyCode(); 
		if (keycode == KeyEvent.VK_ENTER) { 
			begin(); 
		} else if (keycode == KeyEvent.VK_UP) { 
			snake.changeDirection(Snake.up); 
		} else if (keycode == KeyEvent.VK_DOWN) { 
			snake.changeDirection(Snake.down); 
		} else if (keycode == KeyEvent.VK_LEFT) { 
			snake.changeDirection(Snake.left); 
		} else if (keycode == KeyEvent.VK_RIGHT) { 
			snake.changeDirection(Snake.right); 
		} else if (keycode == KeyEvent.VK_S) { 
			Snake.run = false; 
		} 
	} 
 
	public void keyReleased(KeyEvent e) { 
	} 
 
	public void keyTyped(KeyEvent e) { 
	} 
 
	public void drawNode(Graphics2D g, Node n) { 
		g.fillRect(n.x * rectX, n.y * rectY, rectX - 2, rectY - 2); 
	} 
 
	public void begin() { 
		Snake.run = true; 
		SnakeThread thread = new SnakeThread(snake); 
		thread.start(); 
	} 
} 
 
class Node { 
	int x; 
 
	int y; 
 
	public Node(int x, int y) { 
		this.x = x; 
		this.y = y; 
	} 
} 
 
class SnakeThread extends Thread { 
	Snake snake; 
 
	public SnakeThread(Snake s) { 
		snake = s; 
	} 
 
	public void run() { 
		Snake.run = true; 
 
		while (Snake.run) { 
			try { 
				snake.move(); 
				sleep(200); 
			} catch (InterruptedException e) { 
			} 
		} 
		Snake.run = false; 
	} 
} 
 
class Snake { 
	GamePanel panel; 
 
	Node food; 
 
	boolean[][] all; 
 
	public static boolean run; 
 
	int maxX; 
 
	int maxY; 
 
	public static int left = 1; 
 
	public static int up = 2; 
 
	public static int right = 3; 
 
	public static int down = 4; 
 
	int direction = 4; 
 
	LinkedList snakeList = new LinkedList(); 
 
	public Snake(GamePanel p, int maxX, int maxY) { 
		panel = p; 
		this.maxX = maxX; 
		this.maxY = maxY; 
		all = new boolean[maxX][maxY]; 
		for (int i = 0; i < maxX; i++) { 
			for (int j = 0; j < maxY; j++) { 
				all[i][j] = false; 
			} 
		} 
		int arrayLength = maxX > 20 ? 10 : maxX / 2; 
		for (int i = 0; i < arrayLength; i++) { 
			int x = maxX / 10 + i; 
			int y = maxY / 10; 
			snakeList.addFirst(new Node(x, y)); 
			all[x][y] = true; 
		} 
		food = createFood(); 
		all[food.x][food.y] = true; 
	} 
 
	// 蛇移动的方法 
	public void move() { 
		Node n = (Node) snakeList.getFirst(); 
		int x = n.x; 
		int y = n.y; 
 
		if (direction == 3) { 
			x++; 
		} else if (direction == 4) { 
			y++; 
		} else if (direction == 1) { 
			x--; 
		} else if (direction == 2) { 
			y--; 
		} 
		// 实现对蛇撞到自身的检测 
		if ((0 <= x && x <= GamePanel.panelWidth / 15 - 1) 
				&& (0 <= y && y <= GamePanel.panelHeight / 15 - 1)) { 
			if (all[x][y]) { 
				if (x == food.x && y == food.y) { 
					snakeList.addFirst(food); 
					food = createFood(); 
					all[food.x][food.y] = true; 
				} else { 
					JOptionPane.showMessageDialog(null, "你撞到自己了"); 
					System.exit(0); 
				} 
			} else { 
				snakeList.addFirst(new Node(x, y)); 
				all[x][y] = true; 
				Node l = (Node) snakeList.getLast(); 
				snakeList.removeLast(); 
				all[l.x][l.y] = false; 
			} 
		} else { 
			JOptionPane.showMessageDialog(null, "越界了,游戏结束"); 
			System.exit(0); 
		} 
		panel.repaint(); 
	} 
 
	public Node createFood() { 
		int x = 0; 
		int y = 0; 
		do { 
			Random r = new Random(); 
			x = r.nextInt(maxX - 10); 
			y = r.nextInt(maxY - 10); 
 
		} while (all[x][y]); 
		return new Node(x, y); 
	} 
//设置蛇不能回头 
	public void changeDirection(int newDirection) { 
		if (direction % 2 != newDirection % 2) { 
			direction = newDirection; 
		} 
	} 
 
	public void drawMap(Graphics2D g) { 
		for (int i = 0; i < maxX; i++) { 
			for (int j = 0; j < maxY; j++) { 
				if (all[i][j] == true) { 
					g.setColor(Color.red); 
					g.fillRect(i, j, 4, 4); 
				} 
			} 
		} 
	} 
} 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值