当前位置: 首页 > article >正文

Javase | 贪吃蛇小游戏

目录:

    • 1.贪吃蛇游戏介绍:(该游戏代码不是很完善,可后续不断优化哦)
    • 2.贪吃蛇游戏的代码操作步骤/讲解:
    • 3.贪吃蛇游戏的详细代码 :
      • 3.1MPanel.java
      • 3.2 Msnake.java
    • 4.贪吃蛇游戏的代码分享 (获得代码 和 其中游戏图片)
    • 5.(继续优化/完善中.....)

1.贪吃蛇游戏介绍:(该游戏代码不是很完善,可后续不断优化哦)

2.贪吃蛇游戏的代码操作步骤/讲解:

* 1:设计游戏图纸

* 2:设计游戏窗体

* 3:在窗体上添加面板

* 4:在面板上添加画笔方法(paintComponent方法)

*5 用super调用父类的paintComponent (来每一次刷新界面)

* 6:在面板上添加标题:用ImageIcon导入图片类来导入图片,然后调用有关方法

* 7:在面板上添加黑色游戏区框(添加黑色方框)-----在画新成分的paintComponent方 法中 直接用画笔的天面方框的g.fillRect()来填满方框(已达到添加黑色方框的)

* 8:放静态的蛇(包括身体和头):—与在画板上添加标题是差不多的。都是放入图片,与其格式类似

* 9:定义蛇的数据结构 ----记录蛇的长度并把蛇能达到的x y 坐标记录在数组中。数据结 构:意思是将蛇的部位的x y坐标放入到数组中(存放在数组中,以方便调用,此即为蛇 的数据结构)

* 10:控制蛇头的方向----通过设置变量 +if else语句来控制蛇头的方向变化。

* 11:放上开始字符提示----用画笔的g.drawString方法在面板直接有字符串出现 (要先改变画 笔的颜色,用setColor()方法来改变画笔的颜色 +设计字体的有关内容,如字体类型、大 小、是否粗体等的setFont方法)

* 12 :设置boolean变量来显示是否是开始状态,且结合此状态来判断开始字符提示是否应 该没有(不打印了)----只有状态是false才输出开始提示

* 13:设置获取键盘事件-----设置获取焦点的setFocusable()方法,这样就可获取键盘事件

* 14:设置键盘监听器 ----通过addKeyListener()方法来设置键盘监听器,(自己监听自己 是键盘事件,那就要实现KeyListener的接口)

* 15:重写实现KeyListener接口的方法

* 16:通过设置变量 + getKeyCode()方法 来获取到键盘敲了哪个数字 (因为每一个按键都 对应一个数字,getKeyCode()方法能获取到键盘敲了哪个数字)

* 17:判断键盘是否敲了空格键,如果敲了就改变isstarted的状态 (KeyEvent.VK_SPACA : 表示空格键)

* 18:按空格键开始游戏

* 19:设置时钟—让程序到成运行结束和 运行结束后找数: 一般游戏是找回自身的即找 回this。 (要实现ActionListener接口才能设置时钟)(时间到了就会调用重写的 ActionListener的方法)

* 20 :实现ActionListener接口—让时钟能够设置

* 21 :重写接口方法

* 22:在重写的方法中,重写paintComponent方法(即repaint) +通过Timer.start() 让时钟再次开始

* 23:在构造方法中让时钟启动起来。

* 24 :让身体移动起来

* 25 :让头发生移动 ----通过snakex[0] =snakex[0] + 25;让蛇一直向右移动

* 26 :给头的移动范围增加边界----用if语句 +如果snakex[0] =850,就有snakex[0] =25, 通过此让其回到反方向的边界处。(到了边界就从反方向边界出现)

* 27:实现暂停 ----按空格就可有蛇不再跑 —(反正括号里是true则输出其语句,如果 是false则不输出)

* 28:根据键盘事件改编direction的值

* 29 :根据direction的值的变化来改变头的移动方向—actionPerformed(ActionEvent) 方法处写代码。因为这是这是与移动有关的内容

*30:添加食物—打印食物的图片 + 随机生成食物的坐标

* 31:吃掉食物

* 32 :判断蛇是否失败 ----设置变量isFiled =false; --当没死的时候才会移动

