java贪吃蛇小游戏实现

创建snake类

package SomeDo;


//类snack
//定义蛇类
//导入相当于是头文件
import java.awt.Color;
import java.awt.Graphics;
import java.util.ArrayList;		//数组列表
import java.util.List;			//链表

import javax.swing.JOptionPane;

class Node {
  private int x , y;
  public Node() {}										 //构造函数
  public Node(int a , int b) {x = a; y = b;}			 //构造函数的多态
  public Node(Node tmp) {x = tmp.getX(); y = tmp.getY();}//构造函数的多态
  int getX() {return x;}
  int getY() {return y;}
  void setX(int a) {x = a;}//重置x
  void setY(int b) {y = b;}//重置y
}
public class Snack {
  static final int DIR[][] = {{0 , -1} , {0 , 1} , {-1 , 0} , {1 , 0}};//蛇的方向:用方向向量来实现,上下左右
  private List<Node> lt = new ArrayList<Node>();//
  private int curDir;
  
  //构造函数,构造一条蛇
  
  public Snack() {
      curDir = 3;				  //蛇的初始方向是向右边
      lt.add(new Node(350 , 250));//初始化蛇在350,250处生成
      //初始化三个蛇身子
      for(int i = 1;i <= 3;i++) {
    	  lt.add(new Node(350 - 10 * i,250));
      }
  }
  
  int length() {return lt.size();}  //获取长度
  int getDir() {return curDir;} 	//获取方向
  
  //将蛇表现出来
  void draw(Graphics g) 
  {
      g.setColor(Color.red); 
      g.fillRect(lt.get(0).getX(),lt.get(0).getY(),9,9);
      g.setColor(Color.yellow);
      for(int i = 1; i < lt.size(); i++) {
          g.fillRect(lt.get(i).getX(), lt.get(i).getY(), 9, 9);
      }
  }
  
  //死亡的唯一表现形式:头撞身子
  //可以改成有墙壁的
  boolean Dead() {
      for(int i = 1; i < lt.size(); i++) {
          if(lt.get(0).getX() == lt.get(i).getX() && lt.get(0).getY() == lt.get(i).getY()) 
              return true;
      }
      return false;
  }
  
  //蛇头移动
  Node headMove() 
  {
      int tx = lt.get(0).getX() + snackWin.Size * DIR[curDir][0];
      int ty = lt.get(0).getY() + snackWin.Size * DIR[curDir][1];
      if(tx > snackWin.GameLocX + snackWin.GameWidth - snackWin.Size) tx = snackWin.GameLocX;//相当于取余数
      if(tx < snackWin.GameLocX) tx = snackWin.GameWidth + snackWin.GameLocX - snackWin.Size;
      if(ty > snackWin.GameLocY + snackWin.GameHeight - snackWin.Size) ty = snackWin.GameLocY;
      if(ty < snackWin.GameLocY) ty = snackWin.GameHeight + snackWin.GameLocY - snackWin.Size;
      Node tmp = new Node(tx, ty);
      return tmp;
  }
  
  //蛇头移动后的结果:吃食物,死亡
  void move()
  {
      Node head = headMove() , newNode = new Node();//为什么需要加上node(),初始化
      boolean eat = false;
      
      //吃食,生成新的食物
      if(Math.abs(head.getX() - snackWin.rx) < 9 && Math.abs(head.getY() - snackWin.ry) < 9) {
          eat = true;
          newNode = new Node(lt.get(lt.size() - 1));
          snackWin.rx = (int)(Math.random() * (snackWin.GameWidth - 10) + snackWin.GameLocX);//应该是-10,否则出去了
          snackWin.ry = (int)(Math.random() * (snackWin.GameHeight - 10) + snackWin.GameLocY);
      }
      
      //蛇头随着蛇尾移动
      for(int i = lt.size() - 1; i > 0; i--)//最后一个位置舍去,就是尾巴向前移动一个 
          lt.set(i, lt.get(i - 1));
      lt.set(0, head);//新的蛇头保存下来
      
      //死亡之后弹出对话框
      if(Dead()) {
          JOptionPane.showMessageDialog(null, "Snake eating itself", "Message", JOptionPane.ERROR_MESSAGE);
          System.exit(1);
      }
      
      //吃食,分数增加
      if(eat) {
          lt.add(newNode);//如果吃了食物最后一个尾巴在长上
          snackWin.score++;
          snackWin.speed++;
      }
  }
  
  //改变方向的函数
  void changeDir(int dir) {curDir = dir;}
}
 

创建规则类

package SomeDo;

//类snackWin

import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.JButton;//引入button
import javax.swing.JPanel;

public class snackWin extends JPanel implements ActionListener, KeyListener {
	
