Java学习总结之贪吃蛇项目程序编写(一)

之前写了程序分析,接下来进入程序编写,这次写程序跟之前的项目不一样,之前是新增一个功能,就根据这个功能新增一部分内容,而这次有了程序分析,我打算即使还没有加入新功能,也预留好新功能需要的各种属性和方法,即使某个方法还没有实现,也会在应该调用它的地方以注释的形式加入调用语句。

V0.1:这个版本主要是绘制界面。根据程序设计中的属性和方法,实现如下:

SnakeFrame.java

import java.awt.*;
import java.awt.event.*;

public class SnakeFrame
{
 public static void main(String[] args){
  new SnakeWindow("Snake").launch();
 }
}

class SnakeWindow extends Frame
{
 public static final int WINDOW_W = 800;
 public static final int WINDOW_H = 600;
 public static final int UNIT_SIZE = 20;
 public static final int SPEED = 1000;//刷新速度

 //private Snake snake = null;
 //private Bean bean = null;

 public SnakeWindow(String s){
  super(s);
 }

 public void launch(){
  setLocation(100,100);
  setSize(WINDOW_W,WINDOW_H);
  setBackground(Color.GRAY);
  addWindowListener(new WindowAdapter(){
   public void windowClosing (WindowEvent e){
    System.exit(0);
   }
  });
  addKeyListener(new KeyMonitor());
  setVisible(true);

  new Thread(new PaintThread()).start();
 }

 public void paint(Graphics g){
  Color c = g.getColor();
  g.setColor(Color.DARK_GRAY);
  for(int i = 1; i < WINDOW_H/UNIT_SIZE ; i++) {
   g.drawLine(0,UNIT_SIZE * i,WINDOW_W ,UNIT_SIZE * i);
  }
  for (int i = 1; i < WINDOW_W/UNIT_SIZE ; i++ )
  {
   g.drawLine(UNIT_SIZE * i, 0, UNIT_SIZE * i, WINDOW_H);
  }
  g.setColor(c);
 }

 class KeyMonitor extends KeyAdapter
 {
  public void keyPressed (KeyEvent e){
   //snake.keyPressed(e);
  }
 }
 
 class PaintThread implements Runnable
 {

  repaint();
  public void run() {
   while(true){
    repaint();
    try{
     Thread.sleep(SPEED);
    }catch (InterruptedException e){
     e.printStackTrace();
    }
   }
  }

 }
}

 

V0.2:这个版本里先把比较容易实现的豆类加入进去,另外,为了培养一个良好的习惯,从这个版本开始加入各种注释,有些地方有些失误,给private 也加上了文档注释

在实现豆类的时候,发现用坐标产生一个豆并不是特别方便,因为有可能产生在界面的两个格子之间,所以我改换x,y为豆所在格子的行列,row、column

比较复杂的是产生新豆方法newBean(),这里需要添加一个随机数产生器,用来随机产生新豆的位置,同时还要判断新位置是否为空,只有空位置才能添加新豆。若是一时不好实现,我们可以暂时先空着,仅仅声明该方法。

根据程序分析设计中的豆类描述,写好豆类之后,再在主类中添加豆类对象,修改paint方法,加入豆类的draw方法。具体代码如下:

SnakeFrame.java

import java.awt.*;
import java.awt.event.*;

public class SnakeFrame
{
 public static void main(String[] args){
  new SnakeWindow("Snake").launch();
 }
}

class SnakeWindow extends Frame
{
 /**
  * 窗口宽度
  */
 public static final int WINDOW_W = 800;
 /**
  * 窗口高度
  */
 public static final int WINDOW_H = 600;
 /**
  * 正方形单元格边长
  */
 public static final int UNIT_SIZE = 20;
 /**
  * 界面行数
  */
 public static final int ROWS = WINDOW_H/UNIT_SIZE;
 /**
  * 界面列数
  */
 public static final int COLUMNS = WINDOW_W/UNIT_SIZE;
 /**
  * 界面每隔SPEED毫秒刷新一次
  */
 public static final int SPEED = 1000;//刷新速度

 //private Snake snake = null;
 private Bean bean = Bean.newBean();
 
 /**
  * 构造方法
  * @param s:标题栏名称
  */
 public SnakeWindow(String s){
  super(s);
 }

 /**
  * 窗口初始化
  */
 public void launch(){
  setLocation(100,100);
  setSize(WINDOW_W,WINDOW_H);
  setBackground(Color.GRAY);
  addWindowListener(new WindowAdapter(){
   public void windowClosing (WindowEvent e){
    System.exit(0);
   }
  });
  addKeyListener(new KeyMonitor());
  setVisible(true);

  new Thread(new PaintThread()).start();
 }

 /**
  * 窗口绘制方法
  */
 public void paint(Graphics g){
  Color c = g.getColor();
  g.setColor(Color.DARK_GRAY);
  for(int i = 1; i < WINDOW_H/UNIT_SIZE ; i++) {
   g.drawLine(0,UNIT_SIZE * i,WINDOW_W ,UNIT_SIZE * i);
  }
  for (int i = 1; i < WINDOW_W/UNIT_SIZE ; i++ )
  {
   g.drawLine(UNIT_SIZE * i, 0, UNIT_SIZE * i, WINDOW_H);
  }
  bean.draw(g);
  g.setColor(c);
 }

 /**
  * 键盘事件监听器类
  */
 class KeyMonitor extends KeyAdapter
 {
  /**
   * 键盘按下时调用该方法
   * @param e:键盘事件
   */
  public void keyPressed (KeyEvent e){
   //snake.keyPressed(e);
  }
 }
 
 /**
  * 界面刷新线程类
  */
 class PaintThread implements Runnable
 {

  repaint();
  public void run() {
   while(true){
    repaint();
    try{
     Thread.sleep(SPEED);
    }catch (InterruptedException e){
     e.printStackTrace();
    }
   }
  }

 }
}

Bean.java

import java.awt.*;
import java.util.*;

/**
 * 豆类
 */
public class Bean
{
 /**
  * 豆子的直径
  */
 public static final int SIZE = 20;
//豆横坐标

 private int row = 0;
 
 // 豆纵坐标
 private int column = 0;
 /**
  * 随机数产生器
  */
 static Random r = new Random();

 /*
  * 私有的构造方法,不许别的类调用
  */
 private Bean(int col, int row){
  this.row = row;
  this.column = col;
 }

 /**
  * 豆的绘制方法
  */
 public void draw(Graphics g){
  Color c = g.getColor();
  g.setColor(Color.GREEN);
  g.fillOval(column * SnakeWindow.UNIT_SIZE, row * SnakeWindow.UNIT_SIZE, SIZE, SIZE);
  g.setColor(c);
 }

 /**
  * 配合eat方法完成检测
  */
 public Rectangle getRectangle(){
  return new Rectangle(column * SnakeWindow.UNIT_SIZE, row * SnakeWindow.UNIT_SIZE, SIZE, SIZE);
 }
 
 /**
  * 静态方法,用来产生一个新豆
  */
 public static Bean newBean(){
  Bean b = new Bean(r.nextInt(SnakeWindow.COLUMNS), r.nextInt(SnakeWindow.ROWS));
  //缺省判断逻辑,该位置是否为空
  return b;
 }
}

 

V0.3:在这个版本中将蛇类添加进去

蛇类稍微有些麻烦,我们可以先写出一个静止不动的蛇,其他动态的方法实现暂时为空。实现之后再写move方法动起来,再写keyPressed方法控制方向,再之后写eat方法实现吃豆,再之后则是碰撞检测,撞墙死和撞自己死。写完方向控制之后的代码如下:

SnakeFrame.java

import java.awt.*;
import java.awt.event.*;

public class SnakeFrame
{
 public static void main(String[] args){
  new SnakeWindow("Snake").launch();
 }
}

class SnakeWindow extends Frame
{
 /**
  * 窗口宽度
  */
 public static final int WINDOW_W = 800;
 /**
  * 窗口高度
  */
 public static final int WINDOW_H = 600;
 /**
  * 正方形单元格边长
  */
 public static final int UNIT_SIZE = 20;
 /**
  * 界面行数
  */
 public static final int ROWS = WINDOW_H/UNIT_SIZE;
 /**
  * 界面列数
  */
 public static final int COLUMNS = WINDOW_W/UNIT_SIZE;
 /**
  * 界面每隔SPEED毫秒刷新一次
  */
 public static final int SPEED = 500;//刷新速度
 /**
  * 蛇类对象
  */
 private Snake snake = new Snake();
 /**
  * 豆类对象
  */
 private Bean bean = Bean.newBean();
 
 /**
  * 构造方法
  * @param s:标题栏名称
  */
 public SnakeWindow(String s){
  super(s);
 }

 /**
  * 窗口初始化
  */
 public void launch(){
  setLocation(100,100);
  setSize(WINDOW_W,WINDOW_H);
  setBackground(Color.GRAY);
  addWindowListener(new WindowAdapter(){
   public void windowClosing (WindowEvent e){
    System.exit(0);
   }
  });
  addKeyListener(new KeyMonitor());
  setVisible(true);

  new Thread(new PaintThread()).start();
 }

 /**
  * 窗口绘制方法
  */
 public void paint(Graphics g){
  Color c = g.getColor();
  g.setColor(Color.DARK_GRAY);
  for(int i = 1; i < WINDOW_H/UNIT_SIZE ; i++) {
   g.drawLine(0,UNIT_SIZE * i,WINDOW_W ,UNIT_SIZE * i);
  }
  for (int i = 1; i < WINDOW_W/UNIT_SIZE ; i++ )
  {
   g.drawLine(UNIT_SIZE * i, 0, UNIT_SIZE * i, WINDOW_H);
  }
  snake.draw(g);
  bean.draw(g);
  g.setColor(c);
 }

 /**
  * 键盘事件监听器类
  */
 class KeyMonitor extends KeyAdapter
 {
  /**
   * 键盘按下时调用该方法
   * @param e:键盘事件
   */
  public void keyPressed (KeyEvent e){
   snake.keyPressed(e);
  }
 }
 