​ —用for语句判断如果蛇头的坐标与食物的坐标重合的时候,把 isFiled =true(这样会让蛇没法移动了)

* 33:游戏结束提示----当isFiled = true的时候就用drawString输出一个结束字符串提 示游戏结束 (和打印开始提示很类似)

* 34:当游戏结束后,有红色提示出现后,再按空格时不想要白色的开始提示---- 在监听空格键那里把开始提示的变量改为相反的值即可(即把)-

* 34:游戏结束提示 和 实现重新开始功能

* 35:添加分数和长度
……….

( 接下来的步骤可自己结合代码深入理解 )

3.贪吃蛇游戏的详细代码 :

3.1MPanel.java

package moonsnake;

import java.awt.Color;
import java.awt.Font;
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 java.util.Random;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
import javax.swing.Timer;

/**
 *
 *创建游戏面板格式:(讲解:可new对象 或者直接继承JPnanel,让其为父类,获得其属性和方法)
 *关键字为:JPanel
 */

/**
 * 要在面板中画东西,如设置颜色等,前面都要有这两行内容
 * public void paintComponent(Graphics g) {		
 *		super.paintComponent(g);   
 *
 */
public class MPanel extends JPanel implements  KeyListener, ActionListener {    //实现接口,让该面板能监听
	//创建图像类,传入图片到面板中。
	ImageIcon title = new ImageIcon("src/title.jpg");   //用ImageIcon有关的知识点来引入图片
	ImageIcon body= new ImageIcon("src/body.png");    
	ImageIcon up= new ImageIcon("src/up.png");
	ImageIcon down= new ImageIcon("src/down.png");
	ImageIcon left= new ImageIcon("src/left.png");
	ImageIcon right= new ImageIcon("src/right.png");
	ImageIcon food= new ImageIcon("src/food.png");   //然后用画笔画出来
	
	
	/**
	 * 蛇的数据结构,即是有记忆的长度、宽度等是有记录的,长度是会增加的
	 */
	//设置长度
	int len = 3;  //蛇的身体长度默认是3
	
	//设置分数
	int  score = 0;
	//定义数组来存放蛇的x坐标和y坐标:   即蛇能在框移动的位置范围为750x750
	int [] snakex = new  int[750];  //蛇移动的位置:蛇移动产生的x、y坐标
	int [] snakey = new  int[750];
	
	
	/**
	 * 定义变量来确定蛇的方向,而不是只打印一个方向
	 * 
	 * 通过R,L,U,D 来分别代表四个方向  
	 * 先赋一个值,后面根据实际情况而改变
	 */
	String direction = "R";   //先赋一个值,后面会根据实际情况而改变
	
	//设置用于键盘监听器的变量
	//设置判断是否为开始状态 默认是false
	boolean isStarted = false;
	
	
	//设置判断头是否是与身体重叠,重叠就让蛇 out掉
	boolean isFailed = false;
	
	
	//设置时钟,来让蛇体不断进行移动。 new 时钟(Timer)对象
	Timer timer = new Timer(150,this);   //参数为(规定的时间,到点了找谁) ---就可到点了再找回了this,然后不断重复以实现不断的
	 //(时钟设置好了,要在构造方法中进行开始)
	
	//设置食物
	/**
	 * 随机生成食物--引入随机函数 Random 
	 */
	int foodx;   //此变量在画的时候被用
	int foody;
	//引入随机函数
	/**
	 * 生成随机数的格式是:调用生成随机数的nextInt()方法
	 * 如:random.nextInt(34)  //从0到33中随机选一个数
	 */
	
	Random  random  = new  Random();  
	
	
	
   //构造方法 (必须要有空的构造方法)
	public MPanel() {	
		//调用刷新图片的initSnake()方法
		initSnake();  //直接输入方法名
		
		//调用设置获取焦点的方法 即为setFocusable()方法
		//调用设置获取焦点
		this.setFocusable(true);   //获取焦点 即可获取键盘事件
		//设置键盘监听器(参数中填this,即监听此面板的内容)   :调用键盘监听器方法,然后监听自身
		this.addKeyListener(this);   //此处要实现KeyListener的接口
		
		//开始已设置好的时钟
		timer.start();      
		/**
		 * 时钟开始后,在actionPerformed(执行的操作中)进行蛇的移动的操作
		 */
	}
	