  /**
	 * 
	 */
	private static final long serialVersionUID = 1L;
//初始化蛇棋盘的信息
  static final int Up = 0 , Down = 1 , Left = 2 , Right = 3;
  //边距,长宽
  static final int GameLocX = 50 , GameLocY = 50 , GameWidth = 700 , GameHeight = 500 , Size = 10;
  static int rx , ry , score = 0 , speed = 0;
  
  //控制信息
  boolean startFlag = false;
  JButton startButton , stopButton , quitButton; 
 
  //声明一条蛇
  Snack snack;
  
  //构造函数
  public snackWin() {
	  
	  //蛇的创建
	  snack = new Snack();
	  
	  //产生食物
      rx = (int)(Math.random() * (GameWidth - 10) + GameLocX);//相当于[50,690]取随机数
      ry = (int)(Math.random() * (GameHeight - 10) + GameLocY);//同理
      
      //控制键的创建并命名
      startButton = new JButton("开始");//JButton中自带的startButton;
      stopButton = new JButton("暂停");
      quitButton = new JButton("退出");
      
      //控制键的位置
      setLayout(new FlowLayout(FlowLayout.LEFT));
      
      //控制键的定义
      this.add(startButton);
      this.add(stopButton);
      this.add(quitButton);
      startButton.addActionListener(this);
      stopButton.addActionListener(this);
      quitButton.addActionListener(this);
      this.addKeyListener(this);
      
      //创建一个蛇线程并调用
      new Thread(new snackThread()).start();  
  }
  
  //将图像先是给用户
  public void paint(Graphics g)
  {
	  //界面
      super.paint(g);   		//没有会将button刷掉
      g.setColor(Color.white);  //界面的颜色
      g.fillRect(GameLocX, GameLocY, GameWidth, GameHeight);  //刷新界面
      g.setColor(Color.black);
      g.drawRect(GameLocX, GameLocY, GameWidth, GameHeight);  //绘制边界
      g.drawString("Score: " + score + "        Speed: " + speed + "      速度最大为100" , 250, 25);
      
      //食物
      g.setColor(Color.green);
      g.fillRect(rx, ry, 9, 9);   //食物
      
      //蛇
      snack.draw(g);
  }
  
  //控制蛇的行为
  public void actionPerformed(ActionEvent e) {
	  
	  //开始
      if(e.getSource() == startButton) {
          startFlag = true;
          startButton.setEnabled(false);
          stopButton.setEnabled(true);
      }
      
      //暂停
      if(e.getSource() == stopButton) {
          startFlag = false;
          startButton.setEnabled(true);
          stopButton.setEnabled(false);
      }
      
      //结束
      if(e.getSource() == quitButton) {
          System.exit(0);
      }
      
      //不知道是什么
      this.requestFocus();
  }
  
  //按键就回移动
  public void keyPressed(KeyEvent e) {
      //System.out.println(e.getKeyCode()); 
      if(!startFlag) return ;
      
      //方向
      switch(e.getKeyCode()) {
      case KeyEvent.VK_UP:
          if( snack.getDir() == Down) break;//如果是向下的就不改变
          snack.changeDir(Up);
          break;
      case KeyEvent.VK_DOWN:
          if( snack.getDir() == Up) break;
          snack.changeDir(Down);
          break;
      case KeyEvent.VK_LEFT:
          if( snack.getDir() == Right) break;
          snack.changeDir(Left);
          break;
      case KeyEvent.VK_RIGHT:
          if(snack.length() != 1 && snack.getDir() == Left) break;//因为snake 的长度永远大于1所以不需要加上这一句
          snack.changeDir(Right);
          break;
      }
  }
  
  
  public void keyReleased(KeyEvent e) {}
  public void keyTyped(KeyEvent e) {}
  
  //类中的类是什么操作?
  class snackThread implements Runnable
  {
      public void run() {
          while(true) {
              try {
                  Thread.sleep(100 - speed >= 0 ? 100 - speed : 0);
                  repaint();
                  if(startFlag) {
                      snack.move();
                  }
              }
              catch(InterruptedException e) {
                  e.printStackTrace();
              }
          }
      }
  }
}

主启动类

package SomeDo;

//类greedySnackMain

import javax.swing.JFrame;


public class greedySnackMain extends JFrame {
  
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	//声明这一个类
	snackWin snackwin;
  
  //对话框的初始化
  static final int Width = 900 , Height = 700 , LocX = 400 , LocY = 80;
  
  public greedySnackMain() {
      super("GreedySncak_SL");
      
      //创建这一个类
      snackwin = new snackWin();
      
      //在对话框中加入这一个类
      add(snackwin);
      
      //对话框的信息设置
      this.setSize(Width, Height);	//为对话框增加长宽
      this.setVisible(true);    	//对话框可视
      this.setLocation(LocX, LocY); //对话框的位置
      //snackwin.requestFocus();
  }
  
  //主函数
  public static void main(String[] args) {
	  
	  //直接创建就可以了,用不到其中的信息
      new greedySnackMain();
  }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值