בניית משחק לוח בעזרת סוכני TensorFlow ו-Flutter

1. לפני שמתחילים

פריצת הדרך המדהימה של AlphaGo ו-AlphaStar הוכיחה את הפוטנציאל של שימוש בלמידת מכונה לפיתוח סוכני משחקים ברמה על-אנושית. זה תרגיל כיפי לפתח משחק קטן שמבוסס על למידת מכונה, שבעזרתו אפשר לרכוש את המיומנויות שנדרשות ליצירת סוכני משחקים חזקים.

ב-Codelab הזה תלמדו איך לבנות משחק לוח באמצעות:

  • נציג של TensorFlow כדי לאמן סוכן משחקים עם למידת חיזוק
  • מילוי בקשות של TensorFlow לצורך הצגת המודל
  • Flutter ליצירת אפליקציה של משחקי לוח בפלטפורמות שונות

דרישות מוקדמות

  • ידע בסיסי על התפתחות Flutter עם Drt
  • ידע בסיסי בלמידת מכונה עם TensorFlow, למשל אימון לעומת פריסה
  • ידע בסיסי ב-Python, טרמינלים ו-Docker

מה תלמדו

  • איך מאמנים סוכן של דמות שאינה נגן (NPC) באמצעות סוכני TensorFlow
  • איך להציג את המודל שעבר אימון באמצעות הצגת מודעות של TensorFlow
  • איך בונים משחק לוח של Flutter בפלטפורמות שונות

למה תזדקק?

2. המשחק The Plane Strike

המשחק שאתם בונים ב-Codelab הזה נקרא Plane Strike – משחק לוח קטן ל-2 שחקנים שדומה למשחק הלוח Battleship. הכללים פשוטים מאוד:

  • השחקן האנושי משחק נגד סוכן NPC שעבר אימון על ידי למידת מכונה. השחקנים יכולים להתחיל את המשחק בהקשה על תא כלשהו בלוח של הנציג.
  • בתחילת המשחק, לשחקן האנושי ולסוכן יש 'מטוס' אובייקט (8 תאים ירוקים שיוצרים 'מישור' כפי שאפשר לראות בלוח של השחקן באנימציה שלמטה) על הלוחות שלו; המטוסים האלה מוצבים באופן אקראי וגלויים רק לבעלי הלוח ומוסתרים ליריבים.
  • השחקנים האנושיים והנציג תורו להכות בתא אחד בלוח המשחק אחד של השני. הנגן האנושי יכול להקיש על כל תא בלוח של הסוכן, והסוכן יבצע את הבחירה באופן אוטומטי על סמך החיזוי של מודל למידת המכונה. התא לניסיון הופך לאדום אם הוא 'מטוס' תא (‘hit'); אחרת הוא הופך לצהוב ('החמצה').
  • מי שישיג 8 תאים אדומים קודם יזכה במשחק. לאחר מכן המשחק יופעל מחדש עם לוחות חדשים.

הנה גיימפליי לדוגמה:

77cead530c5a4aff.gif

3. הגדרת סביבת הפיתוח של Flutter

לפיתוח של Flutter, נדרשות שתי קטעי תוכנה כדי להשלים את ה-Codelab הזה – Flutter SDK ועורך.

אפשר להריץ את Codelab באמצעות כל אחד מהמכשירים הבאים:

  • הסימולטור של iOS (צריך להתקין כלים של Xcode).
  • האמולטור של Android (נדרשת הגדרה ב-Android Studio).
  • דפדפן (Chrome נדרש לניפוי באגים).
  • בתור אפליקציית Windows , Linux או macOS למחשב. צריך לפתח בפלטפורמה שבה אתם מתכננים לפרוס. לכן, כדי לפתח אפליקציה למחשב של Windows, צריך לפתח את האפליקציה ב-Windows כדי לגשת לשרשרת ה-build המתאימה. יש דרישות ספציפיות למערכת ההפעלה שמפורטות בהרחבה בכתובת docs.flutter.dev/desktop.

4. להגדרה

כדי להוריד את הקוד ל-Codelab הזה:

  1. עוברים אל מאגר ה-GitHub של ה-Codelab הזה.
  2. לוחצים על קוד > כדי להוריד את כל הקוד ל-Codelab הזה, צריך להוריד את ה-ZIP.

2cd45599f51fb8a2.png

  1. מחלצים את קובץ ה-ZIP שהורדתם כדי לפתוח תיקיית בסיס מסוג codelabs-main עם כל המשאבים הנחוצים.

ב-Codelab הזה, צריך רק את הקבצים בספריית המשנה tfagents-flutter/ במאגר, שמכיל כמה תיקיות:

  • התיקיות step0 עד step6 מכילות את קוד הסימן לתחילת פעולה שעליו יוצרים בכל שלב ב-Codelab הזה.
  • התיקייה finished מכילה את הקוד שהושלם עבור האפליקציה לדוגמה הסופית.
  • כל תיקייה מכילה תיקיית משנה backbend, שכוללת את הקוד לקצה העורפי ותיקיית משנה frontend, שכוללת את הקוד בקצה הקדמי של Flutter

5. הורדת יחסי התלות של הפרויקט

קצה עורפי

פותחים את הטרמינל ונכנסים לתיקיית המשנה tfagents-flutter. מריצים את הפקודה הבאה:

pip install -r requirements.txt

קצה קדמי

  1. ב-VS Code, לוחצים על File > (קובץ >) פותחים את התיקייה ובוחרים את התיקייה step0 מקוד המקור שהורדתם קודם.
  2. פתיחת הקובץ step0/frontend/lib/main.dart. אם מופיעה תיבת דו-שיח של VS Code, עם בקשה להוריד את החבילות הנדרשות לאפליקציה למתחילים, לוחצים על קבלת חבילות.
  3. אם תיבת הדו-שיח הזו לא מופיעה, פותחים את הטרמינל ואז מריצים את הפקודה flutter pub get בתיקייה step0/frontend.

7ada07c300f166a6.png

6. שלב 0: מפעילים את האפליקציה לתחילת הפעולה

  1. פותחים את הקובץ step0/frontend/lib/main.dart ב-VS Code, מוודאים שהאמולטור של Android או הסימולטור של iOS מוגדרים כראוי ומופיעים בשורת הסטטוס.

לדוגמה, זה מה שרואים כשמשתמשים ב-Pixel 5 עם האמולטור Android:

9767649231898791.png

כשמשתמשים ב-iPhone 13 עם הסימולטור של iOS, רואים את הפרטים הבאים:

95529e3a682268b2.png

  1. לוחצים על a19a0c68bc4046e6.png התחלת ניפוי באגים.

הפעלה וגילוי של האפליקציה

האפליקציה צריכה להיות מופעלת באמולטור Android או בסימולטור של iOS. ממשק המשתמש הוא די פשוט. יש 2 לוחות משחקים; שחקן אנושי יכול להקיש על כל תא בלוח של הנציג בחלק העליון כמיקום פסילה. תאמנו סוכן חכם לחזות באופן אוטומטי את המיקום שבו הוא יכות על סמך לוח השחקן.

מתחת למכסה הקדמי, אפליקציית Flutter תשלח את הלוח הנוכחי של השחקן בקצה העורפי, שבו יופעל מודל של למידת חיזוק ותחזיר את המיקום הצפוי של התא שבו יוצג השחקן הבא. הקצה הקדמי יציג את התוצאה בממשק המשתמש לאחר קבלת התגובה.

734ab3d48a1133e1.png 15cba2e741149c95.png

אם לוחצים עכשיו על תא כלשהו בלוח של הנציג, לא יקרה כלום כי האפליקציה עדיין לא יכולה לתקשר עם הקצה העורפי.

7. שלב 1: יצירת סביבת Python של סוכני TensorFlow

המטרה העיקרית של ה-Codelab הזה היא לתכנן סוכן שלומד באמצעות אינטראקציה עם סביבה. משחק Plane Strike פשוט יחסית ואפשר ליצור כללים עבור סוכן NPC, אבל משתמשים בלמידת חיזוק כדי לאמן סוכן כדי ללמוד את המיומנויות וליצור סוכנים בקלות למשחקים אחרים בעתיד.

בהגדרה הרגילה של למידת חיזוק (RL), הנציג מקבל תצפית בכל שלב ובוחר פעולה. הפעולה מיושמת בסביבה והסביבה מחזירה תגמול ותצפית חדשה. הנציג אימון מדיניות כדי לבחור פעולות למיקסום סכום הפרסים, שנקראות גם 'החזרה'. כשהוא משחק במשחק הרבה פעמים, הסוכן יכול ללמוד את הדפוסים ולחדד את הכישורים שלו כדי ללמוד היטב את המשחק. כדי לנסח את משחק Plane Strike בתור בעיית RL, צריך להתייחס למצב הלוח בתור תצפית, למקם את הפסילה בתור הפעולה, ואת אות ההיט/החמצה בתור פרס.

bc5da07bc45062f4.png

כדי לאמן את סוכן ה-NPC באמצעות סוכני TensorFlow, ספרייה מהימנה, ניתנת להתאמה וקלה לשימוש ב-TensorFlow.

הכלי TF Agents הוא כלי מעולה ללמידת חיזוק כי הוא מגיע עם ערכה מקיפה של Codelabs, דוגמאות ומסמכי תיעוד מקיפים, שיעזרו לכם להתחיל. אפשר להשתמש בסוכני TF כדי לפתור בעיות RL מציאותיות ומורכבות עם מדרגיות, ולפתח אלגוריתמים חדשים של RL במהירות. אפשר לעבור בקלות בין סוכנים ואלגוריתמים שונים לצורך ניסוי. הוא גם נבדק היטב וקל להגדרה.

יש הרבה סביבות משחק שמובנות מראש ומוטמעות ב-OpenAI Gym (למשל, משחקי Atari), Mujuco וכו', שסוכני TF יכולים למנף בקלות. אבל מכיוון שהמשחק Plane Strike הוא משחק מותאם אישית לגמרי, קודם צריך להטמיע סביבה חדשה מאפס.

כדי להטמיע סביבת Python ב-TF Agents, צריך להטמיע את השיטות הבאות:

class YourGameEnv(py_environment.PyEnvironment):

  def __init__(self):
    """Initialize environment."""


  def action_spec(self):
    """Return action_spec."""


  def observation_spec(self):
    """Return observation_spec."""


  def _reset(self):
    """Return initial_time_step."""


  def _step(self, action):
    """Apply action and return new time_step."""

הפונקציה החשובה ביותר היא הפונקציה _step(), שמבצעת פעולה ומחזירה אובייקט time_step חדש. במקרה של המשחק Plane Strike, יש לכם לוח משחק; כשמתקבלת מיקום התראה חדש, בהתאם לתנאי לוח המשחק, הסביבה קובעת:

  • איך לוח המשחק צריך להיראות עכשיו (האם צריך לשנות את צבע התא לאדום או לצהוב, בהינתן המיקום המוסתר של המטוס?)
  • איזה פרס צריך לקבל השחקן על המיקום הזה (פגיעה בפרס או בהחמצה של עונש?)
  • האם המשחק הסתיים (האם מישהו ניצח?)
  • מוסיפים את הקוד הבא לפונקציה _step() לקובץ _planestrike_py_environment.py:
if self._hit_count == self._plane_size:
    self._episode_ended = True
    return self.reset()

if self._strike_count + 1 == self._max_steps:
    self.reset()
    return ts.termination(
        np.array(self._visible_board, dtype=np.float32), UNFINISHED_GAME_REWARD
    )

self._strike_count += 1
action_x = action // self._board_size
action_y = action % self._board_size
# Hit
if self._hidden_board[action_x][action_y] == HIDDEN_BOARD_CELL_OCCUPIED:
    # Non-repeat move
    if self._visible_board[action_x][action_y] == VISIBLE_BOARD_CELL_UNTRIED:
        self._hit_count += 1
        self._visible_board[action_x][action_y] = VISIBLE_BOARD_CELL_HIT
        # Successful strike
        if self._hit_count == self._plane_size:
            # Game finished
            self._episode_ended = True
            return ts.termination(
                np.array(self._visible_board, dtype=np.float32),
                FINISHED_GAME_REWARD,
            )
        else:
            self._episode_ended = False
            return ts.transition(
                np.array(self._visible_board, dtype=np.float32),
                HIT_REWARD,
                self._discount,
            )
    # Repeat strike
    else:
        self._episode_ended = False
        return ts.transition(
            np.array(self._visible_board, dtype=np.float32),
            REPEAT_STRIKE_REWARD,
            self._discount,
        )
# Miss
else:
    # Unsuccessful strike
    self._episode_ended = False
    self._visible_board[action_x][action_y] = VISIBLE_BOARD_CELL_MISS
    return ts.transition(
        np.array(self._visible_board, dtype=np.float32),
        MISS_REWARD,
        self._discount,

8. שלב 2: מאמנים את סוכן המשחק באמצעות סוכני TensorFlow

בסביבת TF Agents, אפשר לאמן את סוכן המשחק. בשביל ה-Codelab הזה צריך להשתמש בסוכן REINFORCE. REINFORCE הוא אלגוריתם הדרגתי של מדיניות ב-RL. הרעיון הבסיסי הוא להתאים את הפרמטרים של רשת הנוירונים למדיניות בהתאם לאותות הפרסים שנאספים במהלך המשחק, כדי שרשת המדיניות תוכל למקסם את ההחזר במהלכים עתידיים.

  • קודם כל צריך ליצור את סביבות האימון וההערכה. מוסיפים את הקוד הבא לפונקציה train_agent() בקובץ step2/backend/training.py:
train_py_env = planestrike_py_environment.PlaneStrikePyEnvironment(
    board_size=BOARD_SIZE, discount=DISCOUNT, max_steps=BOARD_SIZE**2
)
eval_py_env = planestrike_py_environment.PlaneStrikePyEnvironment(
    board_size=BOARD_SIZE, discount=DISCOUNT, max_steps=BOARD_SIZE**2
)

train_env = tf_py_environment.TFPyEnvironment(train_py_env)
eval_env = tf_py_environment.TFPyEnvironment(eval_py_env)
  • בשלב הבא צריך ליצור סוכן ללמידה של חיזוק שאמור לעבור הדרכה. ב-Codelab הזה משתמשים בסוכן REINFORCE, שהוא סוכן מבוסס-מדיניות. מוסיפים את הקוד הבא ממש מתחת לקוד שלמעלה:
actor_net = tfa.networks.Sequential(
    [
        tfa.keras_layers.InnerReshape([BOARD_SIZE, BOARD_SIZE], [BOARD_SIZE**2]),
        tf.keras.layers.Dense(FC_LAYER_PARAMS, activation="relu"),
        tf.keras.layers.Dense(BOARD_SIZE**2),
        tf.keras.layers.Lambda(lambda t: tfp.distributions.Categorical(logits=t)),
    ],
    input_spec=train_py_env.observation_spec(),
)

optimizer = tf.keras.optimizers.Adam(learning_rate=LEARNING_RATE)

train_step_counter = tf.Variable(0)

tf_agent = reinforce_agent.ReinforceAgent(
    train_env.time_step_spec(),
    train_env.action_spec(),
    actor_network=actor_net,
    optimizer=optimizer,
    normalize_returns=True,
    train_step_counter=train_step_counter,
)
  • לבסוף, מאמנים את הנציג בלולאת האימון. בלולאה, קודם כול צריך לאסוף כמה פרקים של מהלכים במשחק למאגר נתונים, ואז לאמן את הסוכן בעזרת הנתונים שבמאגר. מוסיפים את הקוד הבא לפונקציה train_agent() בקובץ step2/backend/training.py:
# Collect a few episodes using collect_policy and save to the replay buffer.
collect_episode(
    train_py_env,
    collect_policy,
    COLLECT_EPISODES_PER_ITERATION,
    replay_buffer_observer,
)

# Use data from the buffer and update the agent's network.
iterator = iter(replay_buffer.as_dataset(sample_batch_size=1))
trajectories, _ = next(iterator)
tf_agent.train(experience=trajectories)
replay_buffer.clear()
  • עכשיו תוכלו להתחיל את ההדרכה. בטרמינל, נכנסים לתיקייה step2/backend במחשב ומריצים את הפקודה:
python training.py

תהליך האימון נמשך 8-12 שעות, בהתאם לתצורות החומרה (אין צורך להשלים את כל האימון לבד, כי מודל שעבר אימון מראש זמין ב-step3). בינתיים, תוכלו לעקוב אחר ההתקדמות באמצעות TensorBoard. פותחים טרמינל חדש, נכנסים לתיקייה step2/backend במחשב ומריצים את הפקודה:

tensorboard --logdir tf_agents_log/

tf_agents_log היא התיקייה שמכילה את יומן האימון. הרצת אימון לדוגמה נראית כך:

33e12e2b387c063a.png 8488632ccf43348a.png

אפשר לראות שאורך הפרק הממוצע יורד וההחזר הממוצע גדל ככל שהאימון מתקדם. באופן אינטואיטיבי, אתם יכולים להבין שאם הסוכן חכם יותר ויספק תחזיות טובות יותר, משך המשחק יהיה קצר יותר והסוכן יצבור יותר פרסים. זה הגיוני כי הסוכן רוצה לסיים את המשחק בפחות שלבים כדי לצמצם את הנחת הפרסים המשמעותית בשלבים הבאים.

אחרי שהאימון מסתיים, המודל שעבר אימון מיוצא לתיקייה policy_model.

9. שלב 3: פריסת המודל שעבר אימון באמצעות מילוי בקשות של TensorFlow

עכשיו, אחרי שהדרכתם את סוכן המשחק, תוכלו לפרוס אותו באמצעות TensorFlow הצגה.

  • בטרמינל, נכנסים לתיקייה step3/backend במחשב ומתחילים להציג את TensorFlow באמצעות Docker:
docker run -t --rm -p 8501:8501 -p 8500:8500 -v "$(pwd)/backend/policy_model:/models/policy_model" -e MODEL_NAME=policy_model tensorflow/serving

Docker מוריד באופן אוטומטי את תמונת ההצגה של TensorFlow, תוך דקה. לאחר מכן, ההצגה של TensorFlow אמורה להתחיל. היומן אמור להיראות כמו קטע הקוד הבא:

2022-05-30 02:38:54.147771: I tensorflow_serving/model_servers/server.cc:89] Building single TensorFlow model file config:  model_name: policy_model model_base_path: /models/policy_model
2022-05-30 02:38:54.148222: I tensorflow_serving/model_servers/server_core.cc:465] Adding/updating models.
2022-05-30 02:38:54.148273: I tensorflow_serving/model_servers/server_core.cc:591]  (Re-)adding model: policy_model
2022-05-30 02:38:54.262684: I tensorflow_serving/core/basic_manager.cc:740] Successfully reserved resources to load servable {name: policy_model version: 123}
2022-05-30 02:38:54.262768: I tensorflow_serving/core/loader_harness.cc:66] Approving load for servable version {name: policy_model version: 123}
2022-05-30 02:38:54.262787: I tensorflow_serving/core/loader_harness.cc:74] Loading servable version {name: policy_model version: 123}
2022-05-30 02:38:54.265010: I external/org_tensorflow/tensorflow/cc/saved_model/reader.cc:38] Reading SavedModel from: /models/policy_model/123
2022-05-30 02:38:54.277811: I external/org_tensorflow/tensorflow/cc/saved_model/reader.cc:90] Reading meta graph with tags { serve }
2022-05-30 02:38:54.278116: I external/org_tensorflow/tensorflow/cc/saved_model/reader.cc:132] Reading SavedModel debug info (if present) from: /models/policy_model/123
2022-05-30 02:38:54.280229: I external/org_tensorflow/tensorflow/core/platform/cpu_feature_guard.cc:142] This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN) to use the following CPU instructions in performance-critical operations:  AVX2 FMA
To enable them in other operations, rebuild TensorFlow with the appropriate compiler flags.
2022-05-30 02:38:54.332352: I external/org_tensorflow/tensorflow/cc/saved_model/loader.cc:206] Restoring SavedModel bundle.
2022-05-30 02:38:54.337000: I external/org_tensorflow/tensorflow/core/platform/profile_utils/cpu_utils.cc:114] CPU Frequency: 2193480000 Hz
2022-05-30 02:38:54.402803: I external/org_tensorflow/tensorflow/cc/saved_model/loader.cc:190] Running initialization op on SavedModel bundle at path: /models/policy_model/123
2022-05-30 02:38:54.410707: I external/org_tensorflow/tensorflow/cc/saved_model/loader.cc:277] SavedModel load for tags { serve }; Status: success: OK. Took 145695 microseconds.
2022-05-30 02:38:54.412726: I tensorflow_serving/servables/tensorflow/saved_model_warmup_util.cc:59] No warmup data file found at /models/policy_model/123/assets.extra/tf_serving_warmup_requests
2022-05-30 02:38:54.417277: I tensorflow_serving/core/loader_harness.cc:87] Successfully loaded servable version {name: policy_model version: 123}
2022-05-30 02:38:54.419846: I tensorflow_serving/model_servers/server_core.cc:486] Finished adding/updating models
2022-05-30 02:38:54.420066: I tensorflow_serving/model_servers/server.cc:367] Profiler service is enabled
2022-05-30 02:38:54.428339: I tensorflow_serving/model_servers/server.cc:393] Running gRPC ModelServer at 0.0.0.0:8500 ...
[warn] getaddrinfo: address family for nodename not supported
2022-05-30 02:38:54.431620: I tensorflow_serving/model_servers/server.cc:414] Exporting HTTP/REST API at:localhost:8501 ...
[evhttp_server.cc : 245] NET_LOG: Entering the event loop ...

אתם יכולים לשלוח בקשה לדוגמה לנקודת הקצה (endpoint) כדי לוודא שהיא פועלת כצפוי:

curl -d '{"signature_name":"action","instances":[{"0/discount":0.0,"0/observation":[[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,     0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]],"0/reward":0.0,"0/step_type":0}]}'     -X POST http://localhost:8501/v1/models/policy_model:predict

נקודת הקצה תחזיר את המיקום הצפוי 45, שהוא (5, 5) במרכז הלוח (לסקרנים, אפשר לנסות להבין למה מרכז הלוח יכול לנחש טוב את מיקום ההתראה הראשונה).

{
    "predictions": [45]
}

זהו! יצרתם בהצלחה קצה עורפי לחיזוי מיקום ההתראה הבאה עבור סוכן NPC.

10. שלב 4: יוצרים את האפליקציה Flutter ל-Android ול-iOS

הקצה העורפי מוכן. אפשר להתחיל לשלוח אליו בקשות כדי לאחזר חיזויים של מיקומי התראה מאפליקציית Flutter.

  • קודם כל צריך להגדיר מחלקה שמרכזת את ערכי הקלט לשליחה. מוסיפים את הקוד הבא לקובץ step4/frontend/lib/game_agent.dart:
class Inputs {
  final List<double> _boardState;
  Inputs(this._boardState);

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = <String, dynamic>{};
    data['0/discount'] = [0.0];
    data['0/observation'] = [_boardState];
    data['0/reward'] = [0.0];
    data['0/step_type'] = [0];
    return data;
  }
}