	//画游戏中的成分/组成部分的方法
	/**
	 * 其中有Graphics画笔内容
	 */
	public void paintComponent(Graphics g) {
		//在这里面画东西
		super.paintComponent(g);   //调用父类面板方法然后把this.paintComponent中的g传入到调用的方法中
		//设置面板颜色
		/**
		 * 游戏窗体一般是不能设置颜色的,但游戏面板可以设置颜色
		 * 
		 * 用this关键字调用方法则不用new对象的对象的引用来调用方法
		 */
		this.setBackground(Color.WHITE);
		//把引入的图片画出来
		title.paintIcon(this, g, 25, 11);  
		//第一把为画在哪里(this表示画在此面板上。)  g表示传进来的画笔   后两个表示距离窗体的距离
		
		
		
		//在游戏面板中画出黑色的框
		/**
		 * 直接用画笔把想要的方框填成黑色
		 * 即用fill.Rect()方法来在指定位置来填成黑色
		 * (距离位置,距离位置,宽,高)
		 * g即为画笔的引用
		 */
		//画出黑色方框
		g.fillRect(25, 75, 850, 600);
		
		//先把画笔颜色设置为其他颜色,为打印长度和分数做准备
		g.setColor(Color.WHITE);
		//打印长度和分数(用drawString方法打印出字符串、字符)
		g.drawString("len:" +len,750 , 35);
		g.drawString("score:" +score,750 , 50);
		
		//画出身体、上下左右
//				right.paintIcon(this, g, 100, 100);
//				body.paintIcon(this, g, 75, 100);
//				body.paintIcon(this, g, 50, 100);   //这里就不能这样画出蛇的内容,数量多就不行,要用for循环。
		
		//打印头
	  if (direction == "R") {
			right.paintIcon(this, g, snakex[0],snakey[0]);  //如果是R,则打印向右的头图片
	  }else if (direction == "L") {
		  left.paintIcon(this, g, snakex[0],snakey[0]);  //如果是L,则打印向左的头图片
	  }else if (direction == "U") {
		  up.paintIcon(this, g, snakex[0],snakey[0]);  //如果是U,则打印向上的头图片
	  }else if (direction == "D") {
		  down.paintIcon(this, g, snakex[0],snakey[0]);  //如果是D,则打印向下的头图片
	  }
	  
		//打印身体
		for(int i =1 ;i<len;i++) {
			//通过数组下标的增加来在for循环中,打印出蛇的身体  :其坐标为snakex[i],即可根据下标的改变而改变
			body.paintIcon(this, g, snakex[i] ,snakey[i]);
		}
		
		//打印食物
		food.paintIcon(this, g, foodx, foody);
		
		
		//把画笔变成其他颜色
		g.setColor(Color.WHITE);
		
		//改变字体大小  :导入font包,然后设置好参数(字体类型,字符是粗体/斜体,字体大小)
		g.setFont(new Font ("arial",Font.BOLD,40));
		
		/**
		 *在面板中打印开始语 :实际上是用画笔画出字符串
		 */
		//画出开始语
		//当游戏开始时取消画笔画出来的字,isStarted为false时才打印
		if (isStarted ==false ) {
			g.drawString("Press Space to start", 300, 300);
		}
			
		g.setColor(Color.RED);
		g.setFont(new Font ("arial",Font.BOLD,40));
		//输出重新开始语   ---然后要重新开始就要在响应键盘事件:在响应键盘哪里天健if语句使isFailed变成flase
		if (isFailed ==true) {   //如果isFailed = true则输出重新开始语
			g.drawString("Failed:Press Space to start", 200, 300);
		}
		
		/**
		 * 要让这个面板真正的有颜色和其中的方法有效果,就要在窗体中用add方法把面板加入到窗体中。
		 */
	}
	

