CodeGym /Java 博客 /随机的 /CodeGym 上的游戏部分:有用的理论
John Squirrels
第 41 级
San Francisco

CodeGym 上的游戏部分:有用的理论

已在 随机的 群组中发布
在CodeGym 的“游戏”部分,您会发现涉及编写流行计算机游戏的激动人心的项目。想要创建您自己的流行游戏 2048、扫雷、贪吃蛇和其他游戏的版本吗?这很简单。我们已经将游戏编写变成了一个循序渐进的过程。CodeGym 上的“游戏”部分:有用的理论 - 1要测试您作为游戏开发人员的能力,您不必是高级程序员,但需要具备一套特定的 Java 知识。在这里您会找到对游戏编写有用的信息

1.继承

使用 CodeGym 游戏引擎涉及使用继承。但是,如果您不知道那是什么怎么办?一方面,你需要理解这个主题:它在第 11 级学习过. 另一方面,该引擎被特别设计得非常简单,因此您可以通过肤浅的继承知识逃脱。那么什么是继承呢?简单来说,继承就是两个类之间的一种关系。其中一个成为父母,另一个成为孩子(后代)。而且,父类甚至可能不知道自己有后代。换句话说,它不会因为有后代而获得任何特别的优势。但是继承给了后代很多优势。最重要的是,父类的所有变量和方法都出现在子类中,就好像父类的代码被复制到子类中一样。这不是一个完全准确的描述,但足以简化对继承的理解。 示例 1:最简单的继承。

public class Parent {

}
Child类使用extends关键字继承Parent类。

public class Child extends Parent {

}
示例 2:使用父类的变量。

public class Parent {

   public int age;
   public String name;
}
Child类可以使用 Parent 类的agename变量,就好像它们是在Parent类中声明的一样。

public class Child extends Parent {

   public void printInfo() {

     System.out.println(name+" "+age);
   }
}
示例 3:使用父类的方法。

public class Parent {

   public int age;
   public String name;

   public getName() {
      return name;
  }
}
Child类可以像在 Child 类中声明的那样使用Parent类的变量和方法。在此示例中,我们使用getName()方法。

public class Child extends Parent {

   public void printInfo() {

     System.out.println(getName()+" "+age);
   }
}
这就是Child类在编译器看来的样子:

public class Child extends Parent{

   public int age;  // Inherited variable
   public String name;  // Inherited variable

   public getName() {  // Inherited method.
      return name;
  }
   public void printInfo() {

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

2.覆盖方法

有时在某些情况下,我们让我们的子类继承一些非常有用的父类,以及它的所有变量和方法,但有些方法并不能完全按照我们希望的方式工作。或者根本不是我们想要的那样。在这种情况下我们能做什么?我们可以覆盖我们不喜欢的方法。这很容易做到:在我们的 Child 类中,我们只需声明一个与 Parent 类中的方法具有相同签名的方法,然后我们在其中编写自己的代码。 示例 1:覆盖方法。

public class Parent {

   public String name;

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

   public getName() {
      return name;
  }
}
printInfo() 方法将显示“Luke, No!!!”

public class Child extends Parent{

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

   public void printInfo() {
      setName("Luke");
      System.out.println(getName());
   }
}
这就是Child类在编译器看来的样子:

public Child extends Parent {

   public String name;  // Inherited variable

   public void setName(String nameNew)  // Overridden method instead of the inherited method {

       name = nameNew + ", No!!!";
   }
   public getName() {  // Inherited method.

      return name;
   }
   public void printInfo() {

     setName("Luke");
     System.out.println( getName());
   }
}
示例 2:一些继承魔术(和方法覆盖)。

public class Parent {

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

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

public class Child extends Parent {

   public getName() {
      return "Luke, I am your father";
  }
}
在此示例中,如果printInfo方法(来自 Parent 类)未在 Child 类中重写,则在 Child 对象上调用此方法时,getName()将调用其方法而不是 Parent 类的getName()方法。

Parent parent = new Parent ();
parent.printnInfo();
此代码在屏幕上显示“Luke” 。

Child child = new Child ();
child.printnInfo();
此代码在屏幕上显示“卢克,我是你父亲” 。
这就是Child类在编译器看来的样子:

public class Child extends Parent {

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

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

3. 清单

如果你还没有接触过列表(List),这里有一个简单的概述。您可以在CodeGym 课程的第 6-7级中找到完整信息。 列表与数组有很多共同点:
  • 您可以存储大量特定类型的数据;
  • 他们让你通过他们的索引获取项目;
  • 元素索引从 0 开始。
列表的好处: 与数组不同,列表可以动态改变大小。创建列表时,其大小为 0。当您向列表中添加项目时,其大小会增加。以下是创建列表的示例:

ArrayList<String> myList = new ArrayList<String>(); // Create a new 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,就像在经典坐标系中一样。引擎的其他方法以类似的方式工作。在开发游戏时,经常需要在屏幕上重现矩阵的状态。我们该怎么做?首先,您需要循环遍历所有矩阵元素。其次,使用 REVERSED 坐标为它们中的每一个调用 display 方法。例如:

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]));
        }
    }
}
自然地,逆转是双向的。您可以将 (i, j) 传递给该setCellValue方法,同时从矩阵中获取元素 [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 = {"Sarah", "Val", "Sergey"};
String randomName = names[getRandomNumber(names.length)]
以一定的概率生成某些事件。 对于人类来说,早晨从几个可能的场景开始:睡过头——50% 的可能性;准时起床——40%的机会;早起一小时——10% 的几率。想象一下,您正在编写一个早晨结果生成器。您需要以一定的概率生成事件。为此,您再次需要使用随机数生成器。不同的实现是可能的,但最简单的应该基于以下算法:
  1. 设置用于生成数字的限制;
  2. 生成一个随机数;
  3. 处理得到的数字。
在这种情况下,最大值为 10。调用getRandomNumber(10)方法并分析它我们可以返回。它可以返回 10 个数字(从 0 到 9),每个数字都有相同的概率——10%。现在我们需要组合所有可能的结果并将它们映射到我们可能的事件。您可能会想出很多可能的组合,但最明显的是:“如果随机数在 [0..4] 范围内,我们就会发生“睡过头”事件;如果该数字在 [5] 范围内..8],我们有“准时起床”事件;如果数字是 9,那么我们有“提前一小时起床”事件。这一切都非常简单。范围内有 5 个数字 [0 ..4],每个都可能以 10% 的概率返回,总共 50%;[5..8] 范围内有 4 个数字,好吧,9 只是一个出现的数字概率为 10%。

int randomNumber = getRandomNumber(10);
if (randomNumber < 5) {
    System.out.println("Overslept");
} else if (randomNumber < 9) {
    System.out.println("Woke up on time");
} else {
    System.out.println("Woke up an hour early");
}
一般来说,有很多方法可以使用随机数。你只受限于你的想象力。但是,如果您需要反复获得某些结果,则最有效地使用它们。那么新的结果将与之前的结果不同。当然,有一定的可能性。目前为止就这样了!如果您想了解有关“游戏”部分的更多信息,这里有一些有用的文档可以提供帮助:
评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION