2016 年 7 月

第 31 卷,第 7 期

本文章是由機器翻譯。

C# - AI 在多代理程式 "Mini-Basketball" 遊戲中的應用

Arnaldo Pérez Pérez | 2016 年 7 月

人工智慧 (AI) 現在是在電腦科學中的最有趣、 研究欄位和它的子欄位的許多日常生活上有大的影響。您所見 AI 套用幾乎無所不在,以及在最不可預期的情況下,當保險公司適用於資料採礦演算法來尋找個人 (並確認用戶端不會嘗試誘騙手段都),間的關聯取得時的建議的 friend 清單的 Facebook,當您播放視訊遊戲,依此類推。它的應用程式的龐大,而且包括經濟、 商務、 天文學、 醫學和軍事等方面。

多樣化的人力工作自動化,並建立假造的道德感的需求有一段時間,來形成這個受歡迎的科學稱為 AI 負責人。其定義可以聽起來,那麼簡單定期產生疑問,因為 AI 可能代表電腦科學的最大欄位。專家的觀點來看,從 AI 是我們人類的想法與相關聯的活動和活動等的決策、 解決問題、 學習的自動化 (「 人工智慧︰ 電腦可以到認為? 」 Richard 東 Bellman,1978年)。先前的定義狀態人工智慧與關聯的方式自動化人力的活動。因此,就會發生這個問題︰ 為什麼您需要建立人工智慧自動化人力的工作? 是真的有必要? 答案仍是適用的。

人類是最複雜、 更簡潔且複雜簡介-機器已知世人。複雜且有趣我們生態,與我們的大腦令人讚嘆功能結合運作讓我們幾近完美的機器。但是,如果人類是這麼地完美,則為什麼建立 e 鋼機器和 AIs 嗎?

首先,讓人建立電子、 鋼鐵機器因為即使我們生物函式非常,它是非常脆弱。因此,它無法獨立極高或過低的溫度,需氧才能正常運作,它可以輕鬆地損毀自然的物件,它缺乏鋼擁有等等的強度。電子、 鋼鐵機器會略過所有這些 tribulations。

第二,人腦,雖然發生情感,而讓一些很複雜的原因,並能夠開啟緩慢相較於在簡單和基本準則的電腦︰ 計算。不同於人腦,機器大腦 (電腦),是能夠執行數以百萬計的每秒的計算。速度快上許多完成作業,例如搜尋和排序大型網域中的電腦比人類。因此,AIs 是需要以協助我們讓我們的生活更有效率,並可節省時間。當您使用 [小算盤]; 是這樣人腦不通常能提供較大的數字,如平方根的快速計算,例如。因此,您幾乎可以立即; 取得該結果使用計算機計算機基本上是其工作計算的機器人。

在後續章節中,我將說明一些傳統的實體,AI 和其互動相關的系統。我將示範如何開發多代理程式籃球比賽 AI 可能有兩個籃球小組 (相關和 Knicks) 會對彼此播放。

代理程式

'90s 電腦科學所引進的代理程式的概念和詞彙現在是為現代 fashionable 做為物件導向的語言已在' 80 年代或 AI 中 ' 70 年代。代理程式是能夠感應其環境和其上執行的實體 (「 人工智慧︰ 現代的方法,「 Stuart 羅和 Peter Norvig,1997年)。代理程式和一般程式的主要差異是第一個必須是獨立的。也就是它必須運作,而不需直接介入的人或其他人。其他的差異是代理程式會執行特定工作代表其他人 (通常稱為使用者或程式設計人員),因此 word 代理程式,如它所示,指出代表其他人剛做的任何人。

