Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
8
Help us understand the problem. What are the problem?

More than 3 years have passed since last update.

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

概要

「ポ」「プ」「テ」「ピピック」をランダムに出力して「ポプテピピック」が完成したら竹●房を破壊する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

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
8
Help us understand the problem. What are the problem?