• 用Java写一个贪吃蛇游戏


    目录

    创建窗体

    创建游戏棋盘

    创建蛇的节点

    创建蛇身

    让蛇移动

    添加键盘监听

    添加边界处理

    把食物绘制到棋盘上

    吃食物


    创建窗体

    创建一个MainFrame类继承JFrame,表示主窗体。

    1. public class MainFrame extends JFrame {
    2. //创建窗体对象时,初始化船体参数
    3. public MainFrame(){
    4. initFrame();
    5. }
    6. }

    MainFrame类中写一个initFrame方法,初始化窗体参数

    1. //1.初始化窗体参数
    2. private void initFrame() {
    3. //设置窗体标题
    4. setTitle("黑马贪吃蛇");
    5. //设置窗体大小
    6. setSize(610, 640);
    7. //设置窗体位置
    8. setLocation(400, 400);
    9. //设置窗体大小不能改变
    10. setResizable(false);
    11. //设置窗体关闭按钮的作用,是正常退出
    12. setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    13. }

    在MainFrame中添加一个main方法,创建窗体并运行,就可以看到窗体了

    1. //主方法
    2. public static void main(String[] args) {
    3. //创建窗体,并显示在屏幕上
    4. new MainFrame().setVisible(true);
    5. }

    创建游戏棋盘

    在JFrame类中写一个initGamePanel方法,初始化游戏棋盘

    1. //初始化游戏面板
    2. private void initGamePanel() {
    3. JPanel jPanel = new JPanel() {
    4. //paint是用来绘制面板中的内容
    5. @Override
    6. public void paint(Graphics g) {
    7. //设置画笔颜色
    8. g.setColor(Color.black); //设置画笔颜色是黑色
    9. //绘制40条横线(起点横坐标,起点纵坐标,终点横坐标,终点纵坐标)
    10. for(int i=1;i<=40;i++){
    11. g.drawLine(0,15*i,600,15*i);
    12. }
    13. //绘制40条竖线
    14. for (int i=1;i<=40;i++){
    15. g.drawLine(15*i,0,15*i,600);
    16. }
    17. }
    18. };
    19. add(jPanel);
    20. }

    创建蛇的节点

    创建一个Node类表示节点,一条蛇有若干个节点组成,每一个节点其实就是一个小方格,我们用行和列来定义节点在棋盘中的位置。

    1. public class Node {
    2. private int x; //横坐标
    3. private int y; //纵坐标
    4. public int getX() {
    5. return x;
    6. }
    7. public void setX(int x) {
    8. this.x = x;
    9. }
    10. public int getY() {
    11. return y;
    12. }
    13. public void setY(int y) {
    14. this.y = y;
    15. }
    16. }

    创建蛇身

    创建Snake类表示蛇,一条蛇有多个节点使用LinkedList集合存储Node节点,蛇出生的时候 有3个节点。

    1. public class Snake {
    2. //body
    3. private LinkedList<Node> body;
    4. //创建蛇对象时,初始化蛇身
    5. public Snake() {
    6. initSnake();
    7. }
    8. //初始化蛇身 3个节点
    9. public void initSnake(){
    10. //创建蛇的躯体
    11. body=new LinkedList<>();
    12. //给蛇添加3个节点,在棋盘的中心位置横向排列
    13. body.add(new Node(20,20));
    14. body.add(new Node(21,20));
    15. body.add(new Node(22,20));
    16. }
    17. //获取蛇蛇身
    18. public LinkedList<Node> getBody(){
    19. return body;
    20. }
    21. }

    把蛇绘制到棋盘上

    在MainFrame中添加一个创建Snake的成员变量,表示窗体中有一条蛇

    1. public class MainFrame extends JFrame {
    2. //定义成员变量
    3. private Snake snake=new Snake();
    4. ....
    5. }

    在绘制棋盘的paint方法中,添加下面的代码绘制把蛇绘制到棋盘上

    1. //绘制横线
    2. ...
    3. //绘制竖线
    4. ...
    5. //绘制蛇,根据每一个节点的坐标在棋盘上绘制矩形
    6. for (Node node : snake.getBody()) {
    7. //每一个节点的宽度和高度是15
    8. g.fillRect(node.getX()*15,node.getY()*15,15,15);
    9. }

     再次运行,就可以看到有一条蛇静静的躺在棋盘中间了

    让蛇移动

    定义一个枚举类型,表示运动的4个方向

    1. public enum Direction {
    2. UP,DOWN,LEFT,RIGHT
    3. }

    在Snake类中定义一个移动方向的变量成员变量,和move方法。

    1. public class Snake{
    2. //蛇头运动的方向
    3. private Direction direction;
    4. //移动的方法: 每次移动在蛇头运动方向添加一个节点,再删除最后一个节点
    5. public void move(){
    6. //获取蛇头的节点
    7. Node head = body.getFirst();
    8. //新的蛇头节点
    9. Node newHead=null;
    10. //检查移动的方向
    11. switch (direction){
    12. //如果向左移动
    13. case LEFT:
    14. //创建一个新的蛇头节点
    15. newHead=new Node(head.getX()-1,head.getY());
    16. //把心得蛇头节点添加到body的第一个元素
    17. body.addFirst(newHead);
    18. //删除蛇尾
    19. body.removeLast();
    20. break;
    21. case RIGHT:
    22. //创建一个新的蛇头节点
    23. newHead=new Node(head.getX()-1,head.getY());
    24. //把心得蛇头节点添加到body的第一个元素
    25. body.addFirst(newHead);
    26. //删除蛇尾
    27. body.removeLast();
    28. break;
    29. case UP:
    30. //创建一个新的蛇头节点
    31. newHead=new Node(head.getX(),head.getY()-1);
    32. //把心得蛇头节点添加到body的第一个元素
    33. body.addFirst(newHead);
    34. //删除蛇尾
    35. body.removeLast();
    36. break;
    37. case DOWN:
    38. //创建一个新的蛇头节点
    39. newHead=new Node(head.getX(),head.getY()+1);
    40. //把心得蛇头节点添加到body的第一个元素
    41. body.addFirst(newHead);
    42. //删除蛇尾
    43. body.removeLast();
    44. break;
    45. }
    46. }
    47. }

     在MainFrame类中,创建一个定时器每100毫秒,重绘游戏棋盘

    1. public class MainFrame extends JFrame {
    2. ...
    3. //游戏棋盘面板
    4. JPanel jPanel=null;
    5. //定义定时器
    6. private Timer timer;
    7. public MainFrame() throws HeadlessException {
    8. //初始化窗体参数
    9. initFrame();
    10. //初始化窗体中的游戏面板
    11. initGamePanel();
    12. //初始化定时器
    13. initTimer();
    14. }
    15. //2.初始化游戏棋盘
    16. private void initGamePanel() {
    17. jPanel = new JPanel() {
    18. //paint是用来绘制面板中的内容
    19. @Override
    20. public void paint(Graphics g) {
    21. //每次重绘时清空面板中的内容
    22. g.clearRect(0,0,getWidth(),getHeight());
    23. ....
    24. }
    25. };
    26. add(jPanel);
    27. }
    28. //3.初始化定时器
    29. private void initTimer() {
    30. TimerTask task=new TimerTask() {
    31. @Override
    32. public void run() {
    33. //调用蛇移动的方法
    34. snake.move();
    35. //每次移动重绘游戏棋盘,会自动调用jPanel的paint方法
    36. jPanel.repaint();
    37. }
    38. };
    39. timer=new Timer();
    40. timer.scheduleAtFixedRate(task,0,100);
    41. }
    42. }

    添加键盘监听

    在MainFrame类中,添加一个setKeyListener的方法,监听上下左右四个键

    1. public class MainFrame extends JFrame {
    2. ...
    3. public MainFrame() throws HeadlessException {
    4. ...
    5. //添加键盘监听
    6. setkeyListener();
    7. }
    8. //添加键盘监听
    9. private void setkeyListener() {
    10. //对上下左右键进行监听
    11. addKeyListener(new KeyAdapter() {
    12. @Override
    13. public void keyPressed(KeyEvent e) {
    14. switch (e.getKeyCode()){
    15. //按下上键
    16. case KeyEvent.VK_UP:
    17. //蛇头方向改为上
    18. snake.setDirection(Direction.UP);
    19. break;
    20. //按下下键
    21. case KeyEvent.VK_DOWN:
    22. //蛇头方向改为下
    23. snake.setDirection(Direction.DOWN);
    24. break;
    25. //按下左键
    26. case KeyEvent.VK_LEFT:
    27. //蛇头方向改为左
    28. snake.setDirection(Direction.LEFT);
    29. break;
    30. //按下右键
    31. case KeyEvent.VK_RIGHT:
    32. //蛇头方向改为右
    33. snake.setDirection(Direction.RIGHT);
    34. break;
    35. }
    36. }
    37. });
    38. }
    39. }

    到此蛇就可以跟随键盘移动了

    添加边界处理

    当蛇移动到边界处就游戏结束,把标记改为false

    1. public class Snake{
    2. ...
    3. //定义一个标记true表示蛇是活的,可以运动
    4. private boolean isLive=true;
    5. //检查蛇是否碰壁
    6. private void checkOver() {
    7. //获取蛇头
    8. Node head = body.getFirst();
    9. int x=head.getX();
    10. int y=head.getY();
    11. if(x<0||y<0||x>=40||y>=40){
    12. isLive=false;
    13. }
    14. }
    15. }

    在定时器中调用checkOver()方法

    1. //3.初始化定时器
    2. private void initTimer() {
    3. TimerTask task=new TimerTask() {
    4. @Override
    5. public void run() {
    6. //移动
    7. snake.move();
    8. //检查是否碰壁
    9. snake.checkOver();
    10. }
    11. };
    12. timer=new Timer();
    13. timer.scheduleAtFixedRate(task,0,100);
    14. }

    把食物绘制到棋盘上

    创建一个Food类表示食物,其实食物也是一个节点,所以让Food继承Node

    1. public class Food extends Node {
    2. //创建食物的时候,随机产生一个位置
    3. public Food() {
    4. reset();
    5. }
    6. //随产生位置
    7. public void reset(){
    8. //随机生成食物的坐标
    9. Random r=new Random();
    10. setX(r.nextInt(40));
    11. setY(r.nextInt(40));
    12. }
    13. }

    在MainFrame中定义一个成员Food表示食物,并把食物绘制到棋盘上

    1. public class MainFrame extends JFrame {
    2. //定义食物
    3. private Node food=new Node();
    4. public MainFrame() throws HeadlessException {
    5. //初始化窗体参数
    6. initFrame();
    7. //初始化窗体中的游戏面板
    8. initGamePanel();
    9. //初始化定时器
    10. initTimer();
    11. //添加键盘监听
    12. setkeyListener();
    13. }
    14. //2.初始化游戏棋盘
    15. private void initGamePanel() {
    16. jPanel = new JPanel() {
    17. //paint是用来绘制面板中的内容
    18. @Override
    19. public void paint(Graphics g) {
    20. //清空棋盘
    21. g.clearRect(0,0,600,600);
    22. //绘制横线、绘制竖线、绘制蛇
    23. //绘制食物
    24. g.fillRect(food.getX()*15,food.getY()*15,15,15);
    25. }
    26. };
    27. add(jPanel);
    28. }
    29. }

    吃食物

    在Snake类中添加一个eatFood方法

    1. //吃食物
    2. public void eatFood() {
    3. //获取蛇头
    4. Node head = body.getFirst();
    5. //如果蛇头和食物的位置重合,就在蛇头添加一个元素
    6. if(head.getX()==MainFrame.food.getX()
    7. &&head.getY()==MainFrame.food.getY()){
    8. //沿着蛇头运动方向创建一个节点
    9. //新的蛇头节点
    10. Node newHead=null;
    11. //检查移动的方向
    12. switch (direction){
    13. //如果向左移动
    14. case LEFT:
    15. //创建一个新的蛇头节点
    16. newHead=new Node(head.getX()-1,head.getY());
    17. //把心得蛇头节点添加到body的第一个元素
    18. body.addFirst(newHead);
    19. break;
    20. case RIGHT:
    21. //创建一个新的蛇头节点
    22. newHead=new Node(head.getX()+1,head.getY());
    23. //把心得蛇头节点添加到body的第一个元素
    24. body.addFirst(newHead);
    25. break;
    26. case UP:
    27. //创建一个新的蛇头节点
    28. newHead=new Node(head.getX(),head.getY()-1);
    29. //把心得蛇头节点添加到body的第一个元素
    30. body.addFirst(newHead);
    31. break;
    32. case DOWN:
    33. //创建一个新的蛇头节点
    34. newHead=new Node(head.getX(),head.getY()+1);
    35. //把心得蛇头节点添加到body的第一个元素
    36. body.addFirst(newHead);
    37. break;
    38. }
    39. //每次吃完食物,让食物重置
    40. MainFrame.food.reset();
    41. }
    42. }

    在定时器中调用吃食物的方法

    1. //2.初始化游戏棋盘
    2. private void initGamePanel() {
    3.     jPanel = new JPanel() {
    4.         //paint是用来绘制面板中的内容
    5.         @Override
    6.         public void paint(Graphics g) {
    7.             //清空棋盘
    8.             g.clearRect(0,0,600,600);
    9.             //绘制横线、绘制竖线、绘制蛇
    10.             //绘制食物
    11.             g.fillRect(food.getX()*15,food.getY()*15,15,15);
    12.         }
    13.     };
    14.     add(jPanel);
    15. }
  • 相关阅读:
    JAVASE语法零基础——static成员和代码块
    cmmi分为哪几个等级?
    进程同步——信号量机制(操作系统)
    离线部署uni-app,替换启动页
    9月,1Panel开源面板项目收到了这些评论
    车牌自动识别-matlab
    汽车电子 -- PCAN View 安装与使用
    【无标题】
    JavaWeb:上传文件
    谁能想到先打败程序员的不是35岁,而是.
  • 原文地址:https://blog.csdn.net/2301_76549195/article/details/134489845