简单的 AI - JavaScript(使用 jQuery 制作动画)

发布于 2024-11-09 14:19:11 字数 825 浏览 5 评论 0原文

首先,我想让你知道,作为一种爱好,我已经编程几年了(主要是基于 C 的语言、iOS 开发、网络内容等),现在我对创建一个简单的 AI(大多数是基于 C 语言、iOS 开发、网络内容等)产生了兴趣。人们从井字棋游戏开始,是的,但我有兴趣利用遗传编程的原理来制作一些东西)。我希望读者知道这一点的原因是,如果答案不是太复杂(对于孩子来说不太难理解,因为我还没有参加大学计算机科学课程),我会很感激。

这是我的目标:

术语

organsim: a CSS div
种群:一群生物(5或10个)
食物来源:另一个 CSS div

过程

  1. 生成一个种群,每个种群最初似乎都具有相同的表型属性,但技能不同(为此,速度)
  2. 生成一个食物来源(每次都相同 ) )
  3. 环境建立大约 5 秒后(步骤 1 和 2),生物体群体需要找到一种方法来竞争性地到达食物源
  4. 。只有一个生物体可以到达食物项。到达它后,环境会重置除了上次发现食物的生物体现在受益并且其速度水平可能会增加,而其他做得特别糟糕的生物体可能会变得更慢或被
  5. 终止被重复;用户可以观察群体的特征,看看哪些群体在进化上取得了成功,等等。

附加信息

如您所见,上述步骤几乎模拟了进化,但方式非常简单(与动物的现实生活情况相比,条件较少) ;现在这就是我在这里问的原因:我完全迷失了。我真的不知道从哪里开始(除了生成人口之外,我很可能可以做到这一点以及通过 jQuery 动画让它们移动)。但我现在还做不到让它们被食物来源吸引。因此,我希望有人帮助我找到正确的方向。

First off, I would like to let you know that I have been programming for a few years (mostly C-based languages, iOS development, web stuff, etc) as a hobby and am now developing an interest for creating a simple AI (most people start off with a tic tac toe game yes, but I am interested in making something using the principals of geneteic programming). The reason I would like the readers to know this is because I would appreciate it if the answers were not too complex (not too hard for a kid to understand since I haven't attended college computer science courses yet).

Here is my goal:

Terms

organsim: a CSS div
population: a group of organisms (5 or 10)
food source: another CSS div

Process

  1. A population is generated, each appearing to possess the same phenotypic attributes initially but differ in their skills (for this, speed)
  2. A single food source is generated (the same each time)
  3. After about 5 seconds of the environment being set up (steps 1 and 2), the population of organisms need to find a way to get to the food source competitively
  4. Only one organism may reach the food item. Upon reaching it, the environment is reset except the organism who found the food item the previous time is now benefitted and its speed level might increment while the others who did particularly terrible may get even slower or be terminated
  5. Process is repeated; the user may observe the traits of the population and see which ones are succeeding evolutionarily, etc.

Additional information

So as you can see, the above steps almost simulate evolution but in a very simple way (less conditions compared to real life situations for animals); Now here is why I'm asking here: I am completely lost. I really have no idea where to start (except for generating the population, I can most likely do that as well as getting them to move via jQuery animations). But being able to make them attract to a food source is what I can't do right now. So, I'd like help getting pointed in the right direction for this.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

大海や 2024-11-16 14:19:11

实时示例

请注意,这使用Raphael 用于渲染,下划线 用于语义糖。

我编写了一个非常小的程序,可以满足您的要求。 (这很有趣)。

1 生成了一个种群,每个种群最初似乎都具有相同的表型属性,但技能不同(为此,速度)。

var Critter = function() {
    // default the speed to something random.
    this.speed = SPEED + Math.random()*SPEED;

    // logic module
    var logic = function() { ... }
}

...
// initialize an array of critters.
critters: _.map(_.range(0,COUNT), function() {
    return new Critter;    
})

为您的人口成员创建一个构造函数,然后填充这些人的数组。我已将长度计数数组映射到小动物数组。 (厚脸皮的for循环)。

您创建的每个小动物都是相似的,但具有不同的技能(基于Math.random()),但它们将包含相同的逻辑单元。

2 生成单一食物源(每次都相同)

// trivial Food object.
var Food = function() {
    // rectangle with random x, random y, and SIZE as width / height
    this.el = paper.rect(Math.random()*WIDTH, Math.random()*HEIGHT, SIZE, SIZE);    
};

食物对象构造函数只是在屏幕上随机放置一个正方形

3 环境建立大约 5 秒后(步骤 1 和 2),生物群体需要找到一种方法来竞争性地获取食物源

设置环境:

_.invoke(this.critters, "start", this.food.el.getBBox(), out_of_bounds);

对于每个小动物,您调用它们的 start 方法。

this.start = function(food) {
    // create a player (circle);
    this.el = paper.circle(Math.random()*WIDTH, Math.random()*HEIGHT, SIZE / 2);  
    // set an interval to run the logic over and over.
    loop = setInterval(_.bind(logic, this, food), 25);    
};

每个小动物只是将自己随机地放置在屏幕上,然后在循环中一遍又一遍地调用自己的逻辑。

4 只有一种生物体可以接触到食品。到达目标后,环境会重置,除了上次发现食物的生物体现在受益,其速度水平可能会增加,而其他做得特别糟糕的生物体可能会变得更慢或被终止

var logic = function(food) {
    // if you hit food you win
    if (this.el.collision(food)) {
        this.win();
    }
}

// you won
this.win = function() {
    console.log("win");
    // increase speed
    this.speed += Math.random()*5;  
    // end round
    Game.end();
};

该生物将检测它是否有逻辑循环中的食物。一旦它有了食物,它就会调用自己的 win 方法。本轮游戏就此结束。

当小动物获胜时,它的速度会得到提升。

当您调用 .end 时,游戏将自行重新启动(删除所有当前生物后)

end: function () {
    // tell all critters to end their round
    _.invoke(this.critters, "remove");
    // remove the food
    this.food.el.remove();
    // start again !
    this.start();
},

5 重复该过程;用户可以观察群体的特征,看看哪些群体在进化上取得了成功,等等。

观看现场示例:)