עכשיו אפשר לשלוח את הבקשה ל-TensorFlow serving כדי לבצע חיזויים.

  • מוסיפים את הקוד הבא לפונקציה predict() בקובץ step4/frontend/lib/game_agent.dart:
var flattenedBoardState = boardState.expand((i) => i).toList();
final response = await http.post(
  Uri.parse('http://$server:8501/v1/models/policy_model:predict'),
  body: jsonEncode(<String, dynamic>{
    'signature_name': 'action',
    'instances': [Inputs(flattenedBoardState)]
  }),
);

if (response.statusCode == 200) {
  var output = List<int>.from(
      jsonDecode(response.body)['predictions'] as List<dynamic>);
  return output[0];
} else {
  throw Exception('Error response');
}

אחרי שהאפליקציה מקבלת את התשובה מהקצה העורפי, מעדכנים את ממשק המשתמש של המשחק כך שישקף את ההתקדמות במשחק.

  • מוסיפים את הקוד הבא לפונקציה _gridItemTapped() בקובץ step4/frontend/lib/main.dart:
int agentAction =
    await _policyGradientAgent.predict(_playerVisibleBoardState);
_agentActionX = agentAction ~/ _boardSize;
_agentActionY = agentAction % _boardSize;
if (_playerHiddenBoardState[_agentActionX][_agentActionY] ==
    hiddenBoardCellOccupied) {
  // Non-repeat move
  if (_playerVisibleBoardState[_agentActionX][_agentActionY] ==
      visibleBoardCellUntried) {
    _agentHitCount++;
  }
  _playerVisibleBoardState[_agentActionX][_agentActionY] =
      visibleBoardCellHit;
} else {
  _playerVisibleBoardState[_agentActionX][_agentActionY] =
      visibleBoardCellMiss;
}
setState(() {});

