java贪吃蛇源码

java贪吃蛇源码java是一种面向对象的语言,有着其中不用质疑的优点。学习java将近三个月了,一直在琢磨着“万物皆对象”的意义,却总是只知其表不知其意,做完这个java贪吃蛇后才有了那么一点的理解。直接上效果图。游戏分为了六个类,分别为:Node类:蛇身都是由一个一个节点组成,所以首先将节点抽象为一个类。Snake类:此类是一条蛇抽象出来的一个类。一种包含了存储节点的LinkedList类型…

大家好,又见面了,我是你们的朋友全栈君。

欢迎访问我的个人博客 https://jialaner.cn/​​​​​​​

java是一种面向对象的语言,有着其中不用质疑的优点。学习java将近三个月了,一直在琢磨着“万物皆对象”的意义,却总是只知其表不知其意,做完这个java贪吃蛇后才有了那么一点的理解。直接上效果图。

java贪吃蛇源码

游戏分为了六个类,分别为:

Node类:蛇身都是由一个一个节点组成,所以首先将节点抽象为一个类。

Snake类:此类是一条蛇抽象出来的一个类。一种包含了存储节点的 LinkedList 类型的集合,蛇的移动的方式是头部加一个节点,尾部减去一个节点。蛇的类有着吃蛋、越界的行为方法。

SnakeGameView类:这个类是一个游戏界面的类,用于布局游戏的界面。

GameControl类:此类用于监听键盘,从而实现对游戏的操作。

GameRunThread类:此类是一个线程类,用于不断重画界面。

DrawView类:此类继承了面板类,从而拥有了paint()方法的使用权,用于游戏面板的重画,像方格、蛇、蛋、的重画。

其中存在一个问题,就是游戏在不断的重画过程中,会出现游戏的闪烁问题,就引出了双缓冲的技术。

在编写程序的时候,总会出现我们意料之外的情况,像游戏变量权限问题、方法归属问题,都需要我们进行思考,如何让我们的程序执行、编写起来更合理、更加符合面向对象编程的思维维,护时改动最少的代码去实现最好的效果,这些都应该是我们去思考的问题。对于游戏的越界问题,一般有两种方式:中心检测法和边界检测法,在这里我用的是边界检测法,具体情况具体选择。

程序可能有着其他不太合理之处,还请大家原谅一个学java不到三个月的求学者。谢谢大家。下面开始上源码。

Node类

public class Node {
	
	private int nodeX;
	private int nodeY;
	
	public Node(int nodeX, int nodeY) {
		
		this.nodeX = nodeX;
		this.nodeY = nodeY;
	}
	
	public int getNodeX() {
		
		return nodeX; 
	}
	public void setNodeX(int nodeX) {
		
		this.nodeX = nodeX;
	}
	public int getNodeY() {
		
		return nodeY;
	}
	public void setNodeY(int nodeY) {
		
		this.nodeY = nodeY;
	}

}

Snake类

public class Snake {
	
	private LinkedList<Node> snakeBody;
	private Random random;
	//Snake的方向    0上, 1 右 , 2 下 , 3 左
	private int direction = 0;  
	
	private SnakeGameView snakeGameView;
	
	public Snake(int snakeHeadX, int snakeHeadY, SnakeGameView snakeGameView) {
		random = new Random();
		snakeBody = new LinkedList<>();
		snakeBody.add(new Node(snakeHeadX, snakeHeadY));
		this.snakeGameView = snakeGameView;
	}
	
	//获取Snake的方向
	public int getDirection() {
		
		return direction;
	}
	//设置Snake方向
	public void setDirection(int direction) {
		
		this.direction = direction;
	}
	//获取Snake头部结点
	public Node getSnakeHead() {
		
		return snakeBody.getFirst();
	}
	//获取Snake尾部结点
	public Node getSnakeTail() {
		
		return snakeBody.getLast();
	}
	//获取Snake的Body
	public LinkedList<Node> getSnakeBody(){
		
		return snakeBody;
	}
	//Snake移动
	public void snakeMove() {
		
		switch(direction) {
		case 0:
			snakeBody.addFirst(new Node(getSnakeHead().getNodeX() ,getSnakeHead().getNodeY() - DrawView.VIEW_NUMBER));
			break;
		case 1:
			snakeBody.addFirst(new Node(getSnakeHead().getNodeX() + DrawView.VIEW_NUMBER,getSnakeHead().getNodeY()));
			break;
		case 2:
			snakeBody.addFirst(new Node(getSnakeHead().getNodeX(),getSnakeHead().getNodeY()+ DrawView.VIEW_NUMBER));
			break;
		case 3:
			snakeBody.addFirst(new Node(getSnakeHead().getNodeX() - DrawView.VIEW_NUMBER,getSnakeHead().getNodeY()));
			break;
		}
		snakeBody.removeLast();
	}
	//Snake 吃Egg
	public void eatEgg(Node egg) {
		if(snakeBody.getFirst().getNodeX() == egg.getNodeX() && snakeBody.getFirst().getNodeY() == egg.getNodeY()) {
		   snakeBody.add(egg);
		   //产蛋
		   snakeGameView.setEgg(random.nextInt(DrawView.VIEW_WIDTH - 1) * DrawView.VIEW_NUMBER,
					random.nextInt(DrawView.VIEW_WIDTH - 1) * DrawView.VIEW_NUMBER);
		   SnakeGameView.gameScore = SnakeGameView.gameScore + 5;
		   snakeGameView.getJTextArea().setText(SnakeGameView.gameScore + "");
		   System.out.println("吃到蛋了");
		}
	}
	//Snake越界
	public void snakeRunInterface() {
		
		if(this.getSnakeHead().getNodeX() < 0 || this.getSnakeHead().getNodeY() < 0||
				this.getSnakeHead().getNodeX() > (DrawView.VIEW_WIDTH * DrawView.VIEW_NUMBER)||
				this.getSnakeHead().getNodeY() > (DrawView.VIEW_WIDTH * DrawView.VIEW_NUMBER)) {
			SnakeGameView.gameState = false;
		}
	}
}

SnakeGameView类

public class SnakeGameView extends Frame{
		
	private JLabel jl;
	private DrawView drawView;
	private Panel panel;
	private JLabel scoreTitle;
	private JLabel score;
	private Panel rule;
	private JTextArea hint;
	
	private Random random;
	public static boolean gameState = true;
	public static int gameScore = 0;
	private Snake snake;
	private Node egg;
	private GameRunThread grt;
	private static Thread thread;
	
	public SnakeGameView() {
		
		random = new Random();
		//初始化Snake
		snake = new Snake(10 * DrawView.VIEW_NUMBER + random.nextInt(19) * DrawView.VIEW_NUMBER,
				10 * DrawView.VIEW_NUMBER + random.nextInt(19) * DrawView.VIEW_NUMBER,this);
		//初始化Egg
		egg = new Node(random.nextInt(DrawView.VIEW_WIDTH - 1) * DrawView.VIEW_NUMBER,
				random.nextInt(DrawView.VIEW_WIDTH - 1) * DrawView.VIEW_NUMBER);
		//初始化画板
		drawView = new DrawView(snake, egg);
		grt = new GameRunThread(drawView, snake);
		thread = new Thread(grt);	
		
		jl = new JLabel("SnakeGame-3.0",JLabel.CENTER);	
		panel = new Panel();
		scoreTitle = new JLabel("Score", JLabel.CENTER);
		score = new JLabel(gameScore + "", JLabel.CENTER);
		rule = new Panel();
		hint = new JTextArea("    操作方式\n      ↑\n  ←      →\n      ↓\n\n【Esc】退出程序\n\n关于\n");		
	}
	
