JavaRush /Java 博客 /Random-ZH /JavaRush 上的“游戏”部分:有用的理论

JavaRush 上的“游戏”部分:有用的理论

已在 Random-ZH 群组中发布
在JavaRush 的“游戏”部分,您会发现用于编写流行计算机游戏的令人兴奋的项目。您想创建自己的流行“2048”、“工兵”、“贪吃蛇”等游戏版本吗?这很简单。我们已经将游戏编写变成了一个循序渐进的过程。章节要尝试成为一名游戏开发人员,您不必成为一名高级程序员,但仍然需要一定的 Java 知识。在这里您将找到在编写游戏时有用的信息

1. 继承

使用 JavaRush 游戏引擎涉及到使用继承。但如果你不知道它是什么怎么办?一方面,你需要了解这个主题:它是在11 级学习的。另一方面,引擎被故意设计得非常简单,因此您只需了解继承的肤浅知识就可以了。那么,什么是继承呢?简单来说,继承就是两个类之间的关系。其中一个成为父级,第二个成为子级(后继类)。在这种情况下,父类甚至可能不知道它有后代类。那些。它不会从继承类的存在中获得任何特殊的好处。但继承为后代类提供了许多优点。而且最主要的是父类的所有变量和方法都出现在子类中,就好像父类的代码被复制到了子类中一样。这并不完全正确,但为了简化对继承的理解,它就可以了。以下是一些示例,可以帮助您更好地理解继承。 例1:最简单的继承。
public class Родитель {

}
Child类使用extends关键字从Parent类继承。
public class Потомок extends Родитель {

}
示例 2:使用父类变量。
public class Родитель {

   public int age;
   public String name;
}
Child类可以使用Parent类的年龄姓名变量,就像在其中声明它们一样。
public class Потомок extends Родитель {

   public void printInfo() {

     System.out.println(name+" "+age);
   }
}
示例 3:使用父类方法。
public class Родитель {

   public int age;
   public String name;

   public getName() {
      return name;
   }
}
类可以使用类的变量和方法,就好像它们是在父类中声明的一样。在此示例中,我们使用getName () 方法。
public class Потомок extends Родитель {

   public void printInfo() {

     System.out.println(getName()+" "+age);
   }
}
从编译器的角度来看, 后代类是这样的:
public class Потомок extends Родитель {

   public int age; //  унаследованная переменная
   public String name; //  унаследованная переменная

   public getName() { //  унаследованный метод.
      return name;
  }
   public void printInfo() {

     System.out.println(getName()+" "+age);
   }
}

2. 方法重写

有时,我们从一些非常有用的父类继承了后代类以及所有变量和方法,但有些方法并不完全按照我们想要的方式工作。或者根本不是我们不想要的方式。在这种情况下该怎么办?我们可以重写我们不喜欢的方法。这样做非常简单:在我们的后代类中,我们只需声明一个与父类方法具有相同签名(标头)的方法,并在其中编写我们的代码。 示例 1:方法重写。
public class Родитель {

   public String name;

   public void setName (String nameNew) {
       name = nameNew;
  }

   public getName() {
      return name;
  }
}
printInfo() 方法将打印短语“Luke, No!!!”
public class Потомок extends Родитель {

   public void setName (String nameNew) {
       name = nameNew + ",No!!!";
  }

   public void printInfo() {

      setName("Luke");
      System.out.println( getName());
   }
}
从编译器的角度来看, 后代类是这样的:
public Потомок extends Родитель {

   public String name; //  унаследованная переменная

   public void setName (String nameNew) { //  Переопределенный метод взамен унаследованного

       name = nameNew + ", No!!!";
   }
   public getName() { //  унаследованный метод.

      return name;
   }
   public void printInfo() {

     setName("Luke");
     System.out.println(getName());
   }
}
示例 2:继承(和方法重写)的一点魔力。
public class Родитель {

   public getName() {
      return "Luke";
  }
   public void printInfo() {

     System.out.println(getName());
   }
}
public class Потомок extends Родитель {

   public getName() {
      return "I'm your father, Luke";
  }
}
在此示例中:如果在后代类中未重写某个方法printInfo(来自父类),则当在后代类的对象上调用此方法时,将调用其方法getName(),而不是getName()父类。
Родитель parent = new Родитель ();
parent.printnInfo();
此代码在屏幕上显示“Luke”字样。
Потомок child = new Потомок ();
child.printnInfo();
此代码显示铭文“我是你的父亲,卢克;”
从编译器的角度来看, 后代类是这样的:
public class Потомок extends Родитель {

   public getName() {
      return "I'm your father, Luke";
   }
   public void printInfo() {

     System.out.println(getName());
   }
}

3. 列表

如果您还没有接触过列表,这里有一个快速入门知识。您可以找到有关JavaRush 课程 6-7 级的完整信息。 列表与数组有很多共同点:
  • 可以存储大量某种类型的数据;
  • 允许您通过索引/编号检索元素;
  • 元素索引从 0 开始。
列表的优点: 与数组不同,列表可以动态改变大小。创建后,列表的大小立即为 0。当您向列表中添加元素时,其大小会增加。创建列表的示例:
ArrayList<String> myList = new ArrayList<String>(); // создание нового списка типа ArrayList
尖括号中的值是列表可以存储的数据类型。以下是一些处理列表的方法:
代码 简要描述代码的作用
ArrayList<String> list = new ArrayList<String>(); 创建新的字符串列表
list.add("name"); 将一个元素添加到列表末尾
list.add(0, "name"); 将一个元素添加到列表的开头
String name = list.get(5); 通过索引获取元素
list.set(5, "new name"); 通过索引更改元素
int count = list.size(); 获取列表中的元素数量
list.remove(4); 从列表中删除项目
您可以从这些文章中了解有关列表的更多信息:
  1. 数组列表类
  2. 在图片中使用 ArrayList
  3. 从 ArrayList 中删除一个元素

4. 数组

什么是矩阵?矩阵无非是一个可以填充数据的矩形表格。换句话说,它是一个二维数组。您可能知道,Java 中的数组是对象。标准的一维数组类型int如下所示:
int [] array = {12, 32, 43, 54, 15, 36, 67, 28};
让我们直观地想象一下:
0 1 2 3 4 5 6 7
12 32 43 54 15 36 67 28
最上面一行表示单元格地址。也就是说,要获取数字 67,您需要访问索引为 6 的数组元素:
int number = array[6];
这里一切都很简单。二维数组是一维数组的数组。如果这是您第一次听说这个,请停下来在脑海中想象一下。二维数组看起来像这样:
0 一维数组 一维数组
1 一维数组
2 一维数组
3 一维数组
4 一维数组
5 一维数组
6 一维数组
7 一维数组
在代码中:
int [][] matrix = {
{65, 99, 87, 90, 156, 75, 98, 78}, {76, 15, 76, 91, 66, 90, 15, 77}, {65, 96, 17, 25, 36, 75, 54, 78}, {59, 45, 68, 14, 57, 1, 9, 63}, {81, 74, 47, 52, 42, 785, 56, 96}, {66, 74, 58, 16, 98, 140, 55, 77}, {120, 99, 13, 90, 78, 98, 14, 78}, {20, 18, 74, 91, 96, 104, 105, 77} }
0 0 1 2 3 4 5 6 7
65 99 87 90 156 75 98 78
1 0 1 2 3 4 5 6 7
76 15 76 91 66 90 15 77
2 0 1 2 3 4 5 6 7
65 96 17 号 25 36 75 54 78
3 0 1 2 3 4 5 6 7
59 45 68 14 57 1 9 63
4 0 1 2 3 4 5 6 7
81 74 47 52 42 第785章 56 96
5 0 1 2 3 4 5 6 7
66 74 58 16 98 140 55 77
6 0 1 2 3 4 5 6 7
120 99 13 90 78 98 14 78
7 0 1 2 3 4 5 6 7
20 18 74 91 96 104 105 77
要获取值 47,您需要访问 [4][2] 处的矩阵元素。
int number = matrix[4][2];
如果您注意到,矩阵坐标与经典直角坐标系(笛卡尔坐标系)不同。访问矩阵时,首先指定 y,然后指定 x,而在数学中,通常先指定 x(x, y)。您可能会问自己,“为什么不反转您想象中的矩阵并通过 (x, y) 以通常的方式访问元素呢?这不会改变矩阵的内容。” 是的,什么都不会改变。但在编程世界中,习惯上以“先是 y,然后是 x”的形式来引用矩阵。这必须被视为理所当然。现在我们来谈谈将矩阵投影到我们的引擎(类Game)上。如您所知,引擎有许多方法可以改变给定坐标处的运动场单元格。例如,setCellValue(int x, int y, String value). 它将坐标 (x, y) 的某个单元格设置为值value。正如您所注意到的,该方法首先精确地取 x,就像在经典坐标系中一样。其余引擎方法的工作方式类似。在开发游戏时,经常需要在屏幕上重现矩阵的状态。这个怎么做?首先,在循环中,您需要迭代矩阵的所有元素。其次,对于它们中的每一个,调用一个方法来显示反转坐标。例子:
private void drawScene() {
    for (int i = 0; i < matrix.length; i++) {
        for (int j = 0; j < matrix[i].length; j++) {
            setCellValue(j, i, String.valueOf(matrix[i][j]));
        }
    }
}
当然,反转有两个方向。setCellValue您可以将 (i, j) 传递给方法,但同时从矩阵中取出元素 [j][i] 。反转可能看起来有点困难,但要记住这一点。而且,如果出现任何问题,值得用笔拿起一张纸,绘制一个矩阵并重现正在发生的过程。

