贪吃蛇第三弹

贪吃蛇第三弹

要求:创建一个界面,并在界面中画单元格,添加一个线程控制重画,添加键盘方向键来控制蛇的移动
代码:
第一个类

package snake;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
public class Snake {
 // 确定蛇的位置
 private int x;
 private int y;
 // 确定蛇的大小
 private static final int width = 25;
 private static final int height = 25;
 // 实例化方向类
 private Direction dir = Direction.D;
 // 调用SnakeMain类
 private SnakeMain sankeMain;
// 构造带3个参数的方法
 public Snake(int x, int y, SnakeMain snakeMain) {
  this.x = x;
  this.y = y;
  this.sankeMain = snakeMain;
 }
 // 构造带4个参数的方法
 public Snake(int x, int y, Direction dir, SnakeMain snakeMain) {
  this(x, y, snakeMain);
  this.dir = dir;
  }
  public void draw(Graphics g) {
  // 调用画笔
  Color c = g.getColor();
  g.setColor(Color.BLACK);// 设置画笔颜色
  g.setColor(c);
  g.fillRect(x, y, width, height);// 画填充了颜色矩形小蛇
 }
 public void keyPressed(KeyEvent e) {
  // 获取键盘上的键入的方向事件
  int key = e.getKeyCode();
  switch (key) {
  case KeyEvent.VK_LEFT: // 键入为左
   this.x = x - width; // 相对原位置减一个宽度
   break;
  case KeyEvent.VK_UP: // 键入为上
   this.y = y - height; // 相对原位置减一个高度
   break;
  case KeyEvent.VK_RIGHT: // 键入为右
   this.x = x + width; // 相对原位置加一个宽度
   break;
  case KeyEvent.VK_DOWN: // 键入为下
   this.y = y + height;// 相对原位置加一个高度
   break;
  }
  // 边界控制
  if (x <= 0) {
   x = 0;
  } else if (x > SnakeMain.SNAKE_WIDTH - width) {
   x = SnakeMain.SNAKE_WIDTH - width;
  }
  if (y <= 0) {
   y = 0;
  } else if (y > SnakeMain.SNAKE_HEIGHT - height) {
   y = SnakeMain.SNAKE_HEIGHT - width;
  }
  }
  }

第二个类:

package snake;
public enum Direction  {
   L,U,R ,D  //枚举列出4个方向LEFT,UP,RIGHT,DOEN
}

第三个类

package snake;
import java.awt.Color;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
/**
 * 项目名称:Snake 
 * 创建人:YM 
 * 类描述: 创建一个界面,并在界面中画单元格,添加一个线程控制重画,添加键盘方向键来控制蛇的移动
 *  创建时间:2019年1月16日 下午2:59:06
 *
 */
 public class SnakeMain extends Frame {
 static final int SNAKE_WIDTH = 1000; // 定义组件的宽度
 static final int SNAKE_HEIGHT = 600; // 定义组件的高度
 private static final int squareSize = 25; // 用来确定单元格的大小
 Snake s = new Snake(50,50,Direction.D,this);//实例化一个对象,确定蛇的位置
 public static void main(String[] args) {
  SnakeMain s = new SnakeMain(); // 构建SnakeMai类的一个实例,并命名为s
  s.launchFrame(); // 调用实例中的launchFrame()方法
 }
 private void launchFrame() {
  this.setLocation(100, 100); // 确定组件位置
  this.setSize(SNAKE_WIDTH, SNAKE_HEIGHT); // 确定组件大小
  this.setBackground(Color.WHITE); // 确定组件背景颜色
  this.setTitle("我的贪吃蛇"); // 设置窗口的标题
  // 添加关闭的处理事件
  this.addWindowListener(new WindowAdapter() {
   // 添加一个窗口监听
   @Override
   public void windowClosing(WindowEvent e) {
    System.exit(0); // 窗口关闭事件
   }
  });
  // 禁止改变窗的大小
  this.setResizable(false);
  this.setVisible(true);
  //通过调用线程运行启动线程
        new Thread(new MyPaintThread()).start();
        //通过添加指定的按键侦听器,以接收此组件的按键事件
  this.addKeyListener(new MyKeyListener());
 }
@Override
 public void paint(Graphics g) {
  // 调用画笔
  Color c = g.getColor();
  g.setColor(Color.GRAY); // 设置画笔颜色
  g.setColor(c);
  int xweight = SNAKE_WIDTH / squareSize;
  int xheight = SNAKE_HEIGHT / squareSize;
  // 画线
  for (int i = 0; i < xweight; i++) {
   g.drawLine(i * squareSize, 0, i * squareSize, SNAKE_HEIGHT);
  } // 画纵向的线
  for (int i = 0; i < xheight; i++) {
   g.drawLine(0, i * squareSize, SNAKE_WIDTH, i * squareSize);
  } // 画横向的线
  s.draw(g); //调用画小蛇的方法
 }
 private class MyPaintThread implements Runnable{
   //通过新建一个MyPaintThread类来实现Runnable接口
         //重画线程
  @Override
  public void run() {
   //线程的入口
   //每隔50ms重画一次
   while(true){
    repaint();//会自动调用paint方法
    try {
     //指定捕获异常的类型
     Thread.sleep(50);
    } catch (InterruptedException e)
    //InterruptedException异常是指当一个当一个正在执行的线程被中断
    {
     e.printStackTrace();//在命令行中打印异常信息在程序中出错的位置既原因
    }
   }  
  }  
 }
  private class MyKeyListener extends KeyAdapter{
        // 键盘监听类
  @Override
  public void keyPressed(KeyEvent e) {
   s.keyPressed(e);
  }  
 }
}

