gitee仓库地址:
misaka10000/javaswing实现贪吃蛇 (gitee.com)https://gitee.com/misaka10000/java-swing-implements-snake
蛇由 LinkedList<Node> 组成,每个Node包含x,y坐标
思路主要为:
1.初始化界面并绘制棋盘。
2.设置定时任务Timer()让蛇移动 。
3.监听键盘,每次↑↓←→被点击时新增一个节点并删除原链表的最后一个节点实现方向的移动。
4.随机设置食物(节点),蛇吃到食物时便在头部新增一个节点。
视图初始化:
private void initFrame(){ this.setSize(615,610); this.setLocation(250,10); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this.setVisible(true); this.setBackground(new Color(245, 206, 206)); }
游戏界面绘制:
private void initGamePanel(){ jPanel = new JPanel(){ @Override public void paint(Graphics g) { //清空棋盘 g.clearRect(0,0,600,600); //绘制横线 for (int i = 0; i <= 40; i++) { g.drawLine(0,i*15,600,i*15); } //绘制竖线 for (int i = 0; i <= 40; i++) { g.drawLine(i*15,0,i*15,600); } //绘制蛇 LinkedList<Node> body = snake.getBody(); for (Node node : body) { g.fillRect(node.getX()*15,node.getY()*15,15,15); } //绘制食物 g.fillRect(food.getX()*15,food.getY()*15,15,15); } }; this.add(jPanel); }
初始化蛇:
private void initSnake() { this.snake = new Snake(); }
Snake实现:
private void initSnake(){ this.body = new LinkedList<>(); body.add(new Node(16,20)); body.add(new Node(17,20)); body.add(new Node(18,20)); body.add(new Node(19,20)); body.add(new Node(20,20)); body.add(new Node(21,20)); }
设置定时任务(蛇的移动):
private void initTimer() { this.timer = new Timer(); TimerTask timerTask = new TimerTask(){ @Override public void run() { snake.move(); //判断蛇头是否和食物重合 Node head = snake.getBody().getFirst(); if(head.getX()==food.getX()&&head.getY()==food.getY()){ snake.eat(food); food.random(); } //重新绘制棋盘 jPanel.repaint(); } }; //每100毫秒,执行一次监听事件 timer.scheduleAtFixedRate(timerTask,0,100); }
move方法实现:
public void move() { if(isLiving){ Node head = body.getFirst(); switch (direction){ case UP: //在蛇头的上边添加一个节点 body.addFirst(new Node(head.getX(),head.getY()-1)); break; case DOWN: body.addFirst(new Node(head.getX(),head.getY()+1)); break; case LEFT: body.addFirst(new Node(head.getX()-1,head.getY())); break; case RIGHT: body.addFirst(new Node(head.getX()+1,head.getY())); break; } //删除最后的节点 body.removeLast(); //判断蛇是否撞墙 head=body.getFirst(); if(head.getX()<0||head.getY()<0||head.getX()>=40||head.getY()>=40){ isLiving=false; } //判断蛇是否碰到自己的身体 for (int i = 1; i < body.size(); i++) { Node node = body.get(i); if(head.getX()==node.getX()&&head.getY()==node.getY()){ isLiving=false; } } } }
键盘监听事件(感知 ↑↓←→)
private void setKeyListener() { addKeyListener(new KeyAdapter() { //当键盘按下时,会自动掉此方法 @Override public void keyPressed(KeyEvent e) { //键盘中的一个键都有一个编号 switch (e.getKeyCode()){ case KeyEvent.VK_UP: //上键 if(snake.getDirection()!=Direction.DOWN){ snake.setDirection(Direction.UP); } break; case KeyEvent.VK_DOWN: //下键 if(snake.getDirection()!=Direction.UP){ snake.setDirection(Direction.DOWN); } break; case KeyEvent.VK_LEFT: //左键 if(snake.getDirection()!=Direction.RIGHT){ snake.setDirection(Direction.LEFT); } break; case KeyEvent.VK_RIGHT: //右键 if(snake.getDirection()!=Direction.LEFT){ snake.setDirection(Direction.RIGHT); } break; } } }); }
初始化食物:
//初始化食物 private void initFood() { food=new Node(); food.random(); }
public void random(){ Random random = new Random(); this.x = random.nextInt(40); this.y = random.nextInt(40); }
eat方法(类似于键盘监听实现):
public void eat(Node food) { //获取蛇头 Node head = body.getFirst(); switch (direction){ case UP: //在蛇头的上边添加一个节点 body.addFirst(new Node(head.getX(),head.getY()-1)); break; case DOWN: body.addFirst(new Node(head.getX(),head.getY()+1)); break; case LEFT: body.addFirst(new Node(head.getX()-1,head.getY())); break; case RIGHT: body.addFirst(new Node(head.getX()+1,head.getY())); break; } }