 /**
  * 界面刷新线程类
  */
 class PaintThread implements Runnable
 {
  public void run() {
   while(true){
    repaint();
    try{
     Thread.sleep(SPEED);
    }catch (InterruptedException e){
     e.printStackTrace();
    }
   }
  }
 }
}

Snake.java

import java.awt.*;
import java.awt.event.*;
import java.util.*;

public class Snake
{
 /**
  * 盛放组成蛇的各个节点
  */
 public LinkedList<Node> nodeList = new LinkedList<Node>();
 /**
  * 蛇头行进的方向
  */
 private Direction direction = Direction.Left;

 /**
  * 方向枚举类型
  */
 public enum Direction {Up,Down,Left,Right}

 /**
  * 构造方法
  */
 public Snake(){
  nodeList.addFirst(new Node(19,14));
 }

 /**
  * 自身绘制
  */
 public void draw(Graphics g){
  move();

  Color c = g.getColor();
  g.setColor(Color.GREEN);
  for(int i = 0; i < nodeList.size(); i++){
   Node n = nodeList.get(i);
   n.draw(g);
  }
  g.setColor(c);
 }

 /**
  * 根据方向移动
  */
 public void move() {
  switch(direction){
  case Up :
   nodeList.addFirst(new Node(nodeList.getFirst().getColumn(), nodeList.getFirst().getRow() - 1));
   break;
  case Down :
   nodeList.addFirst(new Node(nodeList.getFirst().getColumn(), nodeList.getFirst().getRow() + 1));
   break;
  case Left :
   nodeList.addFirst(new Node(nodeList.getFirst().getColumn() - 1, nodeList.getFirst().getRow()));
   break;
  case Right :
   nodeList.addFirst(new Node(nodeList.getFirst().getColumn() + 1, nodeList.getFirst().getRow()));
   break;
  }
  nodeList.removeLast();
 }

 public void eat() {
  //
 }

 public void addNode() {
  //
 }

 public void collide () {
  //
 }

 /**
  * 方向键按键事件的处理,改变移动方向
  */
 public void keyPressed (KeyEvent e) {
  int keyCode = e.getKeyCode();
  switch(keyCode){
  case KeyEvent.VK_UP :
   direction = Direction.Up;
   break;
  case KeyEvent.VK_DOWN :
   direction = Direction.Down;
   break;
  case KeyEvent.VK_LEFT :
   direction = Direction.Left;
   break;
  case KeyEvent.VK_RIGHT :
   direction = Direction.Right;
   break;
  }
 }

 /**
  * 节点类
  */
 class Node
 {
  /**
   * 豆子列坐标
   */
  private int row = 0;
  /**
   * 豆子行坐标
   */
  private int column = 0;
  /**
   * 豆子行坐标
   */
  public static final int SIZE = SnakeWindow.UNIT_SIZE;

  /**
   * 私有的构造方法,不许别的类调用
   */
  public Node(int col, int row){
   this.row = row;
   this.column = col;
  }

  public int getRow(){
   return row;
  }

  public int getColumn() {
   return column;
  }

  /**
   * 节点的绘制方法
   */
  public void draw(Graphics g){
   Color c = g.getColor();
   g.setColor(Color.BLACK);
   g.fillRect(column * SnakeWindow.UNIT_SIZE, row * SnakeWindow.UNIT_SIZE, SIZE, SIZE);
   g.setColor(c);
  }

  /**
   * 配合完成碰撞检测
   */
  public Rectangle getRectangle(){
   return new Rectangle(column * SnakeWindow.UNIT_SIZE, row * SnakeWindow.UNIT_SIZE, SIZE, SIZE);
  }
 }
}

Bean.java

import java.awt.*;
import java.util.*;

/**
 * 豆类
 */
public class Bean
{
 /**
  * 豆子的直径
  */
 public static final int SIZE = SnakeWindow.UNIT_SIZE;
 /**
  * 豆子行坐标
  */
 private int row = 0;
 /**
  * 豆子列坐标
  */
 private int column = 0;
 /**
  * 随机数产生器
  */
 static Random r = new Random();

 /**
  * 私有的构造方法,不许别的类调用
  */
 private Bean(int col, int row){
  this.row = row;
  this.column = col;
 }

 /**
  * 豆的绘制方法
  */
 public void draw(Graphics g){
  Color c = g.getColor();
  g.setColor(Color.GREEN);
  g.fillOval(column * SnakeWindow.UNIT_SIZE, row * SnakeWindow.UNIT_SIZE, SIZE, SIZE);
  g.setColor(c);
 }

 /**
  * 配合eat方法完成检测
  */
 public Rectangle getRectangle(){
  return new Rectangle(column * SnakeWindow.UNIT_SIZE, row * SnakeWindow.UNIT_SIZE, SIZE, SIZE);
 }
 
 /**
  * 静态方法,用来产生一个新豆
  */
 public static Bean newBean(){
  Bean b = new Bean(r.nextInt(SnakeWindow.COLUMNS), r.nextInt(SnakeWindow.ROWS));
  //缺省判断逻辑,该位置是否为空
  return b;
 }
}

暂时写到这,太长换下一篇

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值