6 下一步:

  • 调整全局数字和其他硬编码数字
  • logic 函数中实现一些 AI。
  • 浏览从 /1 到 /180 的所有 jsfiddles,看看它是如何构建的。
  • 抱怨注释不够详细
  • 既然您已经看到了示例,请扔掉我的代码并从头开始。
  • 出生码只是创建了一个“基本”小动物。它不是由两个现有的
    小动物并且没有增加技能。这意味着没有进化。

奖励:

前往食物

警告:

我将解释走向食物的逻辑

    // angle between critter and food
    var angle = Raphael.angle(
        this.el.getBBox().x,
        this.el.getBBox().y,
        food.x,
        food.y) - 135; // the 135 is the default direction (bottom right)
    // get a random speed
    var rand = Math.random()*this.speed;
    // travel towards the food box by rotating your vector by the angle
    var points = this.rotateVector([rand, rand], angle);

    // move towards the box
    this.el.translate(points[0], points[1]);

首先 rand 创建一个随机向量,如下所示:

“在此处输入图像描述”

Math.random() 确定小动物移动的距离/速度。这是指向右下角的。

因为它指向右下角,所以我们必须从该向量的角度中删除 135

enter image这里的描述

然后我们必须计算小动物和食物之间的角度。我们通过将两个点传递给 Raphael.angle 来实现这一点,它会为我们计算角度。

在此处输入图像描述

现在我们有了角度,我们想要将运动矢量旋转该角度。运动矢量当前指向上方(黑色),我们希望将其旋转一定角度到新位置(红色)。在代码中,这是 this.rotateVector

在此处输入图像描述

现在我们指向正确的方向!我们只需调用 this.el.translate(points[0],points[1])

Live Example

Be warned this uses Raphael for rendering, and underscore for semantic sugar.

I wrote a very small program that kind of meets your requirements. (It was fun).

1 A population is generated, each appearing to possess the same phenotypic attributes initially but differ in their skills (for this, speed).

var Critter = function() {
    // default the speed to something random.
    this.speed = SPEED + Math.random()*SPEED;

    // logic module
    var logic = function() { ... }
}

...
// initialize an array of critters.
critters: _.map(_.range(0,COUNT), function() {
    return new Critter;    
})

Create a constructor function for your population member then populate an array of these guys. I've mapped an array of length count to an array of critters. (Cheeky for loop).

Each critter you create will be similar but have different skills (based on Math.random()) but they will contain the same logic unit.

2 A single food source is generated (the same each time)

// trivial Food object.
var Food = function() {
    // rectangle with random x, random y, and SIZE as width / height
    this.el = paper.rect(Math.random()*WIDTH, Math.random()*HEIGHT, SIZE, SIZE);    
};

The food object constructor just places a square randomly on the screen

3 After about 5 seconds of the environment being set up (steps 1 and 2), the population of organisms need to find a way to get to the food source competitively

Setting the environment up:

_.invoke(this.critters, "start", this.food.el.getBBox(), out_of_bounds);

For each critter you invoke their start method.

this.start = function(food) {
    // create a player (circle);
    this.el = paper.circle(Math.random()*WIDTH, Math.random()*HEIGHT, SIZE / 2);  
    // set an interval to run the logic over and over.
    loop = setInterval(_.bind(logic, this, food), 25);    
};