הפעלה

  1. לוחצים על a19a0c68bc4046e6.png התחלת ניפוי באגים ומחכים עד שהאפליקציה תיטען.
  2. מקישים על תא כלשהו בלוח של הנציג כדי להתחיל את המשחק.

852942d0de299c1f.png 6ae3601470c8e33a.png

11. שלב 5: מפעילים את האפליקציה Flutter לפלטפורמות של מחשבים

בנוסף ל-Android ול-iOS, אפליקציית Flutter תומכת גם בפלטפורמות למחשב, כולל Linux, Mac ו-Windows.

Linux

  1. צריך לוודא שמכשיר היעד מוגדר לערך 86cba523de82b4f9.png בשורת הסטטוס של VSCode.
  2. לוחצים על a19a0c68bc4046e6.png התחלת ניפוי באגים ומחכים עד שהאפליקציה תיטען.
  3. לוחצים על תא כלשהו בלוח של הנציג כדי להתחיל את המשחק.

48594c7c0a589733.png

Mac

  1. ב-Mac צריך להגדיר את ההרשאות המתאימות כי האפליקציה תשלח בקשות HTTP לקצה העורפי. לפרטים נוספים, ניתן לעיין בהרשאות וארגז החול של האפליקציות.

מוסיפים את הקוד הזה אל step4/frontend/macOS/Runner/DebugProfile.entitlements ואל step4/frontend/macOS/Runner/Release.entitlements בהתאמה:

<key>com.apple.security.network.client</key>
<true/>
  1. צריך לוודא שמכשיר היעד מוגדר לערך eb4b0b5563824138.png בשורת הסטטוס של VSCode.
  2. לוחצים על a19a0c68bc4046e6.png התחלת ניפוי באגים ומחכים עד שהאפליקציה תיטען.
  3. לוחצים על תא כלשהו בלוח של הנציג כדי להתחיל את המשחק.

55a5de3674194e89.png

Windows

  1. צריך לוודא שמכשיר היעד מוגדר לערך 9587be1bb375bc0f.png בשורת הסטטוס של VSCode.
  2. לוחצים על a19a0c68bc4046e6.png התחלת ניפוי באגים ומחכים עד שהאפליקציה תיטען.
  3. לוחצים על תא כלשהו בלוח של הנציג כדי להתחיל את המשחק.

41d9f87d84c5e755.png

12. שלב 6: מפעילים את אפליקציית Flutter לפלטפורמת האינטרנט

דבר נוסף שניתן לעשות הוא להוסיף תמיכה באינטרנט לאפליקציית Flutter. כברירת מחדל, פלטפורמת האינטרנט מופעלת באופן אוטומטי עבור אפליקציות Flutter, כך שכל מה שצריך לעשות הוא להפעיל אותה.

  1. צריך לוודא שמכשיר היעד מוגדר בתור 71db93efa928d15d.png בשורת הסטטוס של VSCode.
  2. לוחצים על a19a0c68bc4046e6.png התחלת ניפוי באגים ומחכים עד שהאפליקציה תיטען בדפדפן Chrome.
  3. לוחצים על תא כלשהו בלוח של הנציג כדי להתחיל את המשחק.

fae7490304e28dfe.png

13. מזל טוב

יצרת אפליקציה של משחק לוח בעזרת סוכן מבוסס-ML כדי לשחק נגד השחקן האנושי!

מידע נוסף