	//设置鸡蛋
	public void setEgg(int eggX, int eggY) {
		
		this.egg.setNodeX(eggX);
		this.egg.setNodeY(eggY);
	}
	//获得
	public JLabel getJTextArea() {
		return score;
	}
	//主方法
	public static void main(String[] args) {
		
		new SnakeGameView().showView();
		thread.start();
	}
	public void showView() {
		
		jl.setFont(new Font("宋体", 1, 18));//设置字体,0正常,1粗体
		jl.setForeground(Color.white);//设置颜色
		jl.setBounds(0, 0, DrawView.VIEW_HEIGHT * DrawView.VIEW_NUMBER + 70, 40);
		drawView.setBackground(new Color(51,51,51));
		drawView.setBounds(20, 50, DrawView.VIEW_WIDTH * DrawView.VIEW_NUMBER + 1, DrawView.VIEW_HEIGHT * DrawView.VIEW_NUMBER + 1);
		panel.setLayout(null);	
		panel.setBackground(new Color(0,102,102));
		panel.setBounds(DrawView.VIEW_WIDTH * DrawView.VIEW_NUMBER + 40, 50, 150, DrawView.VIEW_HEIGHT * DrawView.VIEW_NUMBER);	
		scoreTitle.setFont(new Font("宋体", 1, 18));//设置字体,0正常,1粗体
		scoreTitle.setForeground(Color.white);//设置颜色
		scoreTitle.setBounds(0, 0, 150, 50);
		score.setFont(new Font("宋体", 1, 20));//设置字体,0正常,1粗体
		score.setForeground(Color.white);//设置颜色
		score.setBounds(0, 50, 150, 40);
		rule.setBackground(new Color(0,128,128));
		rule.setBounds(0, 90, 150, 1);
		hint.setFont(new Font("宋体", 0, 16));//设置字体,0正常,1粗体
		hint.setBounds(10, 100, 130, 150);
		hint.setBackground(new Color(0,102,102));
		
		panel.add(scoreTitle);
		panel.add(score);
		panel.add(rule);
		panel.add(hint);	
		this.add(jl);
		this.setTitle("SnakeGame-3.0");
		this.setSize(DrawView.VIEW_WIDTH * DrawView.VIEW_NUMBER + 210, DrawView.VIEW_HEIGHT * DrawView.VIEW_NUMBER + 70);
		this.setLocation(500, 200);
		this.setLayout(null);
		//this.setUndecorated(true);
		this.setBackground(new Color(0,128,128));
		this.add(drawView);
		this.add(panel);
		this.addKeyListener(new GameControl(snake));
		this.addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent we) {
				System.exit(0);
			}
		});
		this.setVisible(true);
		
	}

}

DrawView类

public class DrawView extends Panel{
	
	//画板的宽度高度
	public static final int VIEW_WIDTH = 40;
	public static final int VIEW_HEIGHT = 40;
	public static final int VIEW_NUMBER = 15;
	private Image iBuffer;  
	private Graphics gBuffer;  
	private Snake snake;
	private Node egg;
	
	public DrawView(Snake snake, Node egg) {
		
		this.snake = snake;
		this.egg = egg;
	}
	
	public void paint(Graphics g) {
		
		snake.snakeMove();
		this.drawGridding(g);
		this.drawSnake(g);
		this.drawEgg(g);
		snake.eatEgg(egg);
		System.out.println("("+snake.getSnakeHead().getNodeX()+","+snake.getSnakeHead().getNodeY()+")");
	}
	public void update(Graphics g) {
	 if(iBuffer==null)  
	    {  
	       iBuffer=createImage(DrawView.VIEW_WIDTH * DrawView.VIEW_NUMBER + 1, DrawView.VIEW_HEIGHT * DrawView.VIEW_NUMBER + 1);  
	       gBuffer=iBuffer.getGraphics();  
	    }  
	       gBuffer.setColor(getBackground());  
	       gBuffer.fillRect(0,0,DrawView.VIEW_WIDTH * DrawView.VIEW_NUMBER + 1, DrawView.VIEW_HEIGHT * DrawView.VIEW_NUMBER + 1);  
	       paint(gBuffer);  
	       g.drawImage(iBuffer,0,0,this); 
	}
	//画网格
	public void drawGridding(Graphics g) {
		
		g.setColor(new Color(128,128,128));
		for(int i = 0; i < VIEW_WIDTH; i++) {
			g.drawLine(0, i * VIEW_NUMBER, VIEW_WIDTH * VIEW_NUMBER, i * VIEW_NUMBER);
		}
		for(int i = 0; i < VIEW_HEIGHT; i++) {
			g.drawLine(i * VIEW_NUMBER, 0, i * VIEW_NUMBER, VIEW_WIDTH * VIEW_NUMBER);
		}
		
	}
	//画Snake
	public void drawSnake(Graphics g) {
		
		for(int i = 0; i < snake.getSnakeBody().size(); i ++) {
			g.setColor(Color.white);
			if(i == 0)
				g.setColor(Color.lightGray);
			g.fillRect(snake.getSnakeBody().get(i).getNodeX(), snake.getSnakeBody().get(i).getNodeY(), VIEW_NUMBER, VIEW_NUMBER);
		}
	}
	//画Egg
	public void drawEgg(Graphics g) {
		
		g.setColor(Color.yellow);
		g.fillRect(egg.getNodeX(), egg.getNodeY(), VIEW_NUMBER, VIEW_NUMBER);
	}
	
}

GameRunThread类

 

public class GameRunThread implements Runnable{

	private int runTime = 200;
	private DrawView drawView;
	private Snake snake;
	
	public GameRunThread(DrawView drawView, Snake snake) {
		this.drawView = drawView;
		this.snake = snake;
	}