	/**
	 * 图片的x y坐标放入到数组中,然后要输入x y坐标时调用对应下标的数值即有,+配合for循环语句来打印图片,此过程即为蛇的数据结构
	 */
	 //建立初始化snake的方法 (刷新蛇的图片,让其产生移动的效果)
	public void initSnake() {  //init :初始化
		len  =3;  //蛇开始长度是3
	   /**
	    * 蛇头的坐标是100x100,把存在数组的下标为0(x/y数组的下标都为0)
	    */
		snakex[0]=100;
		snakey[0]=100;  //把蛇头的位置坐标存到数组中,且下标为0
		snakex[1]=75;
		snakey[1]=100;
		snakex[2]=50;
		snakey[2]=100;
		//设置食物的x y坐标位置
		/**
		 * 用nextInt()生成随机数,然后给food坐标用上。 范围是25*(0-33)
		 */
		foodx = 25 +25*random.nextInt(34);   //25 +... 的意思是 食物出现当后面的数是0时,就出现在第一个格子
		foody = 75 +25*random.nextInt(24);  //然后画出来  在paintComponent方法中画出来
		
		//设置分数
		score = 0;  //让重新开始时,分数不会再继续。
	} 

	@Override
	public void keyTyped(KeyEvent e) {  //当键敲了
		
		
	}

	@Override  //响应键盘事件
	public void keyPressed(KeyEvent e) {  //当键敲到底了
		 //KeyEvent :指的是敲了哪个键,设置int类型的变量进行接受
		/**
		 * 使用getKeyCode()方法来获取到敲击了哪个按键 (每一个按键都对应一个数字)
		 */
		int keycode  = e.getKeyCode();  //能够知道敲击了哪个键盘
		if  ( keycode == KeyEvent.VK_SPACE ){   //keycode等于空格键就是isStarted的值改变为true
			//重新开始(响应键盘事件)
			if(isFailed) {
				isFailed = false;
				
				//格式化内容:即调用最开始的方法, 让蛇在一开始的地方重新开始 
				initSnake();
				
			}
			isStarted = !isStarted;     //!isStarted是取反的意思 ,整体的意思就是值取反。
			//再次画图片 :重画图片:repaint();
			repaint();  //此即会重新调用方法
		}else if (keycode == KeyEvent.VK_RIGHT) {    //如果键盘按了向右的键盘
			direction = "R";
		}else if (keycode == KeyEvent.VK_LEFT) {    //如果键盘按了向右的键盘
			direction = "L";
		}else if (keycode == KeyEvent.VK_UP) {    //如果键盘按了向右的键盘
			direction = "U";
		}else if (keycode == KeyEvent.VK_DOWN) {    //如果键盘按了向右的键盘
			direction = "D";               //然后在actionPerformed中配合钟表来刷数据
		}
	}

	@Override
	public void keyReleased(KeyEvent e) { //当键敲完然后抬起来了
	
		
	}

	@Override
	public void actionPerformed(ActionEvent e) {   //时间到了就会调用这个方法
		/**
		 * 时间到了就会调用此方法,然后在此内容结尾再次开启时钟,已达到不断循环的效果
		 */
		//到点了就重写
		repaint();
	
		//将图移动和空格键的内容连接起来
		if (isStarted && !isFailed ) {  //如果isStarted是true 且 !isFailed(且不是失败的)
			/**
			 * 让蛇动起来 :先是头动,即让头的图像x,y发生移动。
			 */
			for (int i = len-1; i>0;i--) {
				snakex[i] = snakex[i-1];    //蛇身体的x坐标移动
				snakey[i] = snakey[i-1];    //蛇身体的y坐标移动
			}
			
			if (direction == "R") {
				//direction = "R" 时执行的代码
				snakex[0] =snakex[0]+25;
				if (snakex[0] >850) snakex[0] = 25; //判断语句的简写形式
			}else if  (direction =="L") {
				snakex[0] =snakex[0]-25;
				if (snakex[0] <25) snakex[0] = 850; //判断语句的简写形式
			}else if  (direction =="U") {
				snakey[0] =snakey[0]-25;
				if (snakey[0] <75) snakey[0] = 650; //判断语句的简写形式
			}else if  (direction =="D") {
				snakey[0] =snakey[0]+25;
				if (snakex[0] >650) snakex[0] = 75; //判断语句的简写形式
			}
		
			//吃掉食物
			/**
			 * 判断食物的x、y坐标是否为头的x、y坐标是否重合
			 */
			if (snakex[0] == foodx && snakey[0]==foody) {
				len++;   //头的图片和食物图片重合就长度+1 ---这样长度+1,身体就会变成。
				
				//长度增加后,分数也会增加  (然后把分数显示出来,把它画出来:实质是打印字符一样打印出来即可)
				score = score +10;  
				//然后重新刷新图片
				foodx = 25 +25*random.nextInt(34);   //25 +... 的意思是 食物出现当后面的数是0时,就出现在第一个格子
				foody = 75 +25*random.nextInt(24);  //然后画出来  在paintComponent方法中画出来
				
			}
			
			//判断头是否和身体重合,如果是则  (用for语句来循环输出len的值/数组的值,然后判断是否有重合现象)
			for (int i = 1;i<len ;i++) {
				if (snakex[i]==snakex[0] && snakey[i]==snakey[0]) {
					//如果是重合的,那就有isFailed 变为true,让移动程序不再运行
					isFailed = true;
				}
			}
			
		}
		//重写
		repaint();	
		
		//然后还有让时钟再次开始
		timer.start();
		
			
	}
}

3.2 Msnake.java

package moonsnake;

import java.awt.Color;

import javax.swing.JFrame;

/**
 * 
 *
 *画出窗体 :900x720
 *
 */

/**
 * 看着有颜色,实质上是面板中的颜色,而是窗体中的颜色。
 *
 */
public class Msnake {
 public static void main(String[] args) {
	/**
	 * 窗体类关键字为:JFrame
	 * 作用就是会有一个游戏面板一样的东西会出现在屏幕上,只要这个窗体是有颜色的话。
	 */
	 //画出窗体类 
	 JFrame frame = new JFrame();  //new一个窗体类对象 
	 
	 //调用jframe的Bounds方法来设置窗体的大小和距离和距离屏幕的位置
	 frame.setBounds(10,10,900,700);
	 
	 //用Resizable方法来设置面板不可拖动
	 frame.setResizable(false);
	 
	 //用setDeafaultCloseOperation方法来关闭游戏界面
	 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	 
	 /**
	  * 用add方法把面板类加入到窗体中
	  */
	 frame.add(new MPanel());
	 //用Visible方法来使窗体展现出来
	 frame.setVisible(true);
	 
	 /**
	  * 做完这些的结果就是有一个900x720的白色的距离左上屏幕10,10距离的窗体。
	  */	 	
 	}
} 

4.贪吃蛇游戏的代码分享 (获得代码 和 其中游戏图片)

链接:百度网盘获得“代码”和“游戏图片”

5.(继续优化/完善中…)


http://www.kler.cn/a/160854.html

相关文章:

  • 搭建Python2和Python3虚拟环境
  • Unity3D实现视频和模型融合效果
  • GISBox VS ArcGIS:分别适用于大型和小型项目的两款GIS软件
  • 如何在Puppeteer中实现表单自动填写与提交:问卷调查
  • 《EasyQuotation 与MongoDB在股市信息的奇妙融合》
  • 如何为电子课程创造创意
  • L1-025:正整数A+B
  • python筛选并删除两个文件夹中不同文件名的文件
  • 2-redis高级-centos上安装redis(编译安装、redis启动)、redis客户端操作、redis使用场景、redis中的通用命令
  • Google Guava 集合工具使用详解
  • Node.js快速搭建简单的HTTP服务器并发布公网远程访问
  • 多向通信----多人聊天
  • Elaticsearch 学习笔记
  • 量子纠缠通讯:未来信息技术的革新者
  • AI算力研究报告:智算供给格局分化国产化进程有望加速
  • 【华为网络-配置-025】- 同 VLAN 下不同网段通信(启用 Sub 地址)
  • 圆通单号查询,圆通速递物流查询,对需要的单号进行颜色标记
  • 你了解架构图吗?
  • pytorch中的transpose用法
  • Verilog开源项目——百兆以太网交换机(四)令牌桶管理单元设计
  • CSS-2
  • php中WebSocket简单使用
  • C++——红黑树
  • uniapp实战 —— 自定义顶部导航栏
  • GPT 中文提示词技巧:参照 OpenAI 官方教程
  • mysql知识分享(包含安装卸载)(一)