How to implement timer in a multiplayerchess game? Asp .NET Core
Asked Answered
F

1

0

This is what I currently have: A singleton class GameManager which mostly consists of a ConcurrentDictionary that contains all ongoing games (binds the game board and nicks of both players to the game's ID). I also have a SignalR hub, GameHub with a method MakeAMove(ulong gameId, Move move) that retrieves the relevant gameId game from the dictionary, locks on it, checks if the player who has invoked the method is the player who is now supposed to make a move and if yes, makes appropriate changes to the game's board, broadcasts this move to all observers of this game and if necessary, concludes the game, declaring it to be a victory of player X or a draw and removing it from the dictionary.

What I don't have is the timer. I think the timer is necessary, because without it many games may never conclude and forever linger in this dict. The timer should work in such a way that if a player fails to make a move within the allocated time, the game is automatically concluded and such a player is declared to be the loser.

I don't know how should such a timer be implemented. I have a few ideas, but I'm not sure which one is correct, if any.

The only idea I have to solve this task that doesn't seem to be horrible to me would look like this: ConcurrentDictionary binds gameIds to instances of Game class. Then each such instance has a method that awaits until the timer for the player who is supposed to make a move runs out or until GameHub notifies this method that a move order has been made, whichever happens first. However, I am ignorant how to implement this.

Is this the right way to go? If yes, then how am I supposed to make this method wait until the timer runs out or until a move order comes to GameHub?

EDIT: I SUPPOSE I should write something like this:

await Task.WhenAny(
    Task.Delay(players_available_time_left),  
    ??something_to_mean_a_move_order_has_arrived??
);
  • is this correct? If yes, what should I write instead of the question marks?
Fenland answered 14/6, 2018 at 14:55 Comment(3)
Sounds simpler to have a housekeeping task that does a sweep of the active games, and terminates any which have timed out. How long will the wait time be? A minute? An hour? A day?Plicate
@Plicate Each player gets anywhere in between of 20 sec and 3 mins for each move. Closer to 20 sec if they were thinking for a long time during the previous few moves, closer to 3 mins if they made the previous few moves almost instantly.Fenland
Ah OK. Maybe the task isn't the best solution then - I read "I think the timer is necessary, because without it many games may never conclude and forever linger in this dict." as you were looking to clean-up, rather than implement a game clock.Plicate
K
0

You can simply use a timer that you start every turn and stop after move is done :

private System.Timers.Timer Timer = null;
private double TimerDelay = 30d * 1000d; // 30 seconds
private void StartTimer()
{
    Timer = new System.Timers.Timer() { Interval = TimerDelay , AutoReset = false};
    Timer.Elapsed += Timer_Elapsed;
    Timer.Start();
} 

private void StopTimer()
{
    Timer.Stop();
}     

private void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
    // stop the timer
    StopTimer();

    // call the method to make the player lose and end the game
    EndGame();                
}  

When you start the player turn call the StartTimer() and let it go. When the player ends it's turn call the StopTimer() and it will stop the timer from calling the end of the game. If the timer runs out it will automatically call your end of game.

Kwapong answered 14/6, 2018 at 15:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.