在这里插入图片描述

从贪吃蛇第三弹中学到的知识点:

1,public enum Direction
Direction是Java.lang.enum的子类,其内部包含方向信息,其枚举出来的量可用于Switch语句

2,线程Thread
java的多线程系统构建在Thread类,方法以及Runnable接口之上,Thread封装了线程的执行,如果不能直接引用一个运行的线程状态,可以通过产生它的线程实例来处理它,也可以通过继承Thread类或者实现Runnable接口创建一个新线程,Thread类定义了几个管理线程的方法如下:

getName():获得线程的名字
getPriority():获得线程的优先级
jsAlive():判断线程是否仍在运行
jion():等待一个线程终止
run():线程入口
sleep():暂停一个线程一段时间
start():通过调用线程的运行方法启动它

Runnable接口抽象了可执行的代码单元,Runnable只是一个接口,它里面只有一个run()方法,没有start()方法,所以即使实现了Runnable接口,也无法启动线程,必须依托其他类,即实现接口后,需要依靠Thread来启动

3,KeyPressed(KeyEvent e)键盘按键函数,函数每按下一次时都会被调用一次,按下的键被保存在存储变量中

KeyReleased(KeyEvent e)在源组件上释放一个键后被调用

KeyTyped(KeyEvent e)在源组件上上按下一个键然后释放该键后被调用

KeyListener是键盘监听器,使用时需要继承KeyAdapter类

KeyAdapter类是KeyListener键盘监听器的适配器,每一个KeyAdapter都对应一个或多个KeyListener

KeyEvent()按键事件可以利用键盘来控制和执行一些动作,或者从键盘获取输入,只要按下,释放一个键或者在组件上敲击,就会触发事keyEvent对象描述事件的特性和对应的值,每个按键事件有一个相关的按键字符

getKeyChar()和按键代码getKeyCode()

按键常量: VK_HOME Home键
VK_CONTROL 控制键
VK_END End键
VK_SHIFT Shift键
VK_PGUP page up键
VK_BACK_SPACE 退格键
VK_PGDN page dowm键
VK_CAPS_LOCK 大小写锁定键
VK_ENTER 回车键
VK_NUM_LOCK 小写键盘锁定键
VK_UP 上箭头
VK_DOEN 下箭头
VK_LEFT 左箭头
VK_RIGHT 右键头
VK_F12 F1-F12
VK_ESCAPE Esc键
VK_9 0-9
VK_TAB Tab键
VK_Z A-Z

4,构造函数:在创建对象时就对其进行初始化,即为对象成员变量赋初值,它与其所在的类具有相同的名称,并且在语法上与方法类似,与运算符NEW一起使用在创建对象语句中,能够把定义对象时的参数传给对象的域,即当创建一个对象时,这个对象就被初始化,可以根据其参数个数的不同或参数类型不同来区分它们。如果写的一个类里面没有构造函数,那么编译器会默认加上一个无参数且方法体为空的构造函数,

构造函数的名称必须与类名相同,包括大小写
构造函数没有返回值,也不能用void修饰,如果在构造函数前添加了返回值类型,将使该钩爪函数变成一个普通的方法

5,this关键字:this关键字代表对象本身,,在程序内部,可以在任何方法内使用this关键字引用当前对象,在构造函数中可以使用this关键字调用本类中的其他构造函数,当有几点要求

1,构造函数调用其它的构造函数,需要将this写在构造函数的第一行

2,构造函数不可递归,防止死循化

6,implements接口
实现接口需要注意的问题:
1,实现一个接口就是要实现该接口的所有方法,抽象类除外

2,接口中所有的方法都是抽象的

3,多个无关类可以实现同一个接口,一个雷可以实现多个无关接口

7,try和catch
Java运行时系统提供默认异常处理,这样做不仅可以允许你修正错误,而且可以防止程序自动终止,要防止和处理运行错误时,需要将监控代码写在try块中,然后在try块后面紧跟一个catch字句,该字句指定了需要捕获的异常类型,如果没有try的话,会出现异常导致程序崩溃

 try{
//代码区
}catch(Exceotion e){
//异常处理
}
如果代

码区有错误,会返回所写的异常处理

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值