Each critter simply places itself randomly on the screen then calls its own logic over and over in a loop.

4 Only one organism may reach the food item. Upon reaching it, the environment is reset except the organism who found the food item the previous time is now benefitted and its speed level might increment while the others who did particularly terrible may get even slower or be terminated

var logic = function(food) {
    // if you hit food you win
    if (this.el.collision(food)) {
        this.win();
    }
}

// you won
this.win = function() {
    console.log("win");
    // increase speed
    this.speed += Math.random()*5;  
    // end round
    Game.end();
};

The critter will detect whether it has the food in the logic loop. Once it has the food it calls its own win method. This ends the current game round.

When a critter wins it gets a speed boost.

The game will restart itself when you call .end (after removing all current critters)

end: function () {
    // tell all critters to end their round
    _.invoke(this.critters, "remove");
    // remove the food
    this.food.el.remove();
    // start again !
    this.start();
},

5 Process is repeated; the user may observe the traits of the population and see which ones are succeeding evolutionarily, etc.

Watch the live example :)

6 What's next:

  • Tweak global numbers and other hard coded numbers
  • Implement some AI in the logic function.
  • Go through all the jsfiddles from /1 to /180 and see how it was build up.
  • Complain that comments are not detailed enough
  • Throw my code away and start from scratch now that you've seen an example.
  • The birth code just creates a "basic" Critter. It doesn't breed from two existing
    critters and doesn't have increased skills. This means no evolution.

Bonus:

Travels towards food

Warning: The above link does travel towards the food but it's doing something wrong, there's a dodgy bug in there I think. I don't think I'll get round to fixing that.

I'll explain the logic to travel towards the food

    // angle between critter and food
    var angle = Raphael.angle(
        this.el.getBBox().x,
        this.el.getBBox().y,
        food.x,
        food.y) - 135; // the 135 is the default direction (bottom right)
    // get a random speed
    var rand = Math.random()*this.speed;
    // travel towards the food box by rotating your vector by the angle
    var points = this.rotateVector([rand, rand], angle);

    // move towards the box
    this.el.translate(points[0], points[1]);

First rand creates a random vector that looks like this:

enter image description here

The Math.random() determines how far / fast the critter moves. This is pointing towards the bottom right corner.

Because it's pointing towards bottom right corner we have to remove 135 degrees from the angle for this vector

enter image description here

We then have to calculate the angle between the critter and the food. We do this by passing in two points to Raphael.angle and it calculates the angle for us.

enter image description here

Now we have the angle and we want to rotate our movement vector by that angle. The movement vector is currently pointing up (black) and we want to rotate it by the angle to it's new position (red). In the code this is this.rotateVector

enter image description here

Now were pointing in the right direction ! We can just call this.el.translate(points[0], points[1])

む无字情书 2024-11-16 14:19:11

您应该将问题分为两部分:

第 1 部分:生物体必须能够向您指定的点移动。这需要一个计时器和一些数学来确定您必须移动每个生物体的坐标,以便在计时器的每一次滴答声中使其更接近目标。

谷歌应该能够帮助你找出完成这项工作所需的数学原理。

第 2 部分:生物体需要选择一个食物源(可能是最近的)并以此为目标,然后使用第 1 部分中描述的移动方法。

为此,您可以将每个生物体和食物源存储在数组中。然后,在计时器的每个滴答声中,循环遍历您的生物体,然后在该循​​环内循环遍历食物源,寻找最近的食物源。

同样,可以通过 Google 找到确定两组坐标之间距离的数学公式。

我认为我无法比现在更简单地阐述这些内容,但希望这能让您了解应该朝哪个方向前进。

You should break your problem into two parts:

Part 1: The organisms must be able to move toward a point you specify. Which would require a timer, and some mathematics to determine the coordinates you must move each organism in order to get it one step closer to its goal for each tick of the timer.

Google should be able to aid you in finding out the math to perform to make this work.

Part 2: The organisms need to select a food source (possibly the closest) and target that, then use the movement method described in part 1.

To do that, you might store each of your organisms and food sources in arrays. Then, during each tick of the timer, loop through your organisms, and then within that loop, loop through the food sources looking for the nearest one.

Again the math for determining distance between two sets of coordinates can be found with Google.

I don't think I can state this stuff any simpler than I have, but hopefully this gives you an idea of what direction to go in.

甜是你 2024-11-16 14:19:11

您可以查看 Conway's LIFE 的各种实现来获取灵感。我相信你可能已经见过类似的东西了?

有趣的阅​​读:元胞自动机

You might look at the various implementations of Conway's LIFE for inspiration. I believe you might already have seen something similar?

Interesting reading: Cellular Automata

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文