我真的对AI陌生。 (只看过一些视频/教程) 我了解基本知识...所以我决定从事一个项目..
所以这是我的游戏...我还没有添加计分板和其他东西。
我正在尝试将红球打成ai ...这样它可以得知与蓝色球相撞并不好...所以应该继续躲避那些...即使我看到有人在做不同的事情我不了解如何使用这些知识的项目...我正在考虑用蓝球的坐标制作一个qtable ...这就是我现在能想到的一切...
我基本上需要一个如何在此特定项目中实现AI的演练...请帮助
const canvas = document.getElementById("game");
const context = canvas.getContext("2d");
canvas.width = window.innerWidth-20;
canvas.height = window.innerHeight-20;
let gameover = false;
let x = canvas.width / 2;
let y = canvas.height / 2;
let dx = 0;
let dy = 0;
x3=y3=flag=c=0;
virx = new Array();
viry = new Array();
for (i=0; i<9; i++)
{
virx.push(Math.floor((Math.random() * window.innerWidth-40) + 20));
viry.push(Math.floor((Math.random() * window.innerHeight-40) + 20));
}
const state = {
"ArrowRight": false,
"ArrowLeft": false,
"ArrowUp": false,
"ArrowDown": false
}
function draw() {
context.clearRect(0, 0, canvas.width, canvas.height);
context.beginPath();
context.arc(x, y, 10, 0, Math.PI * 2, false);
context.fillStyle = "red";
context.fill();
context.closePath();
for (i=0; i<9; i++)
{
newpoint();
context.beginPath();
context.arc(virx[i], viry[i], 10, 0, Math.PI * 2, false);
context.fillStyle = "blue";
context.fill();
context.closePath();
context.beginPath();
context.moveTo(x,y);
context.lineTo(virx[i],viry[i]);
a=Math.pow(x-virx[i],2);
b=Math.pow(y-viry[i],2);
c = Math.sqrt(a+b);
if (c>600) {
context.strokeStyle = "#eee";
}
else if (c<600 && c>300) {
context.strokeStyle = "green";
}
else if (c<300 && c>100) {
context.strokeStyle = "yellow";
}
else if (c<100) {
context.strokeStyle = "red";
}
context.stroke();
}
}
function logic() {
const direction = determineDirection();
if (direction.dx) {
dx = dx + direction.dx;
}
if (direction.dy) {
dy = dy + direction.dy;
}
x = x + dx;
y = y + dy;
if (dx > 0) {
dx -= 0.02;
}
if (dx < 0) {
dx += 0.02;
}
if (dy > 0) {
dy -= 0.02;
}
if (dy < 0) {
dy += 0.02;
}
}
function play() {
draw();
logic();
}
document.addEventListener("keydown", keyDownHandler, false);
document.addEventListener("keyup", keyUpHandler, false);
function newpoint()
{
flag=0;
vx= x - virx[i];
vy= y - viry[i];
vsize = Math.sqrt((vx*vx) + (vy*vy));
vn_x = vx / vsize;
vn_y = vy / vsize;
newx = virx[i] + 0.5 * vn_x;
newy = viry[i] + 0.5 * vn_y;
for (j=0; j<9; j++)
{
if (j!=i)
{
a=Math.pow(virx[j]-newx,2);
b=Math.pow(viry[j]-newy,2);
c = Math.sqrt(a+b);
}
if(c<40)
{
// flag=1;
while (true)
{
newx = Math.random() * (window.innerWidth-40) + 20;
newy = Math.random() * (window.innerHeight-40) + 20;
a=Math.pow(x-newx,2);
b=Math.pow(y-newy,2);
c = Math.sqrt(a+b);
if (c>300)
{
break;
}
}
}
}
if (flag==0)
{
virx[i] = newx;
viry[i] = newy;
}
}
function determineDirection() {
const {
ArrowRight,
ArrowLeft,
ArrowUp,
ArrowDown
} = state
if (ArrowRight && ArrowUp) {
return {
dx: .040,
dy: -.040
};
}
if (ArrowRight && ArrowDown) {
return {
dx: .040,
dy: .040
};
}
if (ArrowLeft && ArrowUp) {
return {
dx: -.040,
dy: -.040
};
}
if (ArrowLeft && ArrowDown) {
return {
dx: -.040,
dy: .040
};
}
if (ArrowLeft) {
return {
dx: -.040,
dy: 0
}
}
if (ArrowRight) {
return {
dx: .040,
dy: 0
}
}
if (ArrowUp) {
return {
dx: 0,
dy: -.040
}
}
if (ArrowDown) {
return {
dx: 0,
dy: .040
}
}
return {
dx: 0,
dy: 0
}
}
function keyDownHandler({
key
}) {
state[key] = true;
}
function keyUpHandler({
key
}) {
state[key] = false;
}
setInterval(play, 10);
<html>
<head>
<title>yo ai</title>
<style>
canvas { background: #eee; }
</style>
</head>
<body>
<canvas id="game" height="600" width="1000"></canvas>
<script type="text/javascript" src="script.js"></script>
</body>
</html>
本质上,您需要AI仅计算一件事和一件事:要朝哪个方向前进,以便远离蓝球。
如果它可以沿2轴移动,则AI有望产生8种可能的方向输出:
x+, x-, y+, y-, x+y+, x+y-, x-y+, x-y-
,或根本不移动(这可能不是真正的选择),0、0。(除非您通过正弦(角)或cos(角)的角旋转来确定运动,在这种情况下理论上可以是无限数量的方向,具体取决于您希望达到的精度)
问题是,给定蓝色圆圈的当前位置数组,我们如何得出上述方向之一。
基本上,我们需要理论上遍历每个选项,并确定作为该选项的结果,我们是否比以前更接近一个蓝色圆圈。如果是这样,请选择另一个方向。如果所有这些都导致越来越接近一个蓝色圆圈,那么请选择一个我们正在“接近”蓝色圆圈的位置。
因此,基本上,我们需要先记录当前的红球位置,然后遍历所有方向选项(在这种情况下,它可以是dx和dy的8个值的数组,例如
然后在主循环函数中循环遍历此数组,并在该循环内部遍历所有蓝色圆圈,并对每个蓝色圆圈进行距离检查(确保将理论dx和dy添加到先前记录的电流中红球位置)。
将每个距离的结果存储在紧接在这两个循环之外(但仍在主逻辑循环中)的另一个数组(或对象)中,这也将以某种方式将索引引用到要循环的当前方向对象,然后,在完成两个循环之后,现在再次遍历该“距离”数组/对象,或者使用Math.min确定较小的值,并将dx和dy设置为以某种方式引用的数组在当前“方向”索引中[也许“方向”可以简单地是一个具有两个属性的对象的数组,#1是实际距离,#2是dx和dy值的两部分数组(例如[-1,0 ])或对之前循环的dx-dy数组元素的索引的引用)。
如果需要显式的伪代码示例,请告诉我。