合理的代理程式是一個,以便達成最佳的結果做,或不確定時,最佳的預期結果 (「 人工智慧︰ 現代的方法,「 Stuart 羅和 Peter Norvig,1997年)。在這種情況下 rationality 是指進行正確推斷和選取 (可能的話) 的動作,邏輯結束後會達成所需的目標。人類是合理的代理程式。他們有意義的眼睛、 耳朵、 語言、 和鼻子透過其環境,並最終採取動作之後,使用其腳,指針等等,通常套用某些邏輯的理由,然後選取動作將會導致這些期望的結果。

Percept 是指代理程式的感知輸入在任何給定的時刻。Percept 序列代表完整的 percepts 感應代理程式,或認為他存留期間的順序。代理程式函式表示代理程式的行為,透過從任何 percept 序列對應至動作。此函式是只是抽象的描述。代理程式是這個抽象層的實際實作。[圖 1 籃球播放程式會示範部分代理程式函式。資料行標示為 Percept 順序包含玩家的狀態,並標示為動作的資料行包含對應的 percept 順序後執行的動作。

[圖 1 籃球播放程式的部分代理程式函式

Percept 順序 動作
(關閉到購物籃、 未防護) 疑難排解
(接近對手,對手羊) Block
(對手失去球) 竊取
(保護隊友未防護) 傳遞
(隊友接近購物籃、 未防護的小組、 小組良好 slammer、 眼睛連線) 道 oop 傳遞

您可以分割為世界的代理程式,請根據它們的架構,以下列類別︰

  • 重新啟動代理程式都能夠維護環境中持續進行的互動和及時回應中發生變更。這個詞彙現在廣泛用來表示系統,其中包含任何符號表示法或推論;這類代理程式並不會反映其動作,長期效果並不會視為活動搭配其他代理程式。因此,重新啟動代理程式一律會及時回應至外部刺激,是事件驅動。這可以被實作簡單的 if then 規則。很難確保所需的行為與規則才會隱含地代表代理程式的目標。每種情況下,必須考量事先;因此,在複雜環境中的重新啟動系統通常會包含數百個規則。重新啟動代理程式有沒有內部模型的世界,因此無法推論它任何抽象的方式。再次提醒您,代理程式,只要接收的輸入,並回應透過簡單的規則。
  • 主動代理程式都會計劃。不完全由事件,但能夠產生目標及理性判斷做來達到這些目標所驅動。有些看到做為目標導向的重新啟動代理程式。
  • Deliberative 代理程式以透過符號表示的知識,並使用腦子裡的概念,例如信念、 自己的意願、 成員、 選擇,依此類推。嘗試將模型人力推論,分散式的活動和透過邏輯表現的行為。它通常是透過相信、 desire、 意圖 (BDI) 架構實作。便於有關過去和計劃在未來。規劃務必在這種架構。
  • 混合式代理程式是一個混合一些不同的架構。

分割世界的代理程式的另一個替代方式是將它分割成學習和非學習代理程式。學習代理程式是指需要執行某些訓練、 調整其目前的行為,根據先前的經驗和長時間的發展。非學習代理程式是指不發展或與過去的經驗是硬式編碼及獨立於其程式設計。

由於籃球遊戲環境各有不同,有限且由一組有限的規則定義,我會建議在本文中的非學習代理程式。

多個代理程式系統

當代理程式的環境中與共存的其他代理程式 — 或許是共同作業,或與其競爭 — 它會被視為多代理程式 (MA) 系統。在 MA 環境中,每個代理程式有它自己的全球的觀點來看,不知道的內部狀態或其他代理程式請參閱環境的方式。因此,MA 代表一種分散式系統的下列功能︰

  • 代理程式會有不完整的系統或功能不足,無法自動解決工作資訊。
  • 系統會出現任何通用控制項。
  • 被分散式的資料。

聯盟是在環境中的代理程式的任何子集。籃球比賽有兩個 coalitions — team A 和 B 的小組,其交集是空的他們都有相同的基數為大於零。

策略是接收環境的目前狀態,並將輸出聯盟所要執行動作的函式。為小組的策略通常取決於目前此時小組 B 中的每個代理程式所執行的動作。

MA,在互動會透過通訊方式,有各種形式的代理程式可以進行通訊。對應到固定解譯一般訊號可能是代理程式之間通訊的貝氏形式。矩形色塊結構是組成共用資源分成不同區域的代理程式可以讀取或寫入其動作的任何重要資訊的所在環境的通訊形式。代理程式之間傳遞的訊息是另一種通訊。在這份表單,代理程式來交換訊息與指定的語法和通訊協定,但缺少語意 (semantics)。因此,接收的代理程式必須推算訊息的目的。最後,語音 1969年物件扮演大幅 impulsed 的理論,由美國哲學家 John R.Searle (「 語音的動作︰ 文章的基本概念的語言 」),1994 年 (「 基礎架構的語音 Act 理論上 」) 的加拿大 logician Daniel Vanderveken 能夠克服訊息代理程式之間的互動透過在兩個層級中所傳遞的缺點,首先,告知性訊息和內容,第二個訊息的目的。這個方法會將標示 locution act (單字、 句子),locution 意圖之間的差異 (通知、 要求、 訂單等等) 和所需的 locution 結果 (insult,說服等等)。

協調是 MA 中不可或缺的因為它提供一致性的系統行為,並提供給實現小組或聯盟的目標。它表示考慮到帳戶動作的其他代理程式從規劃及執行對應的項目至個別或多個代理程式。在許多情況下,協調也意味著合作或競爭;同時存在於籃球比賽。

由於互補的技能和代理程式動作和萬全的滿足某些成功準則之間存在相互依存性,必須合作。在合作的模型中,代理程式會共同積極或共同興趣。因此,這些工作完成常見的目標。另一個可能的模型是以代理程式會自我積極或自我想要代理程式因為每個代理程式有它自己的目標,而且可能輸入的代理程式的競賽中達成這些目標系統。在這種情況下,競爭可能參考完成或散發某些工作。在這種模型中,代理程式需要協調其動作,以確保具有一致的行為的其他代理程式。協調程序期間在合作式或競爭激烈的環境中,衝突可能會出現和這些透過交涉來解決。交涉可能會識別通訊為基礎的互動及推理能力關於狀態的程序和其他代理程式的顯示。

在下一節中,我將說明本小說和有趣的資料結構會出現在許多現今的視訊遊戲︰ 行為樹狀結構。

有限狀態機器和行為的樹狀結構

有限狀態機器 (FSMs) 已被建立模型的決策、 動作選取和執行遊戲中的代理程式行為的傳統方式。由一組有限的狀態和轉換函式的數學模型符合 FSM 代表。FSMs 提供簡單、 直覺的機制,重新啟動行為,處理並作出反應輸入事件的連續資料流。

[圖 2 說明簡單的 FSM 模型代理程式的行為,當它到達距離購物籃視為 「 關閉 」。 當發生這種情況時,它會移至疑難排解問題。在此案例中,狀態對應至行為和轉換的事件。需要擴充其功能,或實作更複雜的行為會出現來自 FSM 的主要缺點。在這種情況下,狀態轉換的數字會增加以指數方式進行 FSM 極難了解和處理。

簡單有限狀態機器模型
[圖 2 簡單有限狀態機器模型

行為樹狀目錄 (BTs) 提供簡單、 可調整、 模組化的解決方案,以代表複雜 AI 行為提供方便維護,並設定的邏輯。在遊戲產業中的使用在過去幾年來情況中,例如"Halo3","Spore,""BioShock"和"SWAT 4 」 的標題包含 BTs 行為模型化工具,可大幅增加。BTs 目標導向,而且每個樹狀結構與不同的高階目標。BTs 可以連結在一起,讓先定義較小,子行為的實作複雜的行為。

一種原始架構或複合建構 BT 在每個節點。第一種會形成樹狀結構中,分葉後者代表描述子節點之間的關聯性的方式。

有兩種類型的基本結構。動作只限執行代理程式 (移動、 疑難排解及其他) 與相關的方法。條件的查詢環境的狀態 (是對手連線,是可行的移動,接近購物籃等等)。

[圖 3 節點會顯示兩個小孩 BT — C 的條件和動作 a。

具有兩個子系節點的行為樹狀結構
圖 3 行為樹狀目錄中具有兩個子系的節點

有四種類型的複合建構。選取器會挑選其中一個要執行的子系。此選項可隨機或使用某些優先順序。選取器的值取決於執行的子節點是否已成功 (傳回 true)。

序列會在執行中的子節點的排序。在 [圖 3, ,紅點條線是表示序列的樹狀目錄中執行的順序。此類型的節點才會成功,其所有子系節點的每一個必須成功,以及。

最後,裝飾項目,啟發,程式設計的設計模式中,提供簡化程式設計的程序和擴充功能新增至節點行為的方式。計時器的裝飾項目可能是一種,正如其名,它的子系節點完成後執行的特定時間間隔內的裝飾項目。計數器的裝飾項目,相反地,就可以執行的子節點或行為數次。在 [圖 3, ,D 計數器裝飾項目將會執行節點順序 10 次,所定義。

在下一節中,我將說明在這篇文章中考慮的籃球比賽和提議的這類遊戲 AI 的簡化的版本。

籃球比賽和 AI 實作

籃球比賽是大且複雜的遊戲需要複雜的 FSM 或大型 BT,因為只有簡化它的版本,其中包含一些基本策略,攻擊與防禦播放會被視為在這篇文章。在這個遊戲中,將會有兩名玩家 (A1]-> [blue,B1]-> [綠色),每個都有屬性速度和疑難排解的精確度。第一個定義速度或經常播放程式反應到環境,而後者是定義播放程式會進行一次嘗試的擷取畫面的機率。一開始,播放程式中啟動中心中所示 [圖 4。分數是 0-0 和時間為 0 秒。如果播放程式未在 15 秒後評分的擷取時鐘違規會觸發,並玩家失去球的所有權。遊戲的 GUI 組成一個 Windows Form 應用程式,您稍後可以查閱,以檢查任何圖形化的詳細資料。[開始] 按鈕,如預期地啟動遊戲。類似的 [停止] 按鈕。

AI 實作籃球比賽
圖 4 籃球比賽 AI 實作

黃色方塊表示購物籃,而白色圓圈代表球。讓我們開始分析法院類別對應至籃球法院命令。它包含在所列的欄位 [圖 5

[圖 5 法院類別

public class Court
{
public int Height { get; set; }
public int Width { get; set; }
public Point BallPos { get; set; }
public int ScoreTeamA { get; set; }
public int ScoreTeamB { get; set; }
private readonly string[,] _grid;
public Court(int h, int w)
  {
Height = h;
Width = w;
_grid = new string[h,w];
  }
...
}

欄位的高度和寬度都一目了然。BallPos 表示球在蹺蹺板上法院的位置。ScoreTeamA 和 ScoreTeamB 表示每個玩家的分數,而且 _grid 字串矩陣包含法院的邏輯。如果 player A1 儲存格 (0,0) 上且擁有的球,then 值 _grid [0,0] = A1,b。這同樣適用於 B1,因此,可能的值的方格中的任何儲存格 A1、 B1、 A1、 B 和 B1、 B這個類別中實作的索引子的方法,如下所示 (索引子提供的方格上的項目編製索引,它也會更新在法庭上球的位置)︰

public string this[int i, int j]
{
get { return _grid[i, j]; }
set
  {
    _grid[i, j] = System.String.Format("{0}", value);
if (IsBall(value))
    BallPos = new Point(i, j);
}
}

IsBall 方法判斷指定的字串是否包含球︰

private bool IsBall(string s)
{
  return s.Split(',').Contains("B");
}

IsEmpty 方法會判斷是否是空的方格資料格︰

public bool IsEmpty(int i, int j)
{
  return string.IsNullOrEmpty(_grid[i, j]);
}

最後,ToWallGrid 方法會傳回 PathNode 矩陣中所示 [圖 6; 它將用於路徑尋找演算法中稍後說明。

[圖 6 ToWallGrid 方法

public PathNode[,] ToWallGrid()
{
var wallGrid = newPathNode[Height, Width];
for (var i = 0; i < Height; i++)
  {
for (var j = 0; j < Width; j++)
 {
wallGrid[i, j] = new PathNode
  {
    IsWall = !string.IsNullOrEmpty(_grid[i,j]),
    X = i,
    Y = j,
  };
}
} 
return wallGrid;
}

這種方法 wallGrid 矩陣會指出是否指定儲存格會被視為障礙或不是,如所述,它可以做的路徑尋找的演算法之前。

BehaviorTree 類別和其所有子系結構是根據 [圖 7 圖表。

BehaviorTree 類別結構
[圖 7 BehaviorTree 類別結構

每個 BehaviorTree 相關類別的程式碼所示 [圖 8

[圖 8 程式碼的每個 BehaviorTree 相關類別

public abstract class BehaviorTree
  {
public List<BehaviorTree> Children { get; set; }
public BehaviorTree Value { get; set; }
public Court Court { get; set; }
protected BehaviorTree(Court court)
{
  Court = court;
}
public abstract bool Exec();
  }
public abstract class Primitive : BehaviorTree
  {
protected Primitive(Court court) : base(court)
{
}
  }
public class Action: Primitive
  {
public delegate bool Act();
public Act Function { get; set; }
public Action(Court court):base(court)
{
}
public override bool Exec()
{
return Function();
}
  }
public class Conditional : Primitive
  {
public delegate bool Pred();
public Pred Predicate { get; set; }
public Conditional(Court court)
  : base(court)
{
}
public override bool Exec()
{
return Predicate();
}
  }
public abstract class Composite : BehaviorTree
  {
protected Composite(Court court):base(court)
{
}
  }
public class Sequence: Composite
  {
public Sequence(Court court)
  : base(court)
 {
}
public List<int> Order { get; set; }
public override bool Exec()
{
if (Order.Count != Children.Count)
throw new Exception("Order and children count must be the same");
foreach (var i in Order)
{
if (!Children[i].Exec())
return false;
}
return true;
}
  }
public class Selector : Composite
  {
public Selector(Court court)
  : base(court)
{
}
public int Selection { get; set; }
public override bool Exec()
{
return Children[Selection].Exec();
}
  }

由於每個類別很簡單,而且容易理解的程式碼,將提供其中沒有描述;您可以輕鬆查看每個類別的用途為何,以及它連結至先前所述概念的方式。

應用程式中最重要的類別是播放程式代表本身的代理程式和類別封裝其行為和所有 AI 的程式碼。這種行為已分成冒犯和防衛;第一個具有已透過 FSM 建立模型,後者具有已使用模型化中所示的一個簡單 BT [圖 3。播放包含所列的欄位中顯示 [圖 9

圖 9 Player 類別程式碼欄位

public class Player
{
public Point Position { get; set; }
public string Name { get; set; }
public int Number { get; set; }
public int Speed { get; set; }
public double ShootingAccuracy { get; set; }
public bool BallPossession { get; set; }
public LinkedList<PathNode> Path;
private readonly Court _court;
private readonly Random _random;
public Player(Court court, Point basket)
  {
    ScoringBasket = new Point(basket.X, basket.Y);
    _court = court;
    Path = new LinkedList<PathNode>();
    _random = new Random();
  }
}

位置法庭上定義的播放程式的位置。ScoringBasket 是他應該評分法庭的位置。路徑是一份 PathNodes 用來尋找一個初始指向 _random 及方法上的另一個考慮過障礙是隨機物件用來取得的機率,將擷取的最短的路徑。其餘欄位都一目了然。

這個類別會使用下列的列舉︰

public enum Percept
{
  Guarded,
  CloseToBasket,
  BallLoose,
  BallInPossession,
  OnDefense,
  None
}
public enum Direction
{
  Up, Down, Left, Right
}

Player 類別分為述詞的方法和動作方法。有三個述詞︰

private bool IsBallLoose()
{
return _court[_court.BallPos.X, _court.BallPos.Y] == "B";
}
private bool IsCloseToBasket()
{
return Math.Abs(Position.X - ScoringBasket.X) <= 1 &&Math.Abs(
  Position.Y - ScoringBasket.Y) <= 1;
}

IsBallLoose 方法只會判斷是否球位於鬆散法院;IsCloseToBasket 方法會決定他評分購物籃靠近播放程式︰

private bool IsOpponentReachable()
{
var opponents = FindOpponents();
var factor = ScoringBasket.Y == 0 ? 1 : -1;
foreach (var opponent in opponents)
  {
if ((Position.Y - opponent.Y) * factor >= 0)
return true;
  }
return false;
}

IsOpponentReachable 指出到達其中一個上法院; 對手的可能性決定是否可連線位置對手因素變數的協助。連線到對手尚未傳遞 (以令人反感的模式) 的方法時邁向他評分購物籃的播放程式的資料行。

才能查看動作區塊程式碼,讓我們來分析兩個代理程式執行動作後隨即被呼叫的方法︰

public void Action()
{
var percepts = GetPercepts();
if (percepts.Contains(Percept.CloseToBasket))
Shoot();
elseif (percepts.Contains(Percept.BallLoose))
MoveToBall();
elseif (percepts.Contains(Percept.BallInPossession))
MoveToBasket();
elseif (percepts.Contains(Percept.OnDefense))
Defend();
}

此方法表示代理程式的函式。它會取得一組 percepts 和回應或決定要查看 percepts,所採取的動作中所示 圖 10

[圖 10 代理程式的函式

private IEnumerable<Percept> GetPercepts()
{
var result = new List<Percept>();
if (IsCloseToBasket())
result.Add(Percept.CloseToBasket);
if (IsBallLoose())
result.Add(Percept.BallLoose);
if (IsCloseToBasket())
result.Add(Percept.CloseToBasket);
if (BallPossession)
result.Add(Percept.BallInPossession);
else
result.Add(Percept.OnDefense);
return result;
}

GetPercepts 方法,依賴數個述詞,會傳回 percepts 最後用來決定要採取的動作集合。

首先,FeasibleMoves 方法做為篩選器。一旦代理程式已決定在特定的方向移動,它會檢查 FeasibleMoves 清單的指示,並查看是否代理程式的方向大約是讓實際可行的如果不會採取任何動作。Move 方法,其中包含呼叫 FeasibleMoves 方法所示 [圖 11

[圖 11 Move 方法

private void Move(Direction direction)
{
if (!FeasibleMoves().Contains(direction))
return;
  _court[Position.X, Position.Y] = "";
switch (direction)
  {
case Direction.Left:
Position = new Point(Position.X, Position.Y - 1);
break;
case Direction.Right:
Position = new Point(Position.X, Position.Y + 1);
break;
case Direction.Up:
Position = new Point(Position.X - 1, Position.Y);
break;
case Direction.Down:
Position = new Point(Position.X + 1, Position.Y);
break;
  }
// To write his correct value on the grid
_court[Position.X, Position.Y] =
(_court.BallPos.X == Position.X && _court.BallPos.Y == Position.Y) || BallPossession
? Name + ",B"
: Name;
if (_court[Position.X, Position.Y].Split(',').Contains("B"))
BallPossession = true;
}

萬一它是在法庭上鬆散 MoveToBall 方法會將移動球向 media player:

private void MoveToBall()
{
var ballPos = _court.BallPos;
if (ballPos.X == Position.X)
Move(ballPos.Y>Position.Y ? Direction.Right : Direction.Left);
elseif (ballPos.Y == Position.Y)
Move(ballPos.X>Position.X ? Direction.Up : Direction.Down);
}

中所示 圖 12, ,MoveToBasket 代表應用程式中的特殊方法,因為它是唯一的包括規劃 (反應式和 deliberative) 可讓代理程式的混合式。

圖 12 MovetoBasket 方法

private void MoveToBasket()
{
if (Path.Count == 0)
  {
    Path = new LinkedList<PathNode>(PathFinding(Position, ScoringBasket));
    Path.RemoveFirst();
  }
// Already have a strategy
if (Path.Count > 0)
  {
var nextMove = Path.First();
    Path.RemoveFirst();
// Check if move still available
if (string.IsNullOrEmpty(_court[nextMove.X, nextMove.Y]))
MoveDecision(nextMove);
else
Path.Clear();
  }
}

MoveToBasket 建置到購物籃; 玩家的位置路徑如果計劃失敗或變得不可行,該路徑清除,且重新計算一次。PathFinding 演算法會搜尋演算法。在此情況下,A * 演算法。路徑尋找演算法 AI 經常會實作,並在遊戲中相當常見。

如先前所述,防禦的行為使用開發 BT,如所示 圖 13

[圖 13 防禦行為使用行為樹狀結構

private void Defend()
{
DefensiveBehavior(_court).Exec();
}
private BehaviorTree DefensiveBehavior(Court court)
{
var isReachableNode = new Conditional(court)
{
  Predicate = IsOpponentReachable
};
var blockNode = new Action(court)
{
  Function = BlockPath
};
var defenseBehavior = new Sequence(court)
{
  Order = new List<int> {0,1},
  Children = new List<BehaviorTree>
    {
isReachableNode,
blockNode
    }
};
return defenseBehavior;
}

BlockPath 方法表示的播放程式會嘗試封鎖購物籃他最接近對方路徑的策略。它會依賴最近的方法中所示,使用曼哈頓距離來尋找最接近對方 圖 14

[圖 14 BlockPath 方法

private bool BlockPath()
{
var closestOppPos = Closest(FindOpponents());
// Move to same row
if (closestOppPos.X > Position.X)
Move(Direction.Down);
elseif (closestOppPos.X < Position.X)
Move(Direction.Up);
// Move to same column
elseif (closestOppPos.Y > Position.Y)
Move(Direction.Right);
elseif (closestOppPos.Y < Position.Y)
Move(Direction.Left);
return true;
}

總結

在本文中,我說明了如何開發多代理程式的籃球比賽的混合式代理程式。它是現在最多要加入新功能和加強 AI 提議。在未來的文章中,我將探討建立籃球比賽,學習代理程式的問題學習代理程式會隨時間而演進,並改善其策略與每個新的播放。


Arnaldo Pérez Castaño 是電腦科學家古巴基礎。 他是一系列的程式設計書籍的作者 — 「 JavaScript Fácil 」,「 HTML y CSS Fácil,"和"Python Fácil 」 (Marcombo 南美洲)— 與寫入 VisualStudioMagazine.com 和破壞 Magazine。他的專長包括 Visual Basic、 C#、.NET Framework 和人工智慧、 和他提供他服務透過 freelancer nubelo.com。影片和音樂都他的最愛。他的連絡 arnaldo.skywalker@gmail.com

感謝以下的微軟技術專家對本文的審閱: James McCaffrey
Dr.James McCaffrey 適用於在美國華盛頓州 Redmond 的 Microsoft Research他曾在包括 Internet Explorer 和 Bing 的數個 Microsoft 產品。Dr.McCaffrey 可以到達 jammc@microsoft.com