	public void run() {
		
		while(true) {
			
			snake.snakeRunInterface();
			
			if(SnakeGameView.gameState) {
				
				drawView.repaint();
				
				try {
					Thread.sleep(runTime);
				}catch(InterruptedException e) {
					e.printStackTrace();
				}
					
			}
		}
		
	}

}

GameControl类

public class GameControl implements KeyListener{

	private Snake snake;
	
	public GameControl(Snake snake) {
		
		this.snake = snake;
	}
	
	public void keyReleased(KeyEvent ke) {
		
		switch(ke.getKeyCode()) {
		
		case KeyEvent.VK_UP:
			snake.setDirection(0);
			break;
		case KeyEvent.VK_RIGHT:
			snake.setDirection(1);
			break;
		case KeyEvent.VK_DOWN:
			snake.setDirection(2);
			break;
		case KeyEvent.VK_LEFT:
			snake.setDirection(3);
			break;
		case KeyEvent.VK_ENTER:
			
			if(SnakeGameView.gameState == true) 
				SnakeGameView.gameState = false;
			else 
				SnakeGameView.gameState = true;
			
			break;
		case KeyEvent.VK_ESCAPE:
			System.exit(0);
			break;
		}
	}

	public void keyPressed(KeyEvent arg0) {}
	public void keyTyped(KeyEvent arg0) {}

}

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/141466.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • win11游戏性能提升_win10怎么设置显卡高性能

    win11游戏性能提升_win10怎么设置显卡高性能其实打造一款高性能系统主要要做到以下三点:一、安装纯净的原版系统。二、打开系统的高性能模式,对部分设置进行优化。三、养成良好的使用习惯,在安装软件时,避免某些引起系统卡顿的软件和全家桶、广告软件。安装完纯净版的windows11系统后,可以进行一下的设置优化:一、切换高性能电源计划二、调整性能选项三、调整隐私安全常规设置四、调整隐私安全诊断和反馈设置五、关闭隐私安全搜索权限六、关闭游戏模式七、任务栏设置一、切换高性能电源计划打开系统“开始菜单->所有应用->windows工具

    2022年9月20日
    4
  • django request.get_对象生气了怎么哄

    django request.get_对象生气了怎么哄Django在接收到http请求之后,会根据http请求携带的参数以及报文信息创建一个WSGIRequest对象,并且作为视图函数第一个参数传给视图函数。也就是我们经常看到的request参数。在这个

    2022年7月29日
    7
  • 五大常用算法之五:分支限界法

    一、基本描述类似于回溯法,也是一种在问题的解空间树T上搜索问题解的算法。但在一般情况下,分支限界法与回溯法的求解目标不同。回溯法的求解目标是找出T中满足约束条件的所有解,而分支限界法的求解目标则是找

    2021年12月25日
    36
  • nginx接口转发_网关和nginx区别

    nginx接口转发_网关和nginx区别nginx转发给网关的时候会丢失很多信息,包括host信息解决办法在nginx的配置文件配置proxy_set_headerHost$host;proxy_passhttp://转发的ip地址还有一点需要注意网关转到具体的域名需要配置在网关的最后…

    2022年10月10日
    2
  • Proteus使用教程并仿真51程序——LED流水灯

    Proteus使用教程并仿真51程序——LED流水灯目录一、安装Proteus软件二、熟悉Proteus软件三、51程序设计和仿真四、总结五、参考资料Proteus是LabCenterElectronics公司推出的一个EDA工具软件。Proteus具有原理布图、PCB自动或人工布线、SPICE电路仿真、互动电路仿真、仿真处理器及其外围电路等特点功能。一、安装Proteus软件下面来了解下如何安装Proteus软件,安装过程也十分简单。首先需要下载Proteus的压缩包,链接如下。链接:https://pan.baidu.com/s/1e

    2022年5月10日
    53
  • 语音信号处理入门系列(1)—— 语音信号处理概念「建议收藏」

    语音信号处理入门系列(1)—— 语音信号处理概念「建议收藏」文章目录1.语音交互2.复杂的声学环境2.1声学回声消除2.2解混响2.3语音分离2.4波束形成2.5噪声抑制2.6幅度控制2.7前端信号处理的技术路线3.参考4.推荐开源项目原博客地址:https://www.cnblogs.com/LXP-Never/p/13620804.html1.语音交互你知道苹果手机有几个麦克风吗?语音交互(VUI)是指人与人/设备通过自然语音进行信息传递的过程。语音交互的优势:输入效率高。语音输入的速度是传统键盘输入方式的3倍以上。例如:语

    2022年5月18日
    57

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号