Hier erfahren Sie, wie das Reversi-Beispiel Windows Store-App-Features verwendet.

Applies to Windows only

Im Reversi-Beispiel werden mehrere allgemeine Features von Windows Store-Apps mit XAML und C# verwendet. In diesem Thema wird beschrieben, wie einige dieser Features im Beispiel verwendet werden. Außerdem finden Sie hier Links zu Themen zu wichtigen Features.

Dieses Thema erfordert nicht, dass Sie das gesamte Beispiel verstehen. Es wird jedoch vorausgesetzt, dass Sie bereits über Kenntnisse in XAML und C# verfügen und mit den Grundlagen jedes Features vertraut sind. Andernfalls sollten Sie die verknüpften Themen lesen, um sich das fehlende Wissen anzueignen. Informationen zu den Grundlagen der App-Entwicklung finden Sie unter Erstellen Ihrer ersten Windows Store-App mit C# oder Visual Basic.

Eine allgemeine Einführung in das Beispiel erhalten Sie unter Reversi, ein Windows Store-Spiel in XAML, C# und C++. Informationen dazu, wie die verschiedenen Features als Ganzes zusammenarbeiten, finden Sie unter Grundlagen des Aufbaus der Reversi-App. Informationen dazu, wie die ursprüngliche C#-Spielengine zu C++ portiert wurde, finden Sie unter Informationen zur Reversi-C++-Spielengine.

Laden Sie die Reversi-Beispiel-App herunter, oder durchsuchen Sie den Quellcode.

Kachel und Begrüßungsbildschirm

Die App-Kachel und der Begrüßungsbildschirm sind die Teile der App, die der Benutzer als Erstes sieht. Sie können sie verwenden, um einen attraktiven Einstiegspunkt bereitzustellen und Ihre Marke darzustellen. In den Grundzügen sind diese Features trivial, es gibt jedoch einige aufwändigere Möglichkeiten, die in der Dokumentation beschrieben werden.

Wichtige Ressourcen:

Reversi enthält nur grundlegende Unterstützung für Kacheln und den Begrüßungsbildschirm. Dazu zählen quadratische und breite Kacheln und ein Begrüßungsbildschirm, der hier verkleinert dargestellt ist.

Reversi-Kacheln und Begrüßungsbildschirm

Die Bilddateinamen werden in der Datei Package.appxmanifest festgelegt. Sie können Bilder mit mehreren Skalierungen bereitstellen, um mehrere Bildschirmgrößen zu unterstützen. Für diese einfache Verwendung ist keine weitere Implementierung erforderlich.

App-Leiste

App-Leisten stellen einen Standardplatz für App-Befehle bereit. Benutzer können die App-Leiste standardmäßig wie gewünscht ein- oder ausblenden, wodurch sie ein geeigneter Platz für seltener verwendete Befehle ist. Dies ermöglicht es Ihnen, den Fokus der Hauptbenutzeroberfläche auf direkte Interaktionen mit Ihrem Inhalt zu richten.

Wichtige Ressourcen:

Reversi enthält einige sekundäre Befehle, die sich gut für die App-Leiste eignen: die Funktionen zum Anhalten der Stoppuhr und zum Rückgängigmachen oder Wiederholen von Spielzügen. Während des normalen Spielvorgangs ist die App-Leiste ausgeblendet, der Benutzer kann sie jedoch durch eine Streifbewegung vom oberen oder unteren Bildschirmrand ein- oder ausblenden.

Reversi-App-Leiste

Dieser Code aus GamePage.xaml zeigt die Definition der App-Leiste. Obwohl Hintergrund und Rahmen transparent sind, ist die Background-Eigenschaft auf {x:Null} festgelegt. Dadurch wird verhindert, dass die nicht sichtbare App-Leiste Elemente blockiert, auf die der Benutzer tippt oder klickt. Diese Einstellung ist erforderlich, weil sich die App-Leiste über den gesamten Bildschirm erstreckt und mit der unteren Zeile des Spielbretts überlappt.


<Page.BottomAppBar>
  <CommandBar x:Name="GamePageAppBar" Background="{x:Null}" 
    BorderBrush="Transparent" IsSticky="True" Margin="9,0">
    <CommandBar.SecondaryCommands>
      <AppBarButton Icon="Pause" Label="Pause"
        Command="{Binding Clock.PauseCommand}" Click="DismissAppBar"
        Visibility="{Binding Clock.IsPauseButtonVisible, 
          Converter={StaticResource BooleanToVisibilityConverter}}"/>
      <AppBarButton Icon="Play" Label="Play"
        Command="{Binding Clock.PlayCommand}" Click="DismissAppBar"          
        Visibility="{Binding Clock.IsPauseButtonVisible,
          Converter={StaticResource BooleanToVisibilityConverter}, 
          ConverterParameter=Reverse}"/>
      <AppBarButton Icon="Undo" Label="Undo" Command="{Binding UndoCommand}"/>
      <AppBarButton Icon="Redo" Label="Redo" Command="{Binding RedoCommand}"/>
    </CommandBar.SecondaryCommands>
  </CommandBar>
</Page.BottomAppBar>


Reversi verwendet die Steuerelemente CommandBar und AppBarButton, um das Standardverhalten und den Standardstil zu erhalten. Das Schaltflächenverhalten und der Aktivierungszustand werden durch Ansichtsmodellbefehle bereitgestellt, die an die Command-Eigenschaften der Schaltfläche gebunden sind (siehe Abschnitt Befehle).

Die SchaltflächenWiedergabe und Pause funktionieren wie eine einzelne Umschaltfläche. Hierfür werden die Visibility-Eigenschaften der Schaltflächen an dieselbe Ansichtsmodelleigenschaft gebunden. Beide Bindungen verwenden einen BooleanToVisibilityConverter, eine von ihnen verfügt jedoch außerdem über eine ConverterParameter-Eigenschaftseinstellung, die den Effekt der Bindung umkehrt. Dadurch ist jede Schaltfläche nur dann sichtbar, wenn die andere nicht sichtbar ist. Weitere Informationen finden Sie im Abschnitt Datenbindung.

Popupbenachrichtigungen

Popupbenachrichtigungen machen den Benutzer auf wichtige Ereignisse in Ihrer App aufmerksam – auch dann, wenn gerade eine andere App aktiv ist.

Wichtige Ressourcen:

In Reversi kann es eine Weile dauern, bis der Computer seinen Spielzug ausführt. Wenn Sie während der Wartezeit zu einer anderen App wechseln, werden Sie von einer Popupbenachrichtigung informiert, wenn Sie mit Ihrem Zug an der Reihe sind.

Reversi-Popupbenachrichtigung

In Reversi wird das Minimum an erforderlichem Code für Popupbenachrichtigungen verwendet und das Feld Toastfähig im Package.appxmanifest-Designer auf Ja festgelegt. Der Popupcode kann einfach wiederverwendet werden und ist daher in einer Hilfsklasse im Ordner Common enthalten.

In GameViewModel.cs:


var window = Windows.UI.Xaml.Window.Current;
if (window != null && !window.Visible && !IsCurrentPlayerAi)
{
    Toast.Show("It's your turn!");
}


In "Toast.cs":


public static void Show(string text)
{
    const string template = 
        "<toast duration='short'><visual><binding template='ToastText01'>" +
        "<text id='1'>{0}</text></binding></visual></toast>";
    var toastXml = new XmlDocument();
    toastXml.LoadXml(String.Format(template, text));
    var toast = new ToastNotification(toastXml);
    ToastNotificationManager.CreateToastNotifier().Show(toast);
}


Einstellungsflyouts

Der Charm "Einstellungen" bietet standardisierten Zugriff auf App-Einstellungen.

Wichtige Ressourcen:

Reversi enthält zwei Einstellungsflyouts – eines für Anzeigeoptionen und eines für "Neues Spiel".

Reversi-Einstellungsflyouts

Dieser Code aus App.xaml.cs zeigt, wie das SettingsPane.CommandsRequested-Ereignis in Reversi behandelt wird, um SettingsCommand-Objekte zu erstellen. Wenn diese Option aktiviert ist, erstellt jeder Befehl ein SettingsFlyout-Steuerelement und zeigt es an.


SettingsPane.GetForCurrentView().CommandsRequested += OnCommandsRequested;



private void OnCommandsRequested(SettingsPane sender,
    SettingsPaneCommandsRequestedEventArgs args)
{
    args.Request.ApplicationCommands.Add(new SettingsCommand("Display", "Display options", 
        _ => (new DisplaySettings() { DataContext = SettingsViewModel }).Show()));
    args.Request.ApplicationCommands.Add(new SettingsCommand("NewGame", "New game options", 
        _ => (new NewGameSettings() { DataContext = SettingsViewModel }).Show()));
}


Freigeben von Inhalt

Mit dem Freigabe-Vertrag kann Ihre App Daten teilen, die Benutzer an andere Apps senden können. Benutzer können z. B. Daten aus Ihrer App für eine E-Mail-App freigeben und eine neue Nachricht erstellen.

Wichtige Ressourcen:

Windows bietet integrierte Unterstützung für das Teilen eines Bilds der App, und Reversi erfordert keine zusätzlichen zusätzlichen Funktionen.

Datenbindung

Die Datenbindung ermöglicht es Ihnen, UI-Steuerelemente mit den von ihnen angezeigten Daten zu verbinden, sodass die Daten durch Änderungen des Steuerelements aktualisiert werden (und umgekehrt). Die Datenbindung wird oft für Dateneingabeformulare eingesetzt, kann aber auch verwendet werden, um die gesamte UI zu steuern und die UI von der App-Logik getrennt zu halten.

Wichtige Ressourcen:

In Reversi werden Datenbindungen verwendet, um die UI (oder "Ansichtsebene") mit der App-Logik (oder "Ansichtsmodellebene") zu verbinden. Diese Ebenenstruktur ermöglicht eine Trennung der UI vom Code und wird als Model-View-ViewModel (MVVM)-Muster bezeichnet. Informationen zur Verwendung des Musters in Reversi finden Sie unter Aufbau der Reversi-App. Eine kurze Einführung in MVVM finden Sie unter Verwenden des Model-View-ViewModel (MVVM)-Musters.

Der Großteil der Bindungen in Reversi wird mithilfe der Binding-Markuperweiterung in XAML definiert, in einigen wenigen Fällen wird aber CodeBehind verwendet (z. B. in der Datei Board.xaml.cs). Jede Seite legt ihre DataContext-Eigenschaft fest, und diese Eigenschaft wird von allen Elementen auf der Seite als Datenquelle für Bindungen verwendet wird.

UI-Aktualisierungen

Die Datenbindungen steuern die UI in Reversi. UI-Interaktionen führen zu Änderungen der Datenquelleneigenschaften, und die Datenbindungen reagieren durch Aktualisieren der UI auf die Änderungen.

Diese Aktualisierungen funktionieren, da die Reversi-Ansichtsmodellklassen die BindableBase-Klasse übernehmen. Diese Klasse befindet sich in der Common/BindableBase.cs-Datei und stellt eine standardmäßige INotifyPropertyChanged-Implementierung und einige Unterstützungsmethoden bereit. Die SetProperty-Methode aktualisiert den Sicherungswert einer Eigenschaft und alle gebundenen UI-Elemente mit nur einem Methodenaufruf. Die OnPropertyChanged-Methode aktualisiert die an angegebene Eigenschaften gebundene UI. Dies ist hilfreich für die zeitliche Steuerung der Aktualisierungen und bei Eigenschaften, die ihre Werte von anderen Eigenschaften erhalten.

Der folgende Code aus GameViewModel.cs veranschaulicht die grundlegende Verwendung von SetProperty und OnPropertyChanged.


public State CurrentPlayer
{
    get { return _currentPlayer; }
    set
    {
        SetProperty(ref _currentPlayer, value);
        OnPropertyChanged("IsCurrentPlayerAi");
        OnPropertyChanged("IsPlayerOneAi");
        OnPropertyChanged("IsPlayerTwoAi");
        OnPropertyChanged("CurrentPlayerAiSearchDepth");
    }
}


Wertkonvertierung

Sie können beliebige Eigenschaftswerte in eine für die Bindung geeignetere Form konvertieren, indem Sie berechnete Eigenschaften erstellen, d. h. Eigenschaften, die ihre Werte von anderen Eigenschaften erhalten.

Dieser Code aus GameViewModel.cs zeigt eine einfache berechnete Eigenschaft. An diese Eigenschaft gebundene UI wird durch den entsprechenden OnPropertyChanged-Aufruf im vorhergehenden Beispiel aktualisiert.


public bool IsPlayerOneAi { get { return (int)PlayerOne > 0; } }


Berechnete Eigenschaften lassen sich mühelos für jeden erforderlichen Konvertierungstyp erstellen, führen oft aber dazu, dass der Code unübersichtlich wird. Für häufige Konvertierungen empfiehlt es sich, den Konvertierungscode in einer wiederverwendbaren IValueConverter-Implementierung zu platzieren. In Reversi werden die NullStateToVisibilityConverter- und BooleanToVisibilityConverter-Klassen im Ordner Common/Converters für Bindungen zum Ein- und Ausblenden verschiedener UI-Elemente verwendet.

Diese Bindung aus StartPage.xaml blendet ein Panel abhängig davon, ob eine Eigenschaft einen Wert hat, ein oder aus.


<StackPanel Visibility="{Binding GameViewModel, 
  Converter={StaticResource NullStateToVisibilityConverter}}">


Diese Bindung aus NewGameSettings.xaml blendet ein Panel abhängig vom Zustand eines ToggleSwitch-Steuerelements ein oder aus.


<StackPanel Orientation="Horizontal" 
  Visibility="{Binding IsOn, ElementName=PlayerOneSwitch, 
    Converter={StaticResource BooleanToVisibilityConverter}}">


Weitere Beispiele finden Sie unter App-Leiste.

Befehle

Button-Verhalten werden oft mit Click-Ereignishandlern in CodeBehind-Dateien implementiert. In Reversi wird dieser Ansatz für Navigationsschaltflächen verwendet. Für andere Schaltflächen wird die Schaltflächen-UI jedoch von dem von der Schaltfläche aufgerufenen Nicht-UI-Code getrennt. Zu diesem Zweck werden die Button.Command-Eigenschaften an Ansichtsmodelleigenschaften gebunden, die ICommand-Implementierungen zurückgeben.

Reversi-Befehlseigenschaften sind vom Typ DelegateCommand oder DelegateCommand<T>. Diese Klassen sind in der Datei Common/DelegateCommand.cs enthalten und stellen wiederverwendbare ICommand-Standardimplementierungen bereit. Mit diesen Klassen können Sie die Erstellung einmaliger Befehle vereinfachen und den notwendigen Code auf einzelne Eigenschaftsimplementierungen beschränken.

Dieser Code aus GameViewModel.cs zeigt den von den Spielbrettfeldern verwendeten Move-Befehl (die Spielbrettfelder sind benutzerdefinierte Schaltflächen). Der ??- oder "null-coalescing"-Operator gibt an, dass der Feldwert nur zurückgegeben wird, wenn er nicht null ist. Andernfalls wird das Feld festgelegt, und der neue Wert wird zurückgegeben. Dies bedeutet, dass beim ersten Zugriff auf eine Eigenschaft ein einziges Befehlsobjekt erstellt und das gleiche Objekt für alle zukünftigen Zugriffe wieder verwendet wird. Das Befehlsobjekt wird durch den Aufruf der DelegateCommand<ISpace>.FromAsyncHandler-Methode mit Verweisen auf die Methoden MoveAsync und CanMove initialisiert. Diese Methoden stellen die Implementierung für die Methoden ICommand.Execute und CanExecute bereit.


public DelegateCommand<ISpace> MoveCommand 
{ 
    get 
    { 
        return _moveCommand ?? (_moveCommand = 
            DelegateCommand<ISpace>.FromAsyncHandler(MoveAsync, CanMove));
    } 
}


Die CanExecute-Methode wird von der Datenbindung aufgerufen, um den Aktivierungszustand der Schaltfläche zu aktualisieren. Befehlsbindungen sind jedoch von Änderungsbenachrichtigungen abhängig, die denen anderer Bindungen ähneln (erläutert im Abschnitt UI-Aktualisierungen). Dieser Code aus GameViewModel.cs zeigt, wie die UpdateView-Methode den Ansichtsmodellzustand mit dem Modellzustand synchronisiert und anschließend OnCanExecuteChanged für jeden Befehl aufruft, bevor sie mit dem nächsten Spielzug fortfährt.


private void UpdateView()
{
    SyncModelProperties();
    UpdateBoard();
    UndoCommand.RaiseCanExecuteChanged();
    RedoCommand.RaiseCanExecuteChanged();
    MoveCommand.RaiseCanExecuteChanged();
}


Benutzerdefinierte Abhängigkeitseigenschaften

In Reversi werden benutzerdefinierte Abhängigkeitseigenschaften in den benutzerdefinierten Steuerelementen verwendet, damit Änderungen des visuellen Zustands durch Datenbindungsaktualisierungen ausgelöst werden können. Visuelle Zustände und animierte Übergänge werden mithilfe der VisualStateManager-Klasse in XAML definiert. Es ist jedoch nicht möglich, einen visuellen Zustand direkt an eine Ansichtsmodelleigenschaft zu binden. Benutzerdefinierte Abhängigkeitseigenschaften stellen Ziele für die Bindung an Ansichtsmodelleigenschaften bereit. Die Abhängigkeitseigenschaften enthalten Rückrufe für Eigenschaftsänderungen, die die erforderlichen VisualStateManager.GoToState-Methodenaufrufe ausführen.

Dieser Code veranschaulicht, wie das PlayerStatus-Steuerelement seine benutzerdefinierten Abhängigkeitseigenschaften mithilfe von CodeBehind an Ansichtsmodelleigenschaften bindet. Dieses Beispiel zeigt nur eine der Abhängigkeitseigenschaften mit der zugehörigen Rückrufmethode für Eigenschaftsänderungen. Sowohl der Rückruf als auch die OnApplyTemplate-Methodenüberschreibung rufen die Update-Methode auf. Der OnApplyTemplate-Aufruf initialisiert das Steuerelement jedoch für seine erstmalige Anzeige auf dem Bildschirm und verwendet daher keine animierten Übergänge.


public PlayerStatus()
{
    DefaultStyleKey = typeof(PlayerStatus);
    SetBinding(CurrentPlayerProperty, new Binding { 
        Path = new PropertyPath("CurrentPlayer") });
    SetBinding(IsClockShowingProperty, new Binding { 
        Path = new PropertyPath("Settings.IsClockShowing") });
    SetBinding(IsGameOverProperty, new Binding { 
        Path = new PropertyPath("IsGameOver") });
    SetBinding(WinnerProperty, new Binding { 
        Path = new PropertyPath("Winner") });
}

protected override void OnApplyTemplate()
{
    base.OnApplyTemplate();
    UpdatePlayerState(false);
    UpdateClockState(false);
    UpdateGameOverState(false);
}

public bool IsClockShowing
{
    get { return (bool)GetValue(IsClockShowingProperty); }
    set { SetValue(IsClockShowingProperty, value); }
}

public static readonly DependencyProperty IsClockShowingProperty =
    DependencyProperty.Register("IsClockShowing", typeof(bool),
    typeof(PlayerStatus), new PropertyMetadata(true, IsClockShowingChanged));

private static void IsClockShowingChanged(DependencyObject d, 
    DependencyPropertyChangedEventArgs e)
{
    (d as PlayerStatus).UpdateClockState(true);
}

private void UpdateClockState(bool useTransitions)
{
    GoToState(IsClockShowing ? "ClockShowing" : "ClockHidden", useTransitions);
}

private void GoToState(string state, bool useTransitions)
{
    VisualStateManager.GoToState(this, state, useTransitions);
}


Asynchroner Code

Durch Verwendung von asynchronem Code bleibt die UI reaktionsfähig, während die App zeitaufwendige Vorgänge ausführt.

Wichtige Ressourcen:

Reversi verwendet asynchronen Code, um Bewegungen in einem Spiel auszuführen. Jede Bewegung dauert mindestens eine Sekunde, einschließlich der Animation der Bewegung, und AI-Bewegungen (Artificial Intelligence, künstliche Intelligenz) dauern u. U. viel länger. Die UI bleibt jederzeit reaktionsfähig, und Benutzerbefehle (wie z. B. "rückgängig machen") brechen eine derzeit ausgeführte Bewegung ab.

Dieser Code aus GameViewModel.cs zeigt, wie Reversi die Schlüsselwörter async und await, die Task-Klasse und Abbruchtoken verwendet. Beachten Sie die Verwendung von AsTask zum Integrieren mit dem asynchronen Windows-Runtime-Code in der Game-Klasse. (Weitere Informationen finden Sie im nächsten Abschnitt.)


private async Task MoveAsync(ISpace move)
{
    var cancellationToken = GetNewCancellationToken();
    LastMoveAffectedSpaces = await Game.MoveAsync(move).AsTask(cancellationToken);
    if (cancellationToken.IsCancellationRequested) return;
    await OnMoveCompletedAsync(cancellationToken);
}



private async Task AiMoveAsync()
{
    var cancellationToken = GetNewCancellationToken();

    // Unlike the MoveAsync method, the AiMoveAsync method requires a try/catch 
    // block for cancellation. This is because the AI search checks for 
    // cancellation deep within a recursive, iterative search process
    // that is easiest to halt by throwing an exception. 
    try
    {
        // The WhenAll method call enables the delay and the AI search to 
        // occur concurrently. However, in order to retrieve the return 
        // value of the first task, both tasks must have the same signature,
        // thus requiring the delay task to have a (meaningless) return value.  
        var results = await Task.WhenAll(
            Game.GetBestMoveAsync(CurrentPlayerAiSearchDepth)
                .AsTask(cancellationToken),
            Task.Run(async () =>
            {
                await DelayAsync(MinimumTurnLength, cancellationToken);
                return (ISpace)null;
            })
        );

        // Perform the AI move only after both the 
        // search and the minimum delay have passed.
        LastMoveAffectedSpaces = await Game.MoveAsync(
            results[0]).AsTask(cancellationToken);
        if (cancellationToken.IsCancellationRequested) return;

        await OnMoveCompletedAsync(cancellationToken);
    }
    catch (OperationCanceledException)
    {
        System.Diagnostics.Debug.WriteLine("cancelled with exception");
    }
}


Verwenden einer Komponente für Windows-Runtime

Das Implementieren eines Teils Ihres Codes als Windows-Runtime-Komponente ermöglicht Ihnen das Wiederverwenden dieses Codes in verschiedenen Apps, auf verschiedenen Plattformen oder mit verschiedenen Sprachen. Sie können die Komponente auch einfacher durch eine alternative Implementierung in einer anderen Sprache ersetzen.

Wichtige Ressource:

Reversi implementiert die grundlegende Spiellogik als Windows-Runtime-Komponente, um sie vollständig von der App zu entkoppeln. Dadurch können zukünftige Erweiterungen und die Wiederverwendung von Code unterstützt werden. Reversi enthält außerdem eine C++-Version der Spielengine als Alternative mit höherer Leistung zur ursprünglichen C#-Version. Weitere Informationen finden Sie unter Informationen zur C++-Spielengine von Reversi.

Dieser Code aus Game.cs zeigt, wie Reversi Task-basierten asynchronen Code (einschließlich der Schlüsselwörter async und await), verwendet, die Ergebnisse jedoch über asynchrone Windows-Runtime Schnittstellen bereitstellt. Außerdem wird gezeigt, wie das Abbruchtoken aus dem GameViewModel-Code von der Game-Klasse verwendet wird.

Die erste und die dritte Methode im Beispielcode rufen die AsyncInfo.Run-Methode auf, um eine IAsyncOperation<T> zurückzugeben. Dadurch wird der Rückgabewert der Aufgabe umgebrochen und ermöglicht den Abbruch. Im zweiten Beispiel wird die WindowsRuntimeSystemExtensions.AsAsyncAction-Methode aufgerufen, um eine IAsyncAction zurückzugeben. Dies ist hilfreich bei Aufgaben ohne Rückgabewerte, die nicht abgebrochen werden müssen.


public IAsyncOperation<IList<ISpace>> MoveAsync(ISpace move)
{
    // Use a lock to prevent the ResetAsync method from modifying the game 
    // state at the same time that a different thread is in this method.
    lock (_lockObject)
    {
        return AsyncInfo.Run(cancellationToken => Task.Run(() =>
        {
            if (cancellationToken.IsCancellationRequested) return null;
            var changedSpaces = Move(move);
            SyncMoveStack(move);
            return changedSpaces;
        }, cancellationToken));
    }
}



public IAsyncAction AiMoveAsync(int searchDepth)
{
    return Task.Run(async () => 
    {
        // If it is the AI's turn and we're not at the end of the move stack,
        // just use the next move in the stack. This is necessary to preserve
        // the forward stack, but it also prevents the AI from having to search again. 
        var bestMove = Moves.Count < MoveStack.Count ? 
            MoveStack[Moves.Count] : await GetBestMoveAsync(searchDepth);
        await MoveAsync(bestMove);
    }).AsAsyncAction();
}

public IAsyncOperation<ISpace> GetBestMoveAsync(int searchDepth)
{
    if (searchDepth < 1) throw new ArgumentException(
        "must be 1 or greater.", "searchDepth");

    return AsyncInfo.Run(cancellationToken => Task.Run(() => 
    {
        return (ISpace)reversiAI.GetBestMove(Board, 
            CurrentPlayer == State.One, searchDepth, cancellationToken);
    }, cancellationToken));
}


Verwandte Themen

Reversi-Beispiel-App
Reversi, ein Windows Store-Spiel in XAML, C# und C++
Verwenden des Model-View-ViewModel (MVVM)-Musters
Hier erfahren Sie, wie das Reversi-Beispiel Windows Store-App-Features verwendet.
Grundlegendes zur Reversi-App-Struktur
Informationen zur Reversi-C++-Spielengine
Erstellen Ihrer ersten Windows Store-App mit C# oder Visual Basic
Roadmap für Windows-Runtime-Apps mit C# oder Visual Basic
Datenbindung

 

 

Anzeigen:
© 2014 Microsoft