Start of Numberle/Wordle Tastatur

This commit is contained in:
Gottfried Wilhelm Leibniz 2022-04-19 22:35:37 +02:00
parent f51bd2bb44
commit 626b31a3ce
3 changed files with 209 additions and 34 deletions

View File

@ -1,4 +1,6 @@
<!-- Hidden Alerts --> @using System.Diagnostics
<!-- Hidden Alerts -->
<div hidden="@hideAlert"> <div hidden="@hideAlert">
<MudContainer MaxWidth="MaxWidth.Small"> <MudContainer MaxWidth="MaxWidth.Small">
<MudGrid> <MudGrid>
@ -17,29 +19,27 @@
<!-- Matrix mit Buchstabenfeldern --> <!-- Matrix mit Buchstabenfeldern -->
<div class="d-flex justify-center mt-2 mb-2"> <div class="d-flex justify-center mt-2 mb-2">
<div> <div>
@foreach(var guess in PreviousGuesses) @foreach (CharData[] guess in PreviousGuesses)
{ {
<div class="d-flex mb-2"> <div class="d-flex mb-2">
@for(int i = 0; i < ColumnCount; i++) @foreach (CharData cd in guess)
{ {
char guessedChar = char.ToUpper(guess[i]); if (cd.State == CharState.Correct)
if(guessedChar == char.ToUpper(Secret[i]))
{ {
<MudPaper Style="border-color: green; border-width: 4px;" Class="mr-2" Width="60px" Height="60px" Outlined="true"> <MudPaper Style="border-color: green; border-width: 4px;" Class="mr-2" Width="60px" Height="60px" Outlined="true">
<MudText Typo="Typo.h3" Align="Align.Center">@guessedChar</MudText> <MudText Typo="Typo.h3" Align="Align.Center">@cd.Char</MudText>
</MudPaper> </MudPaper>
} }
else if (Secret.Contains(guessedChar, StringComparison.InvariantCultureIgnoreCase)) else if (cd.State == CharState.Misplaced)
{ {
<MudPaper Style="border-color: yellow; border-width: 4px;" Class="mr-2" Width="60px" Height="60px" Outlined="true"> <MudPaper Style="border-color: yellow; border-width: 4px;" Class="mr-2" Width="60px" Height="60px" Outlined="true">
<MudText Typo="Typo.h3" Align="Align.Center">@guessedChar</MudText> <MudText Typo="Typo.h3" Align="Align.Center">@cd.Char</MudText>
</MudPaper> </MudPaper>
} }
else else
{ {
<MudPaper Style="border-width: 4px;" Class="mr-2" Width="60px" Height="60px" Outlined="true"> <MudPaper Style="border-width: 4px;" Class="mr-2" Width="60px" Height="60px" Outlined="true">
<MudText Typo="Typo.h3" Align="Align.Center">@guessedChar</MudText> <MudText Typo="Typo.h3" Align="Align.Center">@cd.Char</MudText>
</MudPaper> </MudPaper>
} }
} }
@ -48,15 +48,17 @@
</div> </div>
</div> </div>
<p>@Input</p>
<!-- Input dialogue feld --> <!-- Input dialogue feld -->
<MudContainer MaxWidth="MaxWidth.Small" @onkeyup="@Check4Enter"> <MudContainer MaxWidth="MaxWidth.Small" @onkeyup="@Check4Enter">
<MudGrid Spacing="2"> <MudGrid Spacing="2">
<MudItem xs="1"></MudItem> <MudItem xs="1"></MudItem>
<MudItem xs="8"> <MudItem xs="8">
<MudTextField Class="" @ref="textField" T="string" FullWidth="true" @bind-Value="Input" Label="Dein Tipp:" Variant="Variant.Outlined" MaxLength="5" Mask="@InputMask">Hi</MudTextField> <MudTextField Class="" @ref="textField" T="string" FullWidth="true" Immediate="true" @bind-Value="@_input" Label="Dein Tipp:" Variant="Variant.Outlined" MaxLength="5" Mask="@InputMask" Counter="ColumnCount" />
</MudItem> </MudItem>
<MudItem xs="2"> <MudItem xs="2">
<MudButton style="height:56px; margin-top:6px;" Class="justify-center" Disabled="Input.Length != ColumnCount" <MudButton style="height: 56px; margin-top: 6px;" Class="justify-center" Disabled="_input.Length != ColumnCount"
Size="Size.Large" Variant="Variant.Outlined" EndIcon="@Icons.Material.Filled.Send" Color="Color.Primary" OnClick=@ButtonOnClick>OK</MudButton> Size="Size.Large" Variant="Variant.Outlined" EndIcon="@Icons.Material.Filled.Send" Color="Color.Primary" OnClick=@ButtonOnClick>OK</MudButton>
</MudItem> </MudItem>
<MudItem xs="1"></MudItem> <MudItem xs="1"></MudItem>
@ -64,37 +66,93 @@
</MudContainer> </MudContainer>
@code { @code {
public string Input { get; set; } = string.Empty;
public enum CharState
{
None,
Correct,
Misplaced,
Wrong
}
public struct CharData
{
public char Char;
public CharState State;
public CharData(char c, CharState state)
{
Char = c;
State = state;
}
}
private string _input = string.Empty;
[Parameter]
public string Input
{
get => _input;
set => _input = value;
}
public async Task SetText(string text)
{
textField.SetText(text);
}
public bool hideAlert = true; public bool hideAlert = true;
public MudTextField<string> textField; public MudTextField<string> textField;
public List<string> PreviousGuesses = new(); public List<CharData[]> PreviousGuesses = new();
public List<string> SecretList = new();
//Keine Ahnung wie das funktionert... Danke StackOverflow :)
/// <summary>
/// Eine Regexmaske die alle Strings matched die 0 bis 5 Buchstaben enthalten.
/// </summary>
//private IMask _inputMask = new RegexMask(@"^[A-Za-z]{0,5}$");
private bool found = false; private bool found = false;
private int _columnCount;
private string? _secret = null;
private IMask _inputMask = new RegexMask(@"^[A-Za-z]{0,5}$");
private Func<string, bool>? _checkInput;
private Func<string>? _generateSecret;
[Parameter] [Parameter]
public int ColumnCount { get; set; } public int ColumnCount
{
get => _columnCount;
set => _columnCount = value;
}
[Parameter] [Parameter]
public string? Secret { get; set; } = null; public string? Secret
{
[Parameter] get => _secret;
public IMask InputMask { get; set; } = new RegexMask(@"^[A-Za-z]{0,5}$"); set => _secret = value;
}
[Parameter] [Parameter]
public Func<string, bool>? CheckInput { get; set; } public IMask InputMask
{
get => _inputMask;
set => _inputMask = value;
}
[Parameter] [Parameter]
public Func<string>? GenerateSecret { get; set; } public Func<string, bool>? CheckInput
{
get => _checkInput;
set => _checkInput = value;
}
[Parameter]
public Func<string>? GenerateSecret
{
get => _generateSecret;
set => _generateSecret = value;
}
/// <summary>
/// Wird ausgelöst wenn eine Eingabe getätigt und validiert wurde.
/// </summary>
public event EventHandler<CharData[]>? InputValidated;
public void Check4Enter(KeyboardEventArgs e) public void Check4Enter(KeyboardEventArgs e)
{ {
@ -121,17 +179,53 @@
if (Secret == null && GenerateSecret != null) if (Secret == null && GenerateSecret != null)
Secret = GenerateSecret(); Secret = GenerateSecret();
PreviousGuesses.Add(Input); if(TestInput(Input))
if(Secret!.Equals(Input, StringComparison.InvariantCultureIgnoreCase))
{ {
found = true; found = true;
textField.Clear();
hideAlert = false; hideAlert = false;
} }
else
textField.Clear();
}
/// <summary>
/// Prüft ob die Eingabe korrekt ist.
/// </summary>
private bool TestInput(string input)
{
CharData[] validatedInput = new CharData[ColumnCount];
bool correct = true;
for (int i = 0; i < ColumnCount; i++)
{ {
textField.Clear(); char guessedChar = char.ToUpper(input[i]);
CharState state;
if (guessedChar == char.ToUpper(Secret![i]))
{
state = CharState.Correct;
}
else if (Secret.Contains(guessedChar, StringComparison.InvariantCultureIgnoreCase))
{
state = CharState.Misplaced;
correct = false;
}
else
{
state = CharState.Wrong;
correct = false;
}
validatedInput[i] = new CharData(guessedChar, state);
} }
PreviousGuesses.Add(validatedInput);
InputValidated?.Invoke(this, validatedInput);
return correct;
} }
public void PlayAgain() public void PlayAgain()

View File

@ -0,0 +1,72 @@

<!-- Matrix mit Buchstabenfeldern -->
<div class="d-flex justify-center mt-2 mb-2">
<div>
@{
int index = 0;
for (int row = 0; row < Math.Ceiling((double)Keys.Length / KeysPerRow); row++)
{
<div class="d-flex mb-2">
@for (int i = 0; i < KeysPerRow && index < Keys.Length; i++, index++)
{
char key = Keys[index];
char upperKey = char.ToUpper(key);
if (_correctKeys.Contains(upperKey))
{
<MudButton Variant="Variant.Outlined" Class="mr-2" Style="width: 5em; height: 5em" Color="Color.Success" @onclick="() => ButtonPressed(key)">
<MudText Typo="Typo.h5">@upperKey</MudText>
</MudButton>
}
else if (_misplacedKeys.Contains(upperKey))
{
<MudButton Variant="Variant.Outlined" Class="mr-2" Style="width: 5em; height: 5em" Color="Color.Warning" @onclick="() => ButtonPressed(key)">
<MudText Typo="Typo.h5">@upperKey</MudText>
</MudButton>
}
else if (_wrongKeys.Contains(upperKey))
{
<MudButton Disabled="true" Variant="Variant.Outlined" Class="mr-2" Style="width: 5em; height: 5em" Color="Color.Error" @onclick="() => ButtonPressed(key)">
<MudText Typo="Typo.h5">@upperKey</MudText>
</MudButton>
}
else
{
<MudButton Variant="Variant.Outlined" Class="mr-2" Style="width: 5em; height: 5em" @onclick="() => ButtonPressed(key)">
<MudText Typo="Typo.h5">@upperKey</MudText>
</MudButton>
}
}
</div>
}
}
</div>
</div>
@code {
[Parameter]
public char[] Keys { get; set; } = Array.Empty<char>();
private List<char> _correctKeys = new();
private List<char> _misplacedKeys = new();
private List<char> _wrongKeys = new();
[Parameter]
public int KeysPerRow { get; set; } = 10;
[Parameter]
public string Secret { get; set; } = string.Empty;
[Parameter]
public EventCallback<char> KeyPressed { get; set; }
private async Task ButtonPressed(char c)
{
await KeyPressed.InvokeAsync(c);
}
}

View File

@ -7,7 +7,9 @@
<PageTitle>Nacken Numberle</PageTitle> <PageTitle>Nacken Numberle</PageTitle>
<MudText Align="Align.Center" Class="mt-2 mb-2"> Gebe eine (korrekte) mathematische Gleichung ein:</MudText> <MudText Align="Align.Center" Class="mt-2 mb-2"> Gebe eine (korrekte) mathematische Gleichung ein:</MudText>
<WordleComponent ColumnCount="8" GenerateSecret="GenerateSecret" InputMask="@_inputMask" CheckInput="CheckInput" /> <WordleComponent ColumnCount="8" GenerateSecret="GenerateSecret" InputMask="@_inputMask" CheckInput="CheckInput" @ref="_wordle" />
<WordleKeyboardComponent KeyPressed="KeyboardKeyPressed" Keys="Chars" />
@code @code
{ {
@ -15,6 +17,8 @@
private Parser _parser = new(); private Parser _parser = new();
private WordleComponent _wordle;
protected override async Task OnInitializedAsync() protected override async Task OnInitializedAsync()
{ {
await base.OnInitializedAsync(); await base.OnInitializedAsync();
@ -127,4 +131,9 @@
} }
} }
} }
private async Task KeyboardKeyPressed(char key)
{
await _wordle.SetText(_wordle.Input + key); //Input += key;
}
} }