Créer un jeu de société avec les agents TensorFlow et Flutter

1. Avant de commencer

Les avancées spectaculaires d'AlphaGo et d'AlphaStar ont démontré le potentiel du machine learning pour créer des agents de jeu de niveau surhumain. Créer un petit jeu basé sur le ML est un exercice amusant pour acquérir les compétences nécessaires à la création d'agents de jeu puissants.

Dans cet atelier de programmation, vous allez apprendre à créer un jeu de société à l'aide des éléments suivants :

  • TensorFlow Agent pour entraîner un agent de jeu avec l'apprentissage par renforcement
  • TensorFlow Serving pour diffuser le modèle
  • Flutter pour créer une application de jeu de société multiplate-forme

Prérequis

  • Connaissances de base du développement Flutter avec Dart
  • Connaissances de base du machine learning avec TensorFlow, telles que l'entraînement par rapport au déploiement
  • Connaissances de base de Python, des terminaux et de Docker

Points abordés

  • Entraîner un agent de personnage non-joueur (PNJ) à l'aide de TensorFlow Agents
  • Diffuser le modèle entraîné à l'aide de TensorFlow Serving
  • Créer un jeu de société multiplate-forme avec Flutter

Prérequis

2. The Plane Strike Game

Le jeu que vous allez créer dans cet atelier de programmation s'appelle "Plane Strike". Il s'agit d'un petit jeu de société à deux joueurs qui ressemble au jeu de société Battleship. Les règles sont très simples :

  • Le joueur humain affronte un agent PNJ entraîné par le machine learning. Le joueur humain peut commencer la partie en appuyant sur n'importe quelle cellule du plateau de l'agent.
  • Au début du jeu, le joueur humain et l'agent disposent chacun d'un objet "avion" (huit cellules vertes formant un "avion", comme vous pouvez le voir sur le plateau du joueur humain dans l'animation ci-dessous) sur leur propre plateau. Ces "avions" sont placés de manière aléatoire et ne sont visibles que par les propriétaires du plateau, et non par leurs adversaires.
  • Le joueur humain et l'agent frappent à tour de rôle une cellule du plateau de l'autre. Le joueur humain peut appuyer sur n'importe quelle cellule du plateau de l'agent, tandis que l'agent fera automatiquement son choix en fonction de la prédiction d'un modèle de machine learning. La cellule tentée devient rouge s'il s'agit d'une cellule "avion" ("touché"), sinon elle devient jaune ("manqué").
  • Le premier joueur à obtenir huit cellules rouges remporte la partie, qui est ensuite relancée avec de nouveaux plateaux.

Voici un exemple de gameplay :

77cead530c5a4aff.gif

3. Configurer votre environnement de développement Flutter

Pour le développement Flutter, vous avez besoin de deux logiciels pour réaliser cet atelier de programmation : le SDK Flutter et un éditeur.

Vous pouvez exécuter l'atelier de programmation sur l'un des appareils suivants :

  • Le simulateur iOS (les outils Xcode doivent être installés)
  • Android Emulator (à configurer dans Android Studio)
  • Un navigateur (Chrome est requis pour le débogage)
  • En tant qu'application de bureau Windows, Linux ou macOS. Vous devez développer votre application sur la plate-forme où vous comptez la déployer. Par exemple, si vous voulez développer une application de bureau Windows, vous devez le faire sous Windows pour accéder à la chaîne de compilation appropriée. Les exigences spécifiques aux systèmes d'exploitation sont détaillées sur docs.flutter.dev/desktop.

4. Configuration

Pour télécharger le code de cet atelier de programmation, procédez comme suit :

  1. Accédez au dépôt GitHub pour cet atelier de programmation.
  2. Cliquez sur Code > Download ZIP (Code > Télécharger le fichier ZIP) afin de télécharger l'ensemble du code pour cet atelier de programmation.

2cd45599f51fb8a2.png

  1. Décompressez le fichier ZIP téléchargé pour accéder au dossier racine codelabs-main contenant toutes les ressources nécessaires.

Pour cet atelier de programmation, vous n'avez besoin que des fichiers du sous-répertoire tfagents-flutter/ dans le dépôt, qui contient plusieurs dossiers :

  • Les dossiers step0 à step6 contiennent le code de démarrage sur lequel s'appuie chaque étape de cet atelier de programmation.
  • Le dossier finished contient le code final de l'application exemple.
  • Chaque dossier contient un sous-dossier backbend, qui inclut le code de backend, et un sous-dossier frontend, qui inclut le code de frontend Flutter.

5. Télécharger les dépendances pour le projet

Backend

Ouvrez votre terminal et accédez au sous-dossier tfagents-flutter. Exécutez la commande suivante :

pip install -r requirements.txt

Interface

  1. Dans VS Code, cliquez sur File > Open folder (Fichier > Ouvrir le dossier), puis sélectionnez le dossier step0 dans le code source que vous avez téléchargé précédemment.
  2. Ouvrir le fichier step0/frontend/lib/main.dart. Si une boîte de dialogue VS Code vous invite à télécharger les packages requis pour l'application de démarrage, cliquez sur Get packages (Télécharger les packages).
  3. Si cette boîte de dialogue ne s'affiche pas, ouvrez votre terminal, puis exécutez la commande flutter pub get dans le dossier step0/frontend.

7ada07c300f166a6.png

6. Étape 0 : Exécuter l'application de départ

  1. Ouvrez le fichier step0/frontend/lib/main.dart dans VS Code, assurez-vous qu'Android Emulator ou le simulateur iOS est correctement configuré et s'affiche dans la barre d'état.

Par exemple, voici ce que vous voyez lorsque vous utilisez le Pixel 5 avec Android Emulator :

9767649231898791.png

Voici ce qui s'affiche lorsque vous utilisez l'iPhone 13 avec le simulateur iOS :

95529e3a682268b2.png

  1. Cliquez sur l'icône Démarrer le débogage a19a0c68bc4046e6.png.

Exécuter et explorer l'application

L'application devrait se lancer sur Android Emulator ou le simulateur iOS. L'UI est assez simple. Il existe deux plateaux de jeu. Un joueur humain peut appuyer sur n'importe quelle cellule du plateau de l'agent en haut de l'écran pour indiquer une position de frappe. Vous allez entraîner un agent intelligent à prédire automatiquement où frapper en fonction du plateau du joueur humain.

En arrière-plan, l'application Flutter envoie le plateau de jeu actuel du joueur humain au backend, qui exécute un modèle d'apprentissage par renforcement et renvoie une position de cellule prédite à frapper ensuite. Une fois la réponse reçue, le frontend affichera le résultat dans l'UI.

734ab3d48a1133e1.png 15cba2e741149c95.png

Si vous cliquez sur une cellule du tableau de l'agent maintenant, rien ne se passe, car l'application ne peut pas encore communiquer avec le backend.

7. Étape 1 : Créez un environnement Python TensorFlow Agents

L'objectif principal de cet atelier de programmation est de concevoir un agent qui apprend en interagissant avec un environnement. Bien que le jeu Plane Strike soit relativement simple et qu'il soit possible de créer manuellement des règles pour l'agent PNJ, vous utilisez l'apprentissage par renforcement pour entraîner un agent afin d'acquérir les compétences nécessaires et de pouvoir créer facilement des agents pour d'autres jeux à l'avenir.

Dans le paramètre standard de l'apprentissage par renforcement (RL), l'agent reçoit une observation à chaque étape et choisit une action. L'action est appliquée à l'environnement, qui renvoie une récompense et une nouvelle observation. L'agent entraîne une stratégie pour choisir des actions afin de maximiser la somme des récompenses, également appelée "retour". En jouant de nombreuses fois, l'agent est capable d'apprendre les schémas et d'affûter ses compétences pour maîtriser le jeu. Pour formuler le jeu Plane Strike comme un problème de RL, considérez l'état du plateau comme l'observation, une position de frappe comme l'action et le signal de touche/manque comme la récompense.

bc5da07bc45062f4.png

Pour entraîner l'agent PNJ, vous utilisez TensorFlow Agents, une bibliothèque d'apprentissage par renforcement fiable, évolutive et facile à utiliser pour TensorFlow.

TF-Agents est idéal pour l'apprentissage par renforcement, car il est fourni avec un ensemble complet d'ateliers de programmation, d'exemples et une documentation détaillée pour vous aider à vous lancer. Vous pouvez utiliser TF-Agents pour résoudre des problèmes de RL réalistes et complexes avec une grande évolutivité, et développer rapidement de nouveaux algorithmes de RL. Vous pouvez facilement passer d'un agent ou d'un algorithme à un autre pour effectuer des tests. Il est également bien testé et facile à configurer.

De nombreux environnements de jeu prédéfinis sont implémentés dans OpenAI Gym (par exemple, les jeux Atari), Mujuco, etc., que TF-Agents peut facilement exploiter. Toutefois, comme le jeu Plane Strike est un jeu personnalisé complet, vous devez d'abord implémenter un nouvel environnement à partir de zéro.

Pour implémenter un environnement Python TF-Agents, vous devez implémenter les méthodes suivantes :

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."""

La plus importante est la fonction _step(), qui accepte une action et renvoie un nouvel objet time_step. Dans le cas du jeu Plane Strike, vous disposez d'un plateau de jeu. Lorsqu'une nouvelle position de frappe arrive, l'environnement détermine, en fonction de l'état du plateau de jeu :

  • À quoi le plateau de jeu devrait-il ressembler ensuite (la cellule doit-elle changer de couleur pour devenir rouge ou jaune, compte tenu de l'emplacement de l'avion caché) ?
  • Quelle récompense le joueur doit-il recevoir pour cette position (récompense pour un coup réussi ou pénalité pour un coup manqué) ?
  • La partie doit-elle se terminer (quelqu'un a-t-il gagné) ?
  • Ajoutez le code suivant à la fonction _step() du fichier _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. Étape 2 : Entraîner l'agent de jeu avec TensorFlow Agents

Une fois l'environnement TF-Agents en place, vous pouvez entraîner l'agent de jeu. Pour cet atelier de programmation, vous utilisez un agent REINFORCE. REINFORCE est un algorithme de gradient de stratégie dans l'apprentissage par renforcement. L'idée de base est d'ajuster les paramètres du réseau de neurones de la stratégie en fonction des signaux de récompense collectés pendant le jeu, afin que le réseau de stratégie puisse maximiser le retour lors des prochaines parties.

  • Tout d'abord, vous devez instancier les environnements d'entraînement et d'évaluation. Ajoutez ce code à la fonction train_agent() dans le fichier 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)
  • Ensuite, vous devez créer un agent d'apprentissage par renforcement qui sera entraîné. Dans cet atelier de programmation, vous allez utiliser l'agent REINFORCE, qui est un agent basé sur une stratégie. Ajoutez ce code juste en dessous du code ci-dessus :
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,
)
  • Enfin, entraînez l'agent dans la boucle d'entraînement. Dans la boucle, vous collectez d'abord quelques épisodes de parties dans un tampon, puis vous entraînez l'agent avec les données mises en mémoire tampon. Ajoutez ce code à la fonction train_agent() dans le fichier 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()
  • Vous pouvez maintenant lancer l'entraînement. Dans votre terminal, accédez au dossier step2/backend sur votre ordinateur et exécutez la commande suivante :
python training.py

L'entraînement prend entre 8 et 12 heures, selon la configuration matérielle (vous n'avez pas besoin de terminer l'entraînement vous-même, car un modèle préentraîné est fourni dans step3). En attendant, vous pouvez suivre la progression avec TensorBoard. Ouvrez un nouveau terminal, accédez au dossier step2/backend sur votre ordinateur et exécutez la commande suivante :

tensorboard --logdir tf_agents_log/

tf_agents_log est le dossier qui contient le journal d'entraînement. Voici un exemple d'exécution d'entraînement :

33e12e2b387c063a.png 8488632ccf43348a.png

Vous pouvez constater que la durée moyenne des épisodes diminue et que le rendement moyen augmente à mesure que l'entraînement progresse. Intuitivement, vous pouvez comprendre que si l'agent est plus intelligent et fait de meilleures prédictions, la durée du jeu devient plus courte et l'agent collecte plus de récompenses. Cela est logique, car l'agent souhaite terminer le jeu en moins d'étapes pour minimiser la forte réduction de la récompense lors des dernières étapes.

Une fois l'entraînement terminé, le modèle entraîné est exporté vers le dossier policy_model.

9. Étape 3 : Déployez le modèle entraîné avec TensorFlow Serving

Maintenant que vous avez entraîné l'agent de jeu, vous pouvez le déployer avec TensorFlow Serving.

  • Dans votre terminal, accédez au dossier step3/backend sur votre ordinateur et démarrez TensorFlow Serving avec 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 commence par télécharger automatiquement l'image TensorFlow Serving, ce qui prend une minute. Le service TensorFlow Serving devrait alors démarrer. Le journal doit se présenter comme cet extrait de code :

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 ...

Vous pouvez envoyer un exemple de requête au point de terminaison pour vous assurer qu'il fonctionne comme prévu :

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

Le point de terminaison renverra une position prédite 45, qui est (5, 5) au centre du plateau (pour les curieux, vous pouvez essayer de comprendre pourquoi le centre du plateau est une bonne estimation pour la première position de frappe).

{
    "predictions": [45]
}

Et voilà ! Vous avez créé un backend pour prédire la prochaine position de frappe de l'agent PNJ.

10. Étape 4 : Créer l'application Flutter pour Android et iOS

Le backend est prêt. Vous pouvez commencer à lui envoyer des requêtes pour récupérer les prédictions de position de frappe à partir de l'application Flutter.

  • Vous devez d'abord définir une classe qui encapsule les entrées à envoyer. Ajoutez ce code au fichier 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;
  }
}

Vous pouvez maintenant envoyer la requête à TensorFlow Serving pour effectuer des prédictions.

  • Ajoutez ce code à la fonction predict() dans le fichier 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');
}

Une fois que l'application reçoit la réponse du backend, vous mettez à jour l'UI du jeu pour refléter la progression du jeu.

  • Ajoutez ce code à la fonction _gridItemTapped() dans le fichier 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(() {});

Exécuter l'application

  1. Cliquez sur l'icône Démarrer le débogage a19a0c68bc4046e6.png, puis attendez que l'application se charge.
  2. Appuyez sur n'importe quelle cellule du plateau de l'agent pour commencer la partie.

852942d0de299c1f.png 6ae3601470c8e33a.png

11. Étape 5 : Activez l'application Flutter pour les plates-formes de bureau

En plus d'Android et d'iOS, Flutter est également compatible avec les plates-formes de bureau, y compris Linux, Mac et Windows.

Linux

  1. Assurez-vous que l'appareil cible est défini sur 86cba523de82b4f9.png dans la barre d'état de VSCode.
  2. Cliquez sur l'icône Démarrer le débogage a19a0c68bc4046e6.png, puis attendez que l'application se charge.
  3. Cliquez sur n'importe quelle cellule du plateau de l'agent pour commencer la partie.

48594c7c0a589733.png

Mac

  1. Pour Mac, vous devez configurer les droits d'accès appropriés, car l'application envoie des requêtes HTTP au backend. Pour en savoir plus, consultez Droits d'accès et bac à sable de l'application.

Ajoutez ce code à step4/frontend/macOS/Runner/DebugProfile.entitlements et step4/frontend/macOS/Runner/Release.entitlements, respectivement :

<key>com.apple.security.network.client</key>
<true/>
  1. Assurez-vous que l'appareil cible est défini sur eb4b0b5563824138.png dans la barre d'état de VSCode.
  2. Cliquez sur l'icône Démarrer le débogage a19a0c68bc4046e6.png, puis attendez que l'application se charge.
  3. Cliquez sur n'importe quelle cellule du plateau de l'agent pour commencer la partie.

55a5de3674194e89.png

Windows

  1. Assurez-vous que l'appareil cible est défini sur 9587be1bb375bc0f.png dans la barre d'état de VSCode.
  2. Cliquez sur l'icône Démarrer le débogage a19a0c68bc4046e6.png, puis attendez que l'application se charge.
  3. Cliquez sur n'importe quelle cellule du plateau de l'agent pour commencer la partie.

41d9f87d84c5e755.png

12. Étape 6 : Activez l'application Flutter pour la plate-forme Web

Vous pouvez également ajouter une compatibilité Web à l'application Flutter. Par défaut, la plate-forme Web est automatiquement activée pour les applications Flutter. Il vous suffit donc de la lancer.

  1. Assurez-vous que l'appareil cible est défini sur 71db93efa928d15d.png dans la barre d'état de VSCode.
  2. Cliquez sur l'icône Démarrer le débogage a19a0c68bc4046e6.png, puis attendez que l'application se charge dans le navigateur Chrome.
  3. Cliquez sur n'importe quelle cellule du plateau de l'agent pour commencer la partie.

fae7490304e28dfe.png

13. Félicitations

Vous avez créé une application de jeu de société avec un agent optimisé par le ML pour jouer contre le joueur humain.

En savoir plus