Tworzenie gry planszowej przy użyciu agentów TensorFlow i Flutter

1. Zanim zaczniesz

Niesamowite przełomowe rozwiązanie w dziedzinie AlphaGo i AlphaStar udowodniło, że można wykorzystać systemy uczące się do tworzenia agentów gier na poziomie superludzkich. To ciekawe ćwiczenie polegające na zbudowaniu małej gry opartej na ML, w której nauczysz się umiejętności potrzebnych do tworzenia potężnych agentów.

Z tego ćwiczenia w Codelabs dowiesz się, jak stworzyć grę planszową przy użyciu:

  • Agent TensorFlow do trenowania agenta gry z użyciem uczenia przez wzmacnianie
  • Udostępnianie modelu TensorFlow
  • Flutter tworzy wieloplatformową grę planszową

Wymagania wstępne

  • Podstawowa wiedza o rozwoju technologii Flutter w Dart
  • Podstawowa wiedza na temat systemów uczących się z wykorzystaniem TensorFlow, np. do trenowania i wdrażania
  • Podstawowa znajomość Pythona, terminali i Dockera

Czego się nauczysz

  • Jak wytrenować agenta postaci niezależnej (NPC) za pomocą agentów TensorFlow
  • Jak udostępnić wytrenowany model za pomocą TensorFlow Serving
  • Jak stworzyć wieloplatformową grę planszową Flutter

Czego potrzebujesz

2. Gra The Plane Strike

Stworzona w tym ćwiczeniu gra nosi nazwę „Plane Strike”, czyli małą dwuosobową grę planszową przypominającą grę planszową „Battleship”. Zasady są bardzo proste:

  • Gracz gra z agentem NPC wytrenowanym przez systemy uczące się. Gracz może rozpocząć grę, klikając dowolną komórkę na planszy agenta.
  • Na początku gry człowiek i agent mają „samolot” (8 zielonych komórek tworzących „płaszczyznę”, jak widać na planszy gracza na ilustracji poniżej) na jej własnej planszy; te „samoloty” są umieszczane losowo, widoczne tylko dla właścicieli planszy i ukryte dla przeciwników.
  • Gracz i agent uderzają na zmianę w jedną komórkę ze planszy przeciwnika. Gracz może kliknąć dowolną komórkę na planszy agenta, a agent sam dokona wyboru na podstawie prognozy modelu systemów uczących się. Komórka, którą próbowano wyświetlić, ma kolor czerwony, jeśli jest to „samolot” komórka („hit”); w przeciwnym razie zmieni kolor na żółty („miss”).
  • Gra, która zdobędzie 8 czerwonych komórek. gra jest ponownie uruchamiana z nowymi planszami.

Oto przykładowa rozgrywka:

77cead530c5a4aff.gif

3. Konfigurowanie środowiska programistycznego Flutter

Do programowania w technologii Flutter potrzebujesz 2 programów do ukończenia ćwiczenia – pakietu SDK Flutter i edytora.

Ćwiczenie z programowania możesz uruchomić na dowolnym z tych urządzeń:

  • Symulator iOS (wymaga zainstalowania narzędzi Xcode).
  • Emulator Androida (wymaga skonfigurowania Android Studio).
  • Przeglądarka (do debugowania wymagany jest Chrome).
  • Aplikacja komputerowa w systemie Windows, Linux lub macOS Programowanie należy tworzyć na platformie, na której zamierzasz wdrożyć usługę. Jeśli więc chcesz opracować aplikację komputerową dla systemu Windows, musisz to zrobić w tym systemie, aby uzyskać dostęp do odpowiedniego łańcucha kompilacji. Istnieją wymagania związane z konkretnymi systemami operacyjnymi, które zostały szczegółowo omówione na stronie docs.flutter.dev/desktop.

4. Konfiguracja

Aby pobrać kod do tego ćwiczenia z programowania:

  1. Aby przeprowadzić ten moduł, przejdź do repozytorium GitHub.
  2. Kliknij Kod > Pobierz plik ZIP, aby pobrać cały kod do tego ćwiczenia z programowania.

2cd45599f51fb8a2.png

  1. Rozpakuj pobrany plik ZIP, aby rozpakować folder główny codelabs-main ze wszystkimi potrzebnymi zasobami.

Aby wykonać te ćwiczenia w Codelabs, potrzebujesz tylko plików w podkatalogu tfagents-flutter/ repozytorium, które zawiera wiele folderów:

  • Foldery od step0 do step6 zawierają kod startowy, który powstał w każdym kroku tego ćwiczenia z programowania.
  • Folder finished zawiera kompletny kod gotowej przykładowej aplikacji.
  • Każdy folder zawiera podfolder backbend z kodem backendu i podfolder frontend zawierający kod frontendu Flutter

5. Pobierz zależności w projekcie

Backend

Otwórz terminal i przejdź do podfolderu tfagents-flutter. Wykonaj zapytanie:

pip install -r requirements.txt

Frontend

  1. W sekcji VS Code kliknij File (Plik) > Otwórz folder, a następnie wybierz folder step0 z pobranego wcześniej kodu źródłowego.
  2. Otwórz plik step0/frontend/lib/main.dart. Jeśli pojawi się okno VS Code z prośbą o pobranie pakietów wymaganych do aplikacji startowej, kliknij Pobierz pakiety.
  3. Jeśli nie widzisz tego okna, otwórz terminal i uruchom polecenie flutter pub get w folderze step0/frontend.

7ada07c300f166a6.png

6. Krok 0. Uruchom aplikację startową

  1. Otwórz plik step0/frontend/lib/main.dart w VS Code. Sprawdź, czy emulator Androida lub symulator iOS są prawidłowo skonfigurowane i wyświetlają się na pasku stanu.

Na przykład podczas używania Pixela 5 z emulatorem Androida możesz zobaczyć takie elementy:

9767649231898791.png

Oto, co możesz zobaczyć, używając iPhone'a 13 za pomocą symulatora iOS:

95529e3a682268b2.png

  1. Kliknij a19a0c68bc4046e6.png Rozpocznij debugowanie.

Uruchamianie i poznawanie aplikacji

Aplikacja powinna się uruchomić w emulatorze Androida lub symulatorze iOS. Interfejs jest dość prosty. Na gości czekają 2 plansze do gier. człowiek może kliknąć u góry dowolną komórkę na planszy agenta. Wytrenujesz agenta, aby automatycznie przewidywał, gdzie uderzyć, na podstawie planszy gracza.

Znajdująca się w nich aplikacja Flutter wysyła bieżącą planszę gracza do backendu, który uruchamia model uczenia się przez wzmocnienie i zwraca przewidywaną pozycję komórki, która ma zostać zaatakowana. Po otrzymaniu odpowiedzi frontend wyświetli wynik w interfejsie użytkownika.

734ab3d48a1133e1.png 15cba2e741149c95.png

Jeśli teraz klikniesz dowolną komórkę na tablicy agenta, nic się nie stanie, ponieważ aplikacja nie może jeszcze komunikować się z backendem.

7. Krok 1. Utwórz środowisko Pythona dla agentów TensorFlow

Głównym celem tych ćwiczeń w Codelabs jest zaprojektowanie agenta, który uczy się przez interakcję ze środowiskiem. Chociaż gra Plane Strike jest stosunkowo prosta i można opracować reguły dla agenta NPC, musisz wykorzystać uczenie się przez wzmacnianie, aby szkolić agenta, aby zdobyć nowe umiejętności i łatwo budować agentów do innych gier w przyszłości.

W standardowym ustawieniu uczenia się przez wzmacnianie (RL) agent otrzymuje obserwację w każdym kroku i wybiera działanie. Działanie jest wykonywane w środowisku, a środowisko zwraca nagrodę i nową obserwację. Agent uczy się zasad, aby wybierać działania mające na celu maksymalizację sumy nagród, inaczej nazywanych zwrotem. Wielokrotnie grając w grę, agent może poznać wzorce i szlifować swoje umiejętności, aby opanować rozgrywkę. Aby sformułować grę Plane Strike jako zagadnienie RL, potraktuj stan planszy jako obserwację, pozycję uderzenia jako działanie, a sygnał uderzenia/braku jako nagrodę.

bc5da07bc45062f4.png

Aby wytrenować agenta NPC, użyj agentów TensorFlow – niezawodna, skalowalna i łatwa w obsłudze biblioteka do uczenia przez wzmacnianie do TensorFlow.

Agenty TF świetnie się nadają do uczenia przez wzmacnianie, bo zawierają obszerny zestaw ćwiczeń z programowania, przykłady i obszerną dokumentację, które pomogą Ci zacząć. Agenty TF mogą służyć do rozwiązywania realistycznych i złożonych problemów z funkcją RL przy skalowalności oraz do szybkiego opracowywania nowych algorytmów RL. Możesz łatwo przełączać się między różnymi agentami i algorytmami eksperymentów. Usługa została dobrze przetestowana i łatwa w konfiguracji.

W OpenAI Gym jest zaimplementowanych wiele gotowych środowisk gier (np. gry Atari), Mujuco itp., które agenty TF mogą łatwo wykorzystać. Plane Strike to kompletna gra niestandardowa, więc najpierw musisz wdrożyć nowe środowisko od zera.

Aby wdrożyć środowisko agentów TF Python, musisz wdrożyć te metody:

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

Najważniejsza to funkcja _step(), która wykonuje działanie i zwraca nowy obiekt time_step. w przypadku gry Plane Strike masz planszę do gry. gdy pojawi się nowe uderzenie, w zależności od stanu planszy środowisko określa:

  • Jak powinna wyglądać plansza do gry w następnej kolejności (czy komórka powinna zmienić kolor na czerwony lub żółty w zależności od ukrytej lokalizacji samolotu?)
  • Jaką nagrodę powinien otrzymać zawodnik za tę pozycję (nagroda za trafienie lub kara za nieudane uderzenie?)
  • Czy należy zakończyć grę (czy ktoś wygrał?)
  • Dodaj ten kod do funkcji _step() w pliku _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. Krok 2. Wytrenuj agenta gry za pomocą agentów TensorFlow

Po wdrożeniu środowiska agentów TF możesz wytrenować agenta gry. W tym ćwiczeniu w Codelabs używasz agenta REINFORCE. REINFORCE to algorytm gradientu zasad w RL. Podstawowym założeniem jest dostosowanie parametrów sieci neuronowej zasad na podstawie sygnałów nagród zebranych podczas rozgrywki, tak aby sieć zasad mogła zmaksymalizować zwrot z kolejnych rozgrywek.

  • Najpierw trzeba utworzyć instancje środowisk trenowania i oceny. Dodaj ten kod do funkcji train_agent() w pliku 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)
  • Musisz utworzyć agenta uczenia przez wzmacnianie, który będzie trenowany. W tym ćwiczeniu w Codelabs używasz agenta REINFORCE, który jest agentem opartym na zasadach. Dodaj ten kod tuż pod kodem powyżej:
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,
)
  • Na koniec wytrenuj agenta w pętli trenowania. W pętli najpierw zbierasz w buforze kilka odcinków rozgrywki, a potem trenujesz agenta, korzystając z buforowanych danych. Dodaj ten kod do funkcji train_agent() w pliku 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()
  • Teraz możesz rozpocząć szkolenie. W terminalu przejdź do folderu step2/backend na komputerze i uruchom polecenie:
python training.py

W zależności od konfiguracji sprzętowej trenowanie może potrwać 8–12 godzin (nie musisz samodzielnie kończyć trenowania, ponieważ w step3 dostępny jest już wytrenowany model). W międzyczasie możesz śledzić postęp za pomocą usługi TensorBoard. Otwórz nowy terminal, przejdź do folderu step2/backend na komputerze i uruchom polecenie:

tensorboard --logdir tf_agents_log/

tf_agents_log to folder zawierający dziennik trenowania. Przykładowe uruchomienie treningowe wygląda tak:

33e12e2b387c063a.png 8488632ccf43348a.png

Widać, że średnia długość odcinka zmniejsza się i średnia wartość zwrotu wzrasta w miarę postępów trenowania. Intuicyjnie zrozumiesz, że jeśli agent jest mądrzejszy i lepiej przewiduje, gra staje się krótsza i zdobywa więcej nagród. Ma to sens, ponieważ agent chce ukończyć grę w mniejszej liczbie kroków, aby zminimalizować liczbę rabatów na nagrody w późniejszych krokach.

Po zakończeniu trenowania wytrenowany model zostanie wyeksportowany do folderu policy_model.

9. Krok 3. Wdróż wytrenowany model za pomocą TensorFlow Serving

Po wytrenowaniu agenta gry możesz wdrożyć go za pomocą TensorFlow Serving.

  • W terminalu otwórz folder step3/backend na komputerze i uruchom TensorFlow Serving with 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 automatycznie pobiera najpierw obraz TensorFlow Serving, co zajmuje minutę. Następnie powinna uruchomić się usługa TensorFlow Serving. Dziennik powinien wyglądać tak:

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

Aby sprawdzić, czy punkt końcowy działa zgodnie z oczekiwaniami, możesz wysłać przykładowe żądanie:

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

Punkt końcowy zwróci przewidywaną pozycję 45, czyli (5, 5) na środku planszy (jeśli jesteś ciekawostką, możesz spróbować dowiedzieć się, dlaczego środek planszy najlepiej przydaje się przy pierwszym uderzeniu).

{
    "predictions": [45]
}

Znakomicie. Udało Ci się zbudować backend, który przewiduje kolejne ostrzeżenie dla agenta NPC.

10. Krok 4. Utwórz aplikację Flutter na Androida i iOS

Backend jest gotowy. Możesz zacząć wysyłać do tego zespołu prośby, aby otrzymywać z aplikacji Flutter prognozy dotyczące pozycji ostrzeżenia.

  • Najpierw musisz zdefiniować klasę, która opakowuje dane wejściowe do wysłania. Dodaj ten kod do pliku 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;
  }
}

Teraz możesz wysłać żądanie do TensorFlow Serving, aby generować prognozy.

  • Dodaj ten kod do funkcji predict() w pliku 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');
}

Gdy aplikacja otrzyma odpowiedź z backendu, zaktualizujesz interfejs gry, aby odzwierciedlić postępy w grze.

  • Dodaj ten kod do funkcji _gridItemTapped() w pliku 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(() {});

Uruchom

  1. Kliknij a19a0c68bc4046e6.png Rozpocznij debugowanie i poczekaj na wczytanie aplikacji.
  2. Aby rozpocząć grę, kliknij dowolną komórkę na planszy agenta.

852942d0de299c1f.png 6ae3601470c8e33a.png

11. Krok 5. Włącz aplikację Flutter na platformach komputerowych

Oprócz Androida i iOS Flutter obsługuje także platformy komputerowe, takie jak Linux, Mac i Windows.

Linux

  1. Upewnij się, że urządzenie docelowe na pasku stanu VSCode jest ustawione na 86cba523de82b4f9.png.
  2. Kliknij a19a0c68bc4046e6.png Rozpocznij debugowanie i poczekaj na wczytanie aplikacji.
  3. Aby rozpocząć grę, kliknij dowolną komórkę na planszy agenta.

48594c7c0a589733.png

Mac

  1. W przypadku Maca musisz skonfigurować odpowiednie uprawnienia, ponieważ aplikacja będzie wysyłać żądania HTTP do backendu. Więcej informacji znajdziesz w artykule Uprawnienia i piaskownica aplikacji.

Dodaj ten kod odpowiednio do step4/frontend/macOS/Runner/DebugProfile.entitlements i step4/frontend/macOS/Runner/Release.entitlements:

<key>com.apple.security.network.client</key>
<true/>
  1. Upewnij się, że urządzenie docelowe na pasku stanu VSCode jest ustawione na eb4b0b5563824138.png.
  2. Kliknij a19a0c68bc4046e6.png Rozpocznij debugowanie i poczekaj na wczytanie aplikacji.
  3. Aby rozpocząć grę, kliknij dowolną komórkę na planszy agenta.

55a5de3674194e89.png

Windows

  1. Upewnij się, że urządzenie docelowe na pasku stanu VSCode jest ustawione na 9587be1bb375bc0f.png.
  2. Kliknij a19a0c68bc4046e6.png Rozpocznij debugowanie i poczekaj na wczytanie aplikacji.
  3. Aby rozpocząć grę, kliknij dowolną komórkę na planszy agenta.

41d9f87d84c5e755.png

12. Krok 6. Włącz aplikację Flutter na platformie internetowej

Możesz też dodać obsługę sieci do aplikacji Flutter. Domyślnie platforma internetowa jest automatycznie włączona dla aplikacji Flutter, więc wystarczy ją uruchomić.

  1. Upewnij się, że urządzenie docelowe jest ustawione na 71db93efa928d15d.png na pasku stanu VSCode.
  2. Kliknij a19a0c68bc4046e6.png Rozpocznij debugowanie i poczekaj na wczytanie aplikacji w przeglądarce Chrome.
  3. Aby rozpocząć grę, kliknij dowolną komórkę na planszy agenta.

fae7490304e28dfe.png

13. Gratulacje

Udało Ci się stworzyć aplikację do gry planszowej z pomocą agenta opartego na ML, w którym możesz zmierzyć się z człowiekiem.

Więcej informacji