5. 随机数

如何使用随机数生成器? 该类Game定义了一个方法getRandomNumber(int)。在底层,它使用Randomjava.util 包中的类,但这并没有改变使用随机数生成器的原理。getRandomNumber(int)采用一个整数作为参数。该数字将是生成器可以返回的上限。下限为0。 重要的! 生成器永远不会返回上限数字。例如,如果getRandomNumber(3)随机调用,它可以返回 0、1、2。如您所见,它不能返回 3。生成器的使用非常简单,但在许多情况下非常有效。 您需要在一定限制内获得一个随机数: 假设您需要一些三位数(100..999)。正如您所知,返回的最小数字是 0。因此,您需要在其上添加 100。但在这种情况下,您需要注意不要超过上限。要获得 999 作为最大随机值,您应该getRandomNumber(int)使用参数 1000 来调用该方法。但是我们记得随后添加了 100:这意味着上限应该降低 100。也就是说,获取随机三位数将如下所示:
int number = 100 + getRandomNumber(900);
但为了简化这样的过程,引擎提供了一种方法getRandomNumber(int, int),该方法将返回的最小数字作为第一个参数。使用此方法,可以重写前面的示例:
int number = getRandomNumber(100, 1000);
可以使用随机数来获取随机数组元素:
String [] names = {"Andrey", "Валентин", "Сергей"};
String randomName = names[getRandomNumber(names.length)]
以一定的概率触发某些事件。 一个人的早晨是根据可能的情况开始的:睡过头——50%;准时起床——40%;比预期早起一个小时——10%。想象一下您正在编写一个人类早晨模拟器。你需要以一定的概率触发事件。为此,您再次需要使用随机数生成器。实现可能有所不同,但最简单的应该遵循以下算法:
  1. 我们设置需要生成的数量的限制;
  2. 生成一个随机数;
  3. 我们处理结果数字。
因此,在本例中,限制将为 10。让我们调用该方法getRandomNumber(10)并分析它可以返回给我们什么。它可以返回 10 个数字(从 0 到 9),每个数字的概率相同 - 10%。现在我们需要结合所有可能的结果并将它们与我们可能发生的事件相匹配。可能有很多组合,具体取决于您的想象力,但最明显的声音是:“如果随机数在 [0..4] 范围内 - 如果数字在 [5..8] 范围内,则称该事件为“睡过头” ] - “准时起床”,只有当数字是 9 时,那么“我比预期早起一个小时。” 一切都很简单:[0..4]内有5个数字,每个数字返回的概率都是10%,总共就是50%;[5..8]中有4个数字,9是唯一出现概率为10%的数字。在代码中,整个巧妙的设计看起来更加简单:
int randomNumber = getRandomNumber(10);
if (randomNumber < 5) {
    System.out.println("Проспал ");
} else if (randomNumber < 9) {
    System.out.println("Встал вовремя ");
} else {
    System.out.println("Встал на час раньше положенного ");
}
一般来说,使用随机数有很多选择。这一切仅取决于您的想象力。但如果您需要重复获得某些结果,那么它们的使用最为有效。那么这个结果就会和之前的不一样。当然,有一定的概率。就这样!如果您想了解有关游戏部分的更多信息,这里有一些有用的文档可以提供帮助:
评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION