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

1. Zanim zaczniesz

Niesamowity przełom w przypadku AlphaGoAlphaStar pokazał potencjał wykorzystania uczenia maszynowego do tworzenia agentów gier na poziomie przekraczającym możliwości człowieka. Stworzenie małej gry opartej na ML to świetne ćwiczenie, które pozwala zdobyć umiejętności potrzebne do tworzenia zaawansowanych agentów w grach.

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

  • Agent TensorFlow do trenowania agenta gry za pomocą uczenia ze wzmocnieniem
  • TensorFlow Serving do udostępniania modelu
  • Flutter do tworzenia aplikacji z grą planszową na wielu platformach

Wymagania wstępne

  • Podstawowa znajomość tworzenia aplikacji w Flutterze za pomocą języka Dart.
  • Podstawowa wiedza o uczeniu maszynowym za pomocą TensorFlow, np. różnice między trenowaniem a wdrażaniem.
  • Podstawowa znajomość Pythona, terminali i Dockera

Czego się nauczysz

  • Jak wytrenować agenta postaci niezależnej (NPC) za pomocą agentów TensorFlow
  • Jak udostępniać wytrenowany model za pomocą TensorFlow Serving
  • Tworzenie gry planszowej na wielu platformach w Flutterze

Czego potrzebujesz

2. The Plane Strike Game

Gra, którą stworzysz w tym ćwiczeniu, to „Plane Strike” – mała gra planszowa dla 2 graczy przypominająca „Bitwę morską”. Zasady są bardzo proste:

  • Gracz gra przeciwko agentowi NPC wytrenowanemu przez uczenie maszynowe. Gracz może rozpocząć grę, klikając dowolne pole na planszy agenta.
  • Na początku gry gracz i agent mają na swoich planszach obiekt „samolot” (8 zielonych komórek tworzących „samolot”, jak widać na planszy gracza w animacji poniżej). „Samoloty” są rozmieszczone losowo i widoczne tylko dla właścicieli planszy, a ukryte dla przeciwników.
  • Gracz i agent na zmianę atakują po jednym polu na planszy przeciwnika. Gracz może kliknąć dowolną komórkę na planszy agenta, a agent automatycznie dokona wyboru na podstawie prognozy modelu uczenia maszynowego. Próbowana komórka zmieni kolor na czerwony, jeśli jest komórką „samolotu” („trafienie”), w przeciwnym razie zmieni kolor na żółty („pudło”).
  • Wygrywa gracz, który jako pierwszy zdobędzie 8 czerwonych komórek. Następnie gra jest wznawiana z nowymi planszami.

Oto przykładowa rozgrywka:

77cead530c5a4aff.gif

3. Konfigurowanie środowiska programistycznego Fluttera

Aby ukończyć to ćwiczenie, potrzebujesz 2 elementów oprogramowania: pakietu SDK Flutteredytora.

Codelab możesz uruchomić na dowolnym z tych urządzeń:

  • Symulator iOS (wymaga zainstalowania narzędzi Xcode).
  • Android Emulator (wymaga konfiguracji w Android Studio).
  • przeglądarka (do debugowania wymagana jest Chrome);
  • Jako aplikacja komputerowa na Windows, Linux lub macOS. Musisz tworzyć aplikację na platformie, na której zamierzasz ją wdrożyć. Jeśli chcesz opracować aplikację na komputery z systemem Windows, musisz to zrobić na komputerze z tym systemem, aby mieć dostęp do odpowiedniego łańcucha kompilacji. Istnieją wymagania dotyczące poszczególnych systemów operacyjnych, które są szczegółowo opisane na stronie docs.flutter.dev/desktop.

4. Konfiguracja

Aby pobrać kod do tego ćwiczenia:

  1. Otwórz repozytorium GitHub tego ćwiczenia.
  2. Aby pobrać cały kod do tych ćwiczeń z programowania, kliknij Code > Download zip (Kod > Pobierz plik ZIP).

2cd45599f51fb8a2.png

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

W tym ćwiczeniu potrzebne są tylko pliki z podkatalogu tfagents-flutter/ w repozytorium, który zawiera kilka folderów:

  • Foldery step0step6 zawierają kod startowy, który będziesz rozwijać w kolejnych krokach tego ćwiczenia.
  • Folder finished zawiera gotowy kod ukończonej przykładowej aplikacji.
  • Każdy folder zawiera podfolder backbend z kodem backendu i podfolder frontend z kodem frontendu Fluttera.

5. Pobierz zależności projektu.

Backend

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

pip install -r requirements.txt

Frontend

  1. W VS Code kliknij File > Open folder (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 wymaganych pakietów dla aplikacji startowej, kliknij Pobierz pakiety.
  3. Jeśli nie widzisz tego okna, otwórz terminal, a następnie 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 i upewnij się, że Android Emulator lub symulator iOS jest prawidłowo skonfigurowany i wyświetla się na pasku stanu.

Oto przykład tego, co zobaczysz, gdy użyjesz Pixela 5 z emulatorem Androida:

9767649231898791.png

Oto co zobaczysz, gdy użyjesz iPhone'a 13 z symulatorem iOS:

95529e3a682268b2.png

  1. Kliknij a19a0c68bc4046e6.png Rozpocznij debugowanie.

Uruchamianie aplikacji i jej poznawanie

Aplikacja powinna się uruchomić w Android Emulator lub iOS Simulator. Interfejs jest dość prosty. Są 2 plansze do gry. Gracz może kliknąć dowolne pole na planszy agenta u góry, aby zadać cios. Wytrenujesz inteligentnego agenta, który będzie automatycznie przewidywać, gdzie uderzyć, na podstawie planszy gracza.

Aplikacja Flutter wyśle aktualną planszę gracza do backendu, który uruchomi model uczenia przez wzmacnianie i zwróci przewidywaną pozycję komórki, w którą należy uderzyć w następnej kolejności. Po otrzymaniu odpowiedzi interfejs 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 TensorFlow Agents

Głównym celem tych ćwiczeń jest zaprojektowanie agenta, który uczy się przez interakcję ze środowiskiem. Gra Plane Strike jest stosunkowo prosta i można w niej ręcznie tworzyć reguły dla agenta NPC. Jednak w tym samouczku użyjesz uczenia ze wzmocnieniem, aby wytrenować agenta. Dzięki temu zdobędziesz umiejętności, które pozwolą Ci w przyszłości łatwo tworzyć agentów do innych gier.

W standardowym ustawieniu uczenia przez wzmacnianie agent otrzymuje obserwację w każdym kroku czasowym i wybiera działanie. Działanie jest stosowane w środowisku, które zwraca nagrodę i nową obserwację. Agent trenuje strategię, aby wybierać działania, które maksymalizują sumę nagród, czyli zwrot. Dzięki wielokrotnemu graniu w tę grę agent może nauczyć się wzorców i doskonalić swoje umiejętności, aby ją opanować. Aby sformułować grę Plane Strike jako problem RL, potraktuj stan planszy jako obserwację, pozycję uderzenia jako działanie, a sygnał trafienia/chybienia jako nagrodę.

bc5da07bc45062f4.png

Do trenowania agenta NPC używasz TensorFlow Agents, czyli niezawodnej, skalowalnej i łatwej w obsłudze biblioteki uczenia ze wzmocnieniem dla TensorFlow.

TF Agents to świetne narzędzie do uczenia ze wzmocnieniem, ponieważ zawiera obszerny zestaw ćwiczeń z programowania, przykłady i obszerną dokumentację, która pomoże Ci zacząć. Możesz używać TF Agents do rozwiązywania realistycznych i złożonych problemów RL z możliwością skalowania oraz szybkiego opracowywania nowych algorytmów RL. Możesz łatwo przełączać się między różnymi agentami i algorytmami, aby przeprowadzać eksperymenty. Jest też dobrze przetestowany i łatwy w konfiguracji.

OpenAI Gym (np. w przypadku gier Atari), Mujuco itp. zaimplementowano wiele gotowych środowisk gier, które TF Agents może łatwo wykorzystać. Gra Plane Strike jest jednak w pełni niestandardowa, więc musisz najpierw od podstaw zaimplementować nowe środowisko.

Aby zaimplementować środowisko Pythona TF Agents, musisz zaimplementować 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 z nich to funkcja _step(), która przyjmuje działanie i zwraca nowy obiekt time_step. W przypadku gry Plane Strike masz planszę. Gdy pojawi się nowa pozycja ataku, środowisko na podstawie stanu planszy określa:

  • Jak powinna wyglądać plansza w następnej kolejności (czy komórka powinna zmienić kolor na czerwony czy żółty, biorąc pod uwagę ukryte położenie samolotu)?
  • Jaką nagrodę powinien otrzymać gracz za tę pozycję (nagroda za trafienie czy kara za nietrafienie)?
  • Czy gra powinna się zakończyć (czy ktoś wygrał)?
  • Dodaj do funkcji _step() w pliku _planestrike_py_environment.py ten kod:
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. Trenowanie agenta gry za pomocą agentów TensorFlow

Po skonfigurowaniu środowiska TF Agents możesz wytrenować agenta gry. W tym ćwiczeniu użyjesz agenta REINFORCE. REINFORCE to algorytm gradientu strategii w uczeniu przez wzmacnianie. Jego podstawowa idea polega na dostosowywaniu parametrów sieci neuronowej zasad na podstawie sygnałów nagrody zebranych podczas rozgrywki, tak aby sieć zasad mogła w przyszłości maksymalizować zyski.

  • Najpierw musisz 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)
  • Następnie musisz utworzyć agenta uczenia ze wzmocnieniem, który będzie trenowany. W tym ćwiczeniu użyjesz agenta REINFORCE, który jest agentem opartym na zasadach. Dodaj ten kod bezpośrednio pod powyższym kodem:
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 kilka epizodów rozgrywki w buforze, a potem trenujesz agenta na podstawie danych z bufora. 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()
  • Możesz teraz rozpocząć trenowanie. W terminalu otwórz folder step2/backend na komputerze i uruchom:
python training.py

Trenowanie trwa 8–12 godzin w zależności od konfiguracji sprzętu (nie musisz samodzielnie przeprowadzać całego trenowania, ponieważ wstępnie wytrenowany model jest dostępny w step3). W międzyczasie możesz śledzić postępy za pomocą TensorBoard. Otwórz nowy terminal, przejdź do folderu step2/backend na komputerze i uruchom:

tensorboard --logdir tf_agents_log/

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

33e12e2b387c063a.png 8488632ccf43348a.png

Widać, że w miarę postępów w trenowaniu średnia długość odcinka maleje, a średni zwrot rośnie. Intuicyjnie można zrozumieć, że jeśli agent jest inteligentniejszy i dokonuje lepszych prognoz, gra trwa krócej i agent zbiera więcej nagród. Ma to sens, ponieważ agent chce zakończyć grę w mniejszej liczbie kroków, aby zminimalizować duże rabaty na nagrody w późniejszych krokach.

Po zakończeniu trenowania wytrenowany model jest eksportowany do folderu policy_model.

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

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

  • W terminalu przejdź do folderu step3/backend na komputerze i uruchom TensorFlow Serving za pomocą Dockera:
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 najpierw automatycznie pobierze obraz TensorFlow Serving, co zajmie minutę. Następnie powinna się uruchomić usługa TensorFlow Serving. Dziennik powinien wyglądać jak ten fragment kodu:

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

Możesz wysłać do punktu końcowego przykładowe żądanie, aby upewnić się, że działa on zgodnie z oczekiwaniami:

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 Cię to ciekawi, możesz spróbować dowiedzieć się, dlaczego środek planszy jest dobrym miejscem na pierwszy atak).

{
    "predictions": [45]
}

To wszystko. Udało Ci się utworzyć backend do przewidywania następnej pozycji uderzenia agenta NPC.

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

Backend jest gotowy. Możesz zacząć wysyłać do niego żądania, aby pobierać z aplikacji Flutter prognozy pozycji uderzenia.

  • Najpierw musisz zdefiniować klasę, która będzie zawierać 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 uzyskać 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, zaktualizuj interfejs gry, aby odzwierciedlał 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(() {});

Stosuj

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

852942d0de299c1f.png 6ae3601470c8e33a.png

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

Oprócz Androida i iOS Flutter obsługuje też platformy desktopowe, takie jak Linux, Mac i Windows.

Linux

  1. Upewnij się, że na pasku stanu VSCode wybrane urządzenie docelowe to 86cba523de82b4f9.png.
  2. Kliknij a19a0c68bc4046e6.png Rozpocznij debugowanie, a następnie poczekaj na wczytanie aplikacji.
  3. Aby rozpocząć grę, kliknij dowolną komórkę na tablicy agenta.

48594c7c0a589733.png

Mac

  1. W przypadku komputerów Mac 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 do plików step4/frontend/macOS/Runner/DebugProfile.entitlementsstep4/frontend/macOS/Runner/Release.entitlements:

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

55a5de3674194e89.png

Windows

  1. Upewnij się, że na pasku stanu VSCode wybrane urządzenie docelowe to 9587be1bb375bc0f.png.
  2. Kliknij a19a0c68bc4046e6.png Rozpocznij debugowanie, a następnie poczekaj na wczytanie aplikacji.
  3. Aby rozpocząć grę, kliknij dowolną komórkę na tablicy agenta.

41d9f87d84c5e755.png

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

Możesz też dodać obsługę internetu do aplikacji Flutter. Platforma internetowa jest domyślnie włączona w przypadku aplikacji Flutter, więc wystarczy ją uruchomić.

  1. Upewnij się, że na pasku stanu VSCode wybrane urządzenie docelowe to 71db93efa928d15d.png.
  2. Kliknij a19a0c68bc4046e6.png Rozpocznij debugowanie, a następnie poczekaj, aż aplikacja wczyta się w przeglądarce Chrome.
  3. Aby rozpocząć grę, kliknij dowolną komórkę na tablicy agenta.

fae7490304e28dfe.png

13. Gratulacje

Utworzono aplikację do gry planszowej z agentem opartym na uczeniu maszynowym, który może grać przeciwko człowiekowi.

Więcej informacji