C
C#ā€¢3mo ago
jacks

blazor webpage not displaying new information or delaying with Task.Delay()

so i'm making a blazor app that plays the war game. after each round i want it to display the winner of the round as well as the card that won them the round. i was able to get this information to display in the console but never able to got it to display on the actual webpage and i'm not sure why
52 Replies
jacks
jacksā€¢3mo ago
@if (running)
{
foreach (KeyValuePair<string, Hand> kvp in playerHands.PlayerCards)
{
<div>
Player: @kvp.Key<br />
Number Cards Remaining: @kvp.Value.Cards.Count
</div>
}
@if (playersIn > 1)
{
@if (roundWinner.Key != null)
{
<div>
Round Winner: @roundWinner.Key<br />
Winning Card: @(roundWinner.Value.Rank) of @(roundWinner.Value.Suit)
</div>
}
else
{
<div>
Tie!
</div>
}
}
@if (winner != "")
{
<div>
Winner: @winner
</div>
}
}
@if (running)
{
foreach (KeyValuePair<string, Hand> kvp in playerHands.PlayerCards)
{
<div>
Player: @kvp.Key<br />
Number Cards Remaining: @kvp.Value.Cards.Count
</div>
}
@if (playersIn > 1)
{
@if (roundWinner.Key != null)
{
<div>
Round Winner: @roundWinner.Key<br />
Winning Card: @(roundWinner.Value.Rank) of @(roundWinner.Value.Suit)
</div>
}
else
{
<div>
Tie!
</div>
}
}
@if (winner != "")
{
<div>
Winner: @winner
</div>
}
}
public void PlayGame()
{
if (!running)
{
ConfirmPlayers();

if (playersConfirmed)
{
errorMessage = "";

Deck deck = new Deck();
running = true;
StateHasChanged();

deck.Generate();
playerHands = deck.Split(players);

RunGame();
}
}
}
public void PlayGame()
{
if (!running)
{
ConfirmPlayers();

if (playersConfirmed)
{
errorMessage = "";

Deck deck = new Deck();
running = true;
StateHasChanged();

deck.Generate();
playerHands = deck.Split(players);

RunGame();
}
}
}
public void RunGame()
{
playersIn = CheckPlayersIn();
PlayedCards playedCards = new PlayedCards();
playedCards.Cards = new Dictionary<string, Card>();

Console.WriteLine("PLAYING GAME");

while (playersIn > 1)
{
Card worstCard = new Card
{
Suit = (Suit)0,
Rank = (Rank)0
};
KeyValuePair<string, Card> greatestCard = new KeyValuePair<string, Card>("", worstCard);
bool tie = false;

foreach (KeyValuePair<string, Hand> kvp in playerHands.PlayerCards)
{
if (kvp.Value.Cards.Count > 0)
{
Card toCompare = kvp.Value.Play();
playedCards.Cards.Add(kvp.Key, toCompare);

if ((int)toCompare.Rank > (int)greatestCard.Value.Rank)
{
tie = false;

KeyValuePair<string, Card> newGreatest = new KeyValuePair<string, Card>(kvp.Key, toCompare);
greatestCard = newGreatest;
}
else if ((int)toCompare.Rank == (int)greatestCard.Value.Rank)
{
tie = true;
}
}
}

if (tie)
{
playedCards.Tie();

Console.WriteLine($"Tie with {greatestCard.Value.Rank} of {greatestCard.Value.Suit}");
roundWinner = new KeyValuePair<string, Card>();
}
else
{
foreach (KeyValuePair<string, Hand> kvp in playerHands.PlayerCards)
{
if (kvp.Key == greatestCard.Key)
{
foreach (Card card in playedCards.Cards.Values)
{
kvp.Value.Add(card);
}
if (playedCards.TieCards.Count > 0)
{
foreach (Card card in playedCards.TieCards)
{
kvp.Value.Add(card);
}

playedCards.TieCards = new Stack<Card>();
}

roundWinner = greatestCard;

Console.WriteLine($"{roundWinner.Key} wins with {roundWinner.Value.Rank} of {roundWinner.Value.Suit}");
break;
}
}
}

playedCards.Cards = new Dictionary<string, Card>();
playersIn = CheckPlayersIn();
Task.Delay(1000);
StateHasChanged();
}
public void RunGame()
{
playersIn = CheckPlayersIn();
PlayedCards playedCards = new PlayedCards();
playedCards.Cards = new Dictionary<string, Card>();

Console.WriteLine("PLAYING GAME");

while (playersIn > 1)
{
Card worstCard = new Card
{
Suit = (Suit)0,
Rank = (Rank)0
};
KeyValuePair<string, Card> greatestCard = new KeyValuePair<string, Card>("", worstCard);
bool tie = false;

foreach (KeyValuePair<string, Hand> kvp in playerHands.PlayerCards)
{
if (kvp.Value.Cards.Count > 0)
{
Card toCompare = kvp.Value.Play();
playedCards.Cards.Add(kvp.Key, toCompare);

if ((int)toCompare.Rank > (int)greatestCard.Value.Rank)
{
tie = false;

KeyValuePair<string, Card> newGreatest = new KeyValuePair<string, Card>(kvp.Key, toCompare);
greatestCard = newGreatest;
}
else if ((int)toCompare.Rank == (int)greatestCard.Value.Rank)
{
tie = true;
}
}
}

if (tie)
{
playedCards.Tie();

Console.WriteLine($"Tie with {greatestCard.Value.Rank} of {greatestCard.Value.Suit}");
roundWinner = new KeyValuePair<string, Card>();
}
else
{
foreach (KeyValuePair<string, Hand> kvp in playerHands.PlayerCards)
{
if (kvp.Key == greatestCard.Key)
{
foreach (Card card in playedCards.Cards.Values)
{
kvp.Value.Add(card);
}
if (playedCards.TieCards.Count > 0)
{
foreach (Card card in playedCards.TieCards)
{
kvp.Value.Add(card);
}

playedCards.TieCards = new Stack<Card>();
}

roundWinner = greatestCard;

Console.WriteLine($"{roundWinner.Key} wins with {roundWinner.Value.Rank} of {roundWinner.Value.Suit}");
break;
}
}
}

playedCards.Cards = new Dictionary<string, Card>();
playersIn = CheckPlayersIn();
Task.Delay(1000);
StateHasChanged();
}
Task.Delay() and StateHasChanged() don't seem to have any impact so i'm not sre what else to do
jacks
jacksā€¢3mo ago
No description
jacks
jacksā€¢3mo ago
displays just fine in console as well
Joschi
Joschiā€¢3mo ago
What exactly isn't working as expected? And could you please share the complete .razor page including the Properties?
jacks
jacksā€¢3mo ago
ya if yo need me to post the classes as well just lmk uhhh
@page "/"
@using Project3.Data

<h1>War Game</h1>

Select number of players:
<select @bind=numPlayers>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
</select>
<br />

@for (int i = 0; i < numPlayers; i++)
{
int pos = i;

<div>
Player #@(i + 1): <input @bind="@playersToCheck[pos]" />
</div>
}

<button @onclick=PlayGame>Start Game</button>
@errorMessage

@if (playerHands.Count() > 0)
{
@foreach (KeyValuePair<string, Hand> kvp in playerHands.PlayerCards)
{
<div>
Player: @kvp.Key<br />
Cards:
@foreach (Card card in kvp.Value.Cards)
{
<span>
@(card.Rank) of @(card.Suit)
</span><br />
}
</div>
}
}

@if (running)
{
foreach (KeyValuePair<string, Hand> kvp in playerHands.PlayerCards)
{
<div>
Player: @kvp.Key<br />
Number Cards Remaining: @kvp.Value.Cards.Count
</div>
}
@if (playersIn > 1)
{
@if (roundWinner.Key != null)
{
<div>
Round Winner: @roundWinner.Key<br />
Winning Card: @(roundWinner.Value.Rank) of @(roundWinner.Value.Suit)
</div>
}
else
{
<div>
Tie!
</div>
}
}
@if (winner != "")
{
<div>
Winner: @winner
</div>
}
}@page "/"
@using Project3.Data

<h1>War Game</h1>

Select number of players:
<select @bind=numPlayers>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
</select>
<br />

@for (int i = 0; i < numPlayers; i++)
{
int pos = i;

<div>
Player #@(i + 1): <input @bind="@playersToCheck[pos]" />
</div>
}

<button @onclick=PlayGame>Start Game</button>
@errorMessage

@if (playerHands.Count() > 0)
{
@foreach (KeyValuePair<string, Hand> kvp in playerHands.PlayerCards)
{
<div>
Player: @kvp.Key<br />
Cards:
@foreach (Card card in kvp.Value.Cards)
{
<span>
@(card.Rank) of @(card.Suit)
</span><br />
}
</div>
}
}

@if (running)
{
foreach (KeyValuePair<string, Hand> kvp in playerHands.PlayerCards)
{
<div>
Player: @kvp.Key<br />
Number Cards Remaining: @kvp.Value.Cards.Count
</div>
}
@if (playersIn > 1)
{
@if (roundWinner.Key != null)
{
<div>
Round Winner: @roundWinner.Key<br />
Winning Card: @(roundWinner.Value.Rank) of @(roundWinner.Value.Suit)
</div>
}
else
{
<div>
Tie!
</div>
}
}
@if (winner != "")
{
<div>
Winner: @winner
</div>
}
}
@page "/"
@using Project3.Data

<h1>War Game</h1>

Select number of players:
<select @bind=numPlayers>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
</select>
<br />

@for (int i = 0; i < numPlayers; i++)
{
int pos = i;

<div>
Player #@(i + 1): <input @bind="@playersToCheck[pos]" />
</div>
}

<button @onclick=PlayGame>Start Game</button>
@errorMessage

@if (playerHands.Count() > 0)
{
@foreach (KeyValuePair<string, Hand> kvp in playerHands.PlayerCards)
{
<div>
Player: @kvp.Key<br />
Cards:
@foreach (Card card in kvp.Value.Cards)
{
<span>
@(card.Rank) of @(card.Suit)
</span><br />
}
</div>
}
}

@if (running)
{
foreach (KeyValuePair<string, Hand> kvp in playerHands.PlayerCards)
{
<div>
Player: @kvp.Key<br />
Number Cards Remaining: @kvp.Value.Cards.Count
</div>
}
@if (playersIn > 1)
{
@if (roundWinner.Key != null)
{
<div>
Round Winner: @roundWinner.Key<br />
Winning Card: @(roundWinner.Value.Rank) of @(roundWinner.Value.Suit)
</div>
}
else
{
<div>
Tie!
</div>
}
}
@if (winner != "")
{
<div>
Winner: @winner
</div>
}
}@page "/"
@using Project3.Data

<h1>War Game</h1>

Select number of players:
<select @bind=numPlayers>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
</select>
<br />

@for (int i = 0; i < numPlayers; i++)
{
int pos = i;

<div>
Player #@(i + 1): <input @bind="@playersToCheck[pos]" />
</div>
}

<button @onclick=PlayGame>Start Game</button>
@errorMessage

@if (playerHands.Count() > 0)
{
@foreach (KeyValuePair<string, Hand> kvp in playerHands.PlayerCards)
{
<div>
Player: @kvp.Key<br />
Cards:
@foreach (Card card in kvp.Value.Cards)
{
<span>
@(card.Rank) of @(card.Suit)
</span><br />
}
</div>
}
}

@if (running)
{
foreach (KeyValuePair<string, Hand> kvp in playerHands.PlayerCards)
{
<div>
Player: @kvp.Key<br />
Number Cards Remaining: @kvp.Value.Cards.Count
</div>
}
@if (playersIn > 1)
{
@if (roundWinner.Key != null)
{
<div>
Round Winner: @roundWinner.Key<br />
Winning Card: @(roundWinner.Value.Rank) of @(roundWinner.Value.Suit)
</div>
}
else
{
<div>
Tie!
</div>
}
}
@if (winner != "")
{
<div>
Winner: @winner
</div>
}
}
@code
{
int numPlayers = 0;
string[] playersToCheck = new string[4];
string errorMessage = "";
List<string> players = new List<string>();
bool playersConfirmed = false;
bool running = false;
PlayerHands playerHands = new PlayerHands();
KeyValuePair<string, Card> roundWinner = new KeyValuePair<string, Card>();
int playersIn = 0;
string winner = "";

public void PlayGame()
{
if (!running)
{
ConfirmPlayers();

if (playersConfirmed)
{
errorMessage = "";

Deck deck = new Deck();
running = true;
StateHasChanged();

deck.Generate();
playerHands = deck.Split(players);

RunGame();
}
}
}

public void ConfirmPlayers()
{
int numInvalid = 0;
List<string> pass = new List<string>();

for (int i = 0; i < numPlayers; i++)
{
if (playersToCheck[i] == "" || playersToCheck[i] == null)
{
errorMessage = "Fill out all player name fields!";
numInvalid++;
}
else
{
pass.Add(playersToCheck[i]);
}
}

if (numInvalid > 0)
{
playersConfirmed = false;
}
else if (pass.Distinct().Count() != numPlayers)
{
errorMessage = "Make sure each player name is unique!";
playersConfirmed = false;
}
else
{
foreach (string player in pass)
{
players.Add(player);
}
playersConfirmed = true;
}
}
@code
{
int numPlayers = 0;
string[] playersToCheck = new string[4];
string errorMessage = "";
List<string> players = new List<string>();
bool playersConfirmed = false;
bool running = false;
PlayerHands playerHands = new PlayerHands();
KeyValuePair<string, Card> roundWinner = new KeyValuePair<string, Card>();
int playersIn = 0;
string winner = "";

public void PlayGame()
{
if (!running)
{
ConfirmPlayers();

if (playersConfirmed)
{
errorMessage = "";

Deck deck = new Deck();
running = true;
StateHasChanged();

deck.Generate();
playerHands = deck.Split(players);

RunGame();
}
}
}

public void ConfirmPlayers()
{
int numInvalid = 0;
List<string> pass = new List<string>();

for (int i = 0; i < numPlayers; i++)
{
if (playersToCheck[i] == "" || playersToCheck[i] == null)
{
errorMessage = "Fill out all player name fields!";
numInvalid++;
}
else
{
pass.Add(playersToCheck[i]);
}
}

if (numInvalid > 0)
{
playersConfirmed = false;
}
else if (pass.Distinct().Count() != numPlayers)
{
errorMessage = "Make sure each player name is unique!";
playersConfirmed = false;
}
else
{
foreach (string player in pass)
{
players.Add(player);
}
playersConfirmed = true;
}
}
public void RunGame()
{
playersIn = CheckPlayersIn();
PlayedCards playedCards = new PlayedCards();
playedCards.Cards = new Dictionary<string, Card>();

Console.WriteLine("PLAYING GAME");

while (playersIn > 1)
{
Card worstCard = new Card
{
Suit = (Suit)0,
Rank = (Rank)0
};
KeyValuePair<string, Card> greatestCard = new KeyValuePair<string, Card>("", worstCard);
bool tie = false;

foreach (KeyValuePair<string, Hand> kvp in playerHands.PlayerCards)
{
if (kvp.Value.Cards.Count > 0)
{
Card toCompare = kvp.Value.Play();
playedCards.Cards.Add(kvp.Key, toCompare);

if ((int)toCompare.Rank > (int)greatestCard.Value.Rank)
{
tie = false;

KeyValuePair<string, Card> newGreatest = new KeyValuePair<string, Card>(kvp.Key, toCompare);
greatestCard = newGreatest;
}
else if ((int)toCompare.Rank == (int)greatestCard.Value.Rank)
{
tie = true;
}
}
}

if (tie)
{
playedCards.Tie();

Console.WriteLine($"Tie with {greatestCard.Value.Rank} of {greatestCard.Value.Suit}");
roundWinner = new KeyValuePair<string, Card>();
}
else
{
foreach (KeyValuePair<string, Hand> kvp in playerHands.PlayerCards)
{
if (kvp.Key == greatestCard.Key)
{
foreach (Card card in playedCards.Cards.Values)
{
kvp.Value.Add(card);
}
if (playedCards.TieCards.Count > 0)
{
foreach (Card card in playedCards.TieCards)
{
kvp.Value.Add(card);
}

playedCards.TieCards = new Stack<Card>();
}

roundWinner = greatestCard;

Console.WriteLine($"{roundWinner.Key} wins with {roundWinner.Value.Rank} of {roundWinner.Value.Suit}");
break;
}
}
}

playedCards.Cards = new Dictionary<string, Card>();
playersIn = CheckPlayersIn();
Task.Delay(1000);
StateHasChanged();
}

foreach (KeyValuePair<string, Hand> kvp in playerHands.PlayerCards)
{
if (kvp.Value.Cards.Count > 0)
{
winner = kvp.Key;
break;
}
}
}

public int CheckPlayersIn()
{
int numIn = 0;

foreach (KeyValuePair<string, Hand> kvp in playerHands.PlayerCards)
{
if (kvp.Value.Cards.Count > 0)
{
numIn++;
}
}

return numIn;
}
}
public void RunGame()
{
playersIn = CheckPlayersIn();
PlayedCards playedCards = new PlayedCards();
playedCards.Cards = new Dictionary<string, Card>();

Console.WriteLine("PLAYING GAME");

while (playersIn > 1)
{
Card worstCard = new Card
{
Suit = (Suit)0,
Rank = (Rank)0
};
KeyValuePair<string, Card> greatestCard = new KeyValuePair<string, Card>("", worstCard);
bool tie = false;

foreach (KeyValuePair<string, Hand> kvp in playerHands.PlayerCards)
{
if (kvp.Value.Cards.Count > 0)
{
Card toCompare = kvp.Value.Play();
playedCards.Cards.Add(kvp.Key, toCompare);

if ((int)toCompare.Rank > (int)greatestCard.Value.Rank)
{
tie = false;

KeyValuePair<string, Card> newGreatest = new KeyValuePair<string, Card>(kvp.Key, toCompare);
greatestCard = newGreatest;
}
else if ((int)toCompare.Rank == (int)greatestCard.Value.Rank)
{
tie = true;
}
}
}

if (tie)
{
playedCards.Tie();

Console.WriteLine($"Tie with {greatestCard.Value.Rank} of {greatestCard.Value.Suit}");
roundWinner = new KeyValuePair<string, Card>();
}
else
{
foreach (KeyValuePair<string, Hand> kvp in playerHands.PlayerCards)
{
if (kvp.Key == greatestCard.Key)
{
foreach (Card card in playedCards.Cards.Values)
{
kvp.Value.Add(card);
}
if (playedCards.TieCards.Count > 0)
{
foreach (Card card in playedCards.TieCards)
{
kvp.Value.Add(card);
}

playedCards.TieCards = new Stack<Card>();
}

roundWinner = greatestCard;

Console.WriteLine($"{roundWinner.Key} wins with {roundWinner.Value.Rank} of {roundWinner.Value.Suit}");
break;
}
}
}

playedCards.Cards = new Dictionary<string, Card>();
playersIn = CheckPlayersIn();
Task.Delay(1000);
StateHasChanged();
}

foreach (KeyValuePair<string, Hand> kvp in playerHands.PlayerCards)
{
if (kvp.Value.Cards.Count > 0)
{
winner = kvp.Key;
break;
}
}
}

public int CheckPlayersIn()
{
int numIn = 0;

foreach (KeyValuePair<string, Hand> kvp in playerHands.PlayerCards)
{
if (kvp.Value.Cards.Count > 0)
{
numIn++;
}
}

return numIn;
}
}
jacks
jacksā€¢3mo ago
when i run the program nothing updates on the actual web page
No description
jacks
jacksā€¢3mo ago
at the same time the console has output so i know that it's running fine and i've walked thru it a few times in debug mode and the program itself works how i want it to it just won't display things on the page
Joschi
Joschiā€¢3mo ago
So the @if statements in your html evaluate correctly?
jacks
jacksā€¢3mo ago
they should whenever i fire playgame it changes running to true and currently there's nothing that changes running to false and that should trigger the foreach
Joschi
Joschiā€¢3mo ago
I believe you can actually put breakpoints in your HTML as well for debugging. But could you just try putting some random text in that if to see if it get's rendered?
jacks
jacksā€¢3mo ago
inside the if statements or just like random
Joschi
Joschiā€¢3mo ago
Inside the if just some <span>SomeText</span> to see if that updates correctly.
jacks
jacksā€¢3mo ago
No description
jacks
jacksā€¢3mo ago
nop it jst doesn't seem to like detect the change in running? even tho i put StateHasChanged after every round so im not really sure man ā˜¹ļø
Joschi
Joschiā€¢3mo ago
Typically you don't need to call StateHasChanged() at all. Ok try to display the running bool outside your if statement to see if the variable actually updates the way you want to
jacks
jacksā€¢3mo ago
yup running doesn't update at all on the webpage
No description
jacks
jacksā€¢3mo ago
it doesn't seem anything changes on the webpage after i run playgame
public void PlayGame()
{
if (!running)
{
ConfirmPlayers();

if (playersConfirmed)
{
errorMessage = "";

Deck deck = new Deck();
running = true;

deck.Generate();
playerHands = deck.Split(players);

RunGame();
}
}
else
{
errorMessage = "There's a game in progress!";
}
}
public void PlayGame()
{
if (!running)
{
ConfirmPlayers();

if (playersConfirmed)
{
errorMessage = "";

Deck deck = new Deck();
running = true;

deck.Generate();
playerHands = deck.Split(players);

RunGame();
}
}
else
{
errorMessage = "There's a game in progress!";
}
}
i added this at the end of playgame and when i click the button again it doesn't display that error message
Joschi
Joschiā€¢3mo ago
<button @onclick="() => _running = !_running">Start/Stop</button>
@if (_running)
{
<span>The game is running</span>
}
else
{
<span>The game is not running</span>
}

@code {
private bool _running = false;

}
<button @onclick="() => _running = !_running">Start/Stop</button>
@if (_running)
{
<span>The game is running</span>
}
else
{
<span>The game is not running</span>
}

@code {
private bool _running = false;

}
just to be sure if you add this, does that work and update correctly on your end?
jacks
jacksā€¢3mo ago
i'll see works good before i start a game doesn't work after i start a game idk šŸ˜­šŸ˜­
Joschi
Joschiā€¢3mo ago
Ok let's see then Wait a second So you are calling Task.Delay() without awaiting. Never ever call an async Method and not await it!
jacks
jacksā€¢3mo ago
how do dat
Joschi
Joschiā€¢3mo ago
We don't really need to get into await / async here, but you should maybe read some guides or watch a video or two about it. You will not need to do any async programming for this anyways. But the very basics are. Async methods are awaited using the await keyword. This can only be used in async methods. Async methods should (basically) always return a Task or Task<T>.
jacks
jacksā€¢3mo ago
to use it in this case would i need to turn the whole RunGame() into an async task i want it to wait 1 second after each turn instead of going instantly
Joschi
Joschiā€¢3mo ago
Ok, then you will have to turn everything into async methods.
jacks
jacksā€¢3mo ago
gotcha so if i'm not returning anything from the method do i just add async and if i'm returning something it has to be an async Task<datatype of what i will retrn>
Joschi
Joschiā€¢3mo ago
If you would return void return a task instead.
c#
private async Task PlayGame()
{
if (_running)
{
return;
}

_running = true;
await Task.Delay(1000);
_running = false;
}
c#
private async Task PlayGame()
{
if (_running)
{
return;
}

_running = true;
await Task.Delay(1000);
_running = false;
}
jacks
jacksā€¢3mo ago
gotcha
Joschi
Joschiā€¢3mo ago
async void methods have some very very specific cases, where they have to be used. But generally they should be avoided if possible.
jacks
jacksā€¢3mo ago
okay i'll try to remember that i got it to work and the information displays now but generally where do you want to put the return if it's just a Task
Joschi
Joschiā€¢3mo ago
I don't quite understand the question?
jacks
jacksā€¢3mo ago
hm so in this one you returned it inside of this if statement and for mine
public async Task RunGame()
{
playersIn = CheckPlayersIn();
PlayedCards playedCards = new PlayedCards();
playedCards.Cards = new Dictionary<string, Card>();

Console.WriteLine("PLAYING GAME");

while (playersIn > 1)
{
Card worstCard = new Card
{
Suit = (Suit)0,
Rank = (Rank)0
};
KeyValuePair<string, Card> greatestCard = new KeyValuePair<string, Card>("", worstCard);
bool tie = false;

foreach (KeyValuePair<string, Hand> kvp in playerHands.PlayerCards)
{
if (kvp.Value.Cards.Count > 0)
{
Card toCompare = kvp.Value.Play();
playedCards.Cards.Add(kvp.Key, toCompare);

if ((int)toCompare.Rank > (int)greatestCard.Value.Rank)
{
tie = false;

KeyValuePair<string, Card> newGreatest = new KeyValuePair<string, Card>(kvp.Key, toCompare);
greatestCard = newGreatest;
}
else if ((int)toCompare.Rank == (int)greatestCard.Value.Rank)
{
tie = true;
}
}
}

if (tie)
{
playedCards.Tie();

Console.WriteLine($"Tie with {greatestCard.Value.Rank} of {greatestCard.Value.Suit}");
roundWinner = new KeyValuePair<string, Card>();
}
else
{
foreach (KeyValuePair<string, Hand> kvp in playerHands.PlayerCards)
{
if (kvp.Key == greatestCard.Key)
{
foreach (Card card in playedCards.Cards.Values)
{
kvp.Value.Add(card);
}
if (playedCards.TieCards.Count > 0)
{
foreach (Card card in playedCards.TieCards)
{
kvp.Value.Add(card);
}

playedCards.TieCards = new Stack<Card>();
}

roundWinner = greatestCard;

Console.WriteLine($"{roundWinner.Key} wins with {roundWinner.Value.Rank} of {roundWinner.Value.Suit}");
break;
}
}
}

playedCards.Cards = new Dictionary<string, Card>();
playersIn = CheckPlayersIn();
await Task.Delay(1000);
StateHasChanged();
}

foreach (KeyValuePair<string, Hand> kvp in playerHands.PlayerCards)
{
if (kvp.Value.Cards.Count > 0)
{
winner = kvp.Key;
break;
}
}

return;
}
public async Task RunGame()
{
playersIn = CheckPlayersIn();
PlayedCards playedCards = new PlayedCards();
playedCards.Cards = new Dictionary<string, Card>();

Console.WriteLine("PLAYING GAME");

while (playersIn > 1)
{
Card worstCard = new Card
{
Suit = (Suit)0,
Rank = (Rank)0
};
KeyValuePair<string, Card> greatestCard = new KeyValuePair<string, Card>("", worstCard);
bool tie = false;

foreach (KeyValuePair<string, Hand> kvp in playerHands.PlayerCards)
{
if (kvp.Value.Cards.Count > 0)
{
Card toCompare = kvp.Value.Play();
playedCards.Cards.Add(kvp.Key, toCompare);

if ((int)toCompare.Rank > (int)greatestCard.Value.Rank)
{
tie = false;

KeyValuePair<string, Card> newGreatest = new KeyValuePair<string, Card>(kvp.Key, toCompare);
greatestCard = newGreatest;
}
else if ((int)toCompare.Rank == (int)greatestCard.Value.Rank)
{
tie = true;
}
}
}

if (tie)
{
playedCards.Tie();

Console.WriteLine($"Tie with {greatestCard.Value.Rank} of {greatestCard.Value.Suit}");
roundWinner = new KeyValuePair<string, Card>();
}
else
{
foreach (KeyValuePair<string, Hand> kvp in playerHands.PlayerCards)
{
if (kvp.Key == greatestCard.Key)
{
foreach (Card card in playedCards.Cards.Values)
{
kvp.Value.Add(card);
}
if (playedCards.TieCards.Count > 0)
{
foreach (Card card in playedCards.TieCards)
{
kvp.Value.Add(card);
}

playedCards.TieCards = new Stack<Card>();
}

roundWinner = greatestCard;

Console.WriteLine($"{roundWinner.Key} wins with {roundWinner.Value.Rank} of {roundWinner.Value.Suit}");
break;
}
}
}

playedCards.Cards = new Dictionary<string, Card>();
playersIn = CheckPlayersIn();
await Task.Delay(1000);
StateHasChanged();
}

foreach (KeyValuePair<string, Hand> kvp in playerHands.PlayerCards)
{
if (kvp.Value.Cards.Count > 0)
{
winner = kvp.Key;
break;
}
}

return;
}
i ended up slapping the return at the very end when the game is over what is the return actually doing? just breaking out of the method?
Joschi
Joschiā€¢3mo ago
Generally speaking yes. What I did is called an early return. It is used to make code more readable. You should really try applying this to your code. Let me write up an example real quick.
jacks
jacksā€¢3mo ago
gotcha
Joschi
Joschiā€¢3mo ago
Let's take this method.
c#
private void NotEarlyReturning()
{
bool condition1 = true;
bool condition2 = true;
bool condition3 = true;
bool condition4 = true;

if (condition1)
{
Console.Write("Do One");

if (condition2)
{
Console.Write("Do Two");

if (condition3)
{
Console.Write("Do Three");

if (condition4)
{
Console.Write("Do Four");
}
}
}
}
}
c#
private void NotEarlyReturning()
{
bool condition1 = true;
bool condition2 = true;
bool condition3 = true;
bool condition4 = true;

if (condition1)
{
Console.Write("Do One");

if (condition2)
{
Console.Write("Do Two");

if (condition3)
{
Console.Write("Do Three");

if (condition4)
{
Console.Write("Do Four");
}
}
}
}
}
If you just read it from top to bottom, you kind of know what will happen. But it get's more nested and confusing real fast, especially the longer and more complex your method ist. This could be reduced down to
c#
private void EarlyReturning()
{
bool condition1 = true;
bool condition2 = true;
bool condition3 = true;
bool condition4 = true;

if (!condition1)
{
return;
}
Console.Write("Do One");

if (!condition2)
{
return;
}

Console.Write("Do Two");

if (!condition3)
{
return;
}

Console.Write("Do Three");

if (!condition4)
{
return;
}

Console.Write("Do Four");
}
c#
private void EarlyReturning()
{
bool condition1 = true;
bool condition2 = true;
bool condition3 = true;
bool condition4 = true;

if (!condition1)
{
return;
}
Console.Write("Do One");

if (!condition2)
{
return;
}

Console.Write("Do Two");

if (!condition3)
{
return;
}

Console.Write("Do Three");

if (!condition4)
{
return;
}

Console.Write("Do Four");
}
Now you can just read the method from top to bottom. You have a clear idea of where you can stop reading and the code is segmented into nice little pieces. This is just for demonstration, your method should't actually return at so many places, when you have returns all over the place you can start thinking of extracting stuff into their own smaller methods. A more realistic use case would be something called guard clauses
private void GuardClauses(string? param1, string? param2)
{
if (param1 is null || param2 is null)
{
return;
}

Console.WriteLine($"1 {param1}; 2 {param2}");
}
private void GuardClauses(string? param1, string? param2)
{
if (param1 is null || param2 is null)
{
return;
}

Console.WriteLine($"1 {param1}; 2 {param2}");
}
Where you check some conditions at the start of your method and return early if they are not met.
jacks
jacksā€¢3mo ago
i see does the ? on string? make it so that it can pass through even if it's null
Joschi
Joschiā€¢3mo ago
Yes that's right. That's C# nullable annotations. It should be turned on by default in the newer project templates.
jacks
jacksā€¢3mo ago
i see these examples are super helpful thank you for showing them
Joschi
Joschiā€¢3mo ago
Sure no problem, happy to help
jacks
jacksā€¢3mo ago
would it be ideal to convert all my other methods in my @Code{} to async tasks as well oops sorry whoever i pinged
Joschi
Joschiā€¢3mo ago
Hmm that's actually not that easy to answer. Having a method marked with async does come with a bit of a performance cost (it is 100% negligible in your and most cases!). A method that doesn't await anything often just returns a Task, without being an async method itself.
c#
private async Task IDoAsyncWork()
{
await Task.Delay(1000);
}

private Task IJustPassOnTheTask()
{
// Nothing async happening in this method
Console.WriteLine("We are doing some work now!");
return IDoAsyncWork();
}

private async Task IConsumeAnAsyncMethod()
{
// This HAS to be awaited!
await IJustPassOnTheTask();
Console.WriteLine("Work done");
}
c#
private async Task IDoAsyncWork()
{
await Task.Delay(1000);
}

private Task IJustPassOnTheTask()
{
// Nothing async happening in this method
Console.WriteLine("We are doing some work now!");
return IDoAsyncWork();
}

private async Task IConsumeAnAsyncMethod()
{
// This HAS to be awaited!
await IJustPassOnTheTask();
Console.WriteLine("Work done");
}
I honestly can't give you a strong answer to your question. Async has this property of being "contagious", if one thing down the chain is async, everything else has to be async as well. So you could just write everything to have that in mind. But async also has downsides. For example you cannot use out parameters. Or yield. So the real answer in the end probably is "use async, when you need it". Anything that needs to do IO calls at some point, like web requests or reading files, should be async.
jacks
jacksā€¢3mo ago
i see in my case only 1 other thing really "interacts" with RunGame() which is just PlayGame() and i did get a green squiggle under that one saying i never declared an await for RunGame() so i gess that is the only one i need to convert i guess that's all i need in terms of actual programming help, you were super helpful so thank you a lot! my project is basically done for the most part
Joschi
Joschiā€¢3mo ago
Now to the horrible lands of css huh?
jacks
jacksā€¢3mo ago
how did you know šŸ˜­ i was just about to ask about formatting this table
Joschi
Joschiā€¢3mo ago
Yeah that's not something I can help you with. I personally always use some component library like MudBlazor and pray that I don't have to actually touch the CSS too much.
jacks
jacksā€¢3mo ago
gotcha i will just look online for this one cus it should be relatively simple hopefully once again thank you for your help, i really appreciate it and i learn a lot
Joschi
Joschiā€¢3mo ago
Yeah some basic tables should be doable. And there are a lot of ressources for CSS
jacks
jacksā€¢3mo ago
100%
Joschi
Joschiā€¢3mo ago
Is this some project for school / university or just for yourself to learn?
jacks
jacksā€¢3mo ago
it's a project for university
Joschi
Joschiā€¢3mo ago
Good luck then! Looks like a neat project
jacks
jacksā€¢3mo ago
thank you! it's been pretty fun so far just ended up getting stumped and came here and you were able to help me solve it
Joschi
Joschiā€¢3mo ago
Yeah that was a sneaky problem, but we got there in the end.