Help us understand the problem. What is going on with this article?

「ポ」「プ」「テ」「ピピック」をランダムに出力して「ポプテピピック」が完成したら竹●房を破壊するC#

More than 1 year has passed since last update.

概要

「ポ」「プ」「テ」「ピピック」をランダムに出力して「ポプテピピック」が完成したら竹●房を破壊するJavaScript
をC# + WPF + Reactive Extensions で書いてみました。

C#でもすでに先達がおられる
https://qiita.com/ruhiel/items/c98451e4700344654f25

今回コンソールじゃなくてWPFにしたのはAAをきれいに表示するため。WinFormsでも同じようにできます。

コード

AAは改行が含まれていてい直接コードに書きづらいので、ResourceにTakeで登録しておきます。
NugetでReactive Extensions(System.Reactive)を導入します。

WindowのXamlではAAが正しく表示されるようTextboxのフォントを「MS PGothic」に設定しています。

MainWindow.xaml
<Window
    x:Class="PopTeamEpicWpf.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="「ポ」「プ」「テ」「ピピック」をランダムに出力して「ポプテピピック」が完成したら竹●房を破壊するC#"
    Width="900"
    Height="600">
    <ScrollViewer>
        <TextBox
            x:Name="textBox"
            FontFamily="MS PGothic"
            FontSize="16"
            IsReadOnly="True"
            TextWrapping="Wrap" />
    </ScrollViewer>
</Window>

コードビハインドでは主に以下の2つを行っています。

  • ランダムに「ポ」「プ」「テ」「ピピック」が流れてきて、「ポプテピピック」に一致したらCompleteするIObservableの生成
  • それを購読してOnNextではそのまま、CompleteではAAをTextboxへ出力

注意点は一致判定のためにBufferでまとめている部分で、あえてBufferの長さを余分にしていることです。
これは一致した時の最後のOnNext「ピピック」を流すためです。

MainWindow.xaml.cs
public partial class MainWindow : Window
{
    static string[] pops = new[] { "ポ", "プ", "テ", "ピピック" };

    public MainWindow()
    {
        InitializeComponent();

        CreateRandomPops()
            //Textboxにアクセスするので、UIスレッド上で購読
            .ObserveOn(this.Dispatcher)
            .Subscribe(
                //OnNextは流れてきた文字をそのままTextboxに書き足す
                x => this.textBox.Text += x,
                //CompleteしたらリソースからAAを取得してTextboxに書き足す
                () => textBox.Text += Properties.Resources.Take);
    }

    /// <summary>
    /// ランダムに「ポ」「プ」「テ」「ピピック」がOnNextに流れてきて、「ポプテピピック」に一致したらCompleteするIObservable
    /// </summary>
    private static IObservable<string> CreateRandomPops()
    {
        int maxCount = pops.Count();
        var random = new Random();
        IObservable<string> randomPop = Observable
            //10msecごとに
            .Interval(TimeSpan.FromMilliseconds(10))
            //ランダムに「ポ」「プ」「テ」「ピピック」のどれか
            .Select(_ => pops[random.Next(maxCount)]);
        //※テスト用 最初がいきなり「ポプテピピック」になる
        //.Select(i => pops[i % maxCount]);

        //バッファを空白で埋めておく (["","","","",""])
        return Observable.Repeat("", maxCount)
            .Concat(randomPop)
            //最後の「ピピック」をOnNextに流すために1つ余分にBufferをもつ
            .Buffer(maxCount + 1, 1)
            //Bufferの前が「ポプテピピック」に一致する状態(["ポ","プ","テ","ピピック",*])になるまで続行 
            .TakeWhile(x => !x.Take(maxCount).SequenceEqual(pops))
            //Bufferの最後をOnNextに流す  ([*,*,*,*,○] の ○)
            .Select(x => x.Last());
    }
}

実行結果例

スクリーンショット 2018-03-30 01.00.14.png

参考

Reactive Extensions再入門
https://qiita.com/amay077/items/85dfc4bd194f57c52c57#_reference-557477ce374f1a552c5c

環境

System.Reactive 3.1.1
VisualStudio2017
.NET Framework 4.7
C#7.1

soi
ソフトウェアエンジニア C#, Xaml チョットワカル
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした