public async Task<ActionResult> MakeMove(Guid id, int x, int y) { var guid = GetGuid(); var game = GameGrainFactory.GetGrain(id); var move = new GameMove { PlayerId = guid, X = x, Y = y }; var state = await game.MakeMove(move); return Json(state, JsonRequestBehavior.AllowGet); }
// make a move during the game public async Task<GameState> MakeMove(GameMove move) { // check if its a legal move to make if (this.GameState != GameState.InPlay) throw new ApplicationException("This game is not in play"); if (ListOfPlayers.IndexOf(move.PlayerId) < 0) throw new ArgumentException("No such playerid for this game", "move"); if (move.PlayerId != ListOfPlayers[indexNextPlayerToMove]) throw new ArgumentException("The wrong player tried to make a move", "move"); if (move.X < 0 || move.X > 2 || move.Y < 0 || move.Y > 2) throw new ArgumentException("Bad co-ordinates for a move", "move"); if (theBoard[move.X, move.Y] != -1) throw new ArgumentException("That square is not empty", "move"); // record move this.ListOfMoves.Add(move); this.theBoard[move.X, move.Y] = indexNextPlayerToMove; // check for a winning move var win = false; if (!win) for (int i = 0; i < 3 && !win; i++) win = isWinningLine(theBoard[i, 0], theBoard[i, 1], theBoard[i, 2]); if (!win) for (int i = 0; i < 3 && !win; i++) win = isWinningLine(theBoard[0, i], theBoard[1, i], theBoard[2, i]); if (!win) win = isWinningLine(theBoard[0, 0], theBoard[1, 1], theBoard[2, 2]); if (!win) win = isWinningLine(theBoard[0, 2], theBoard[1, 1], theBoard[2, 0]); // check for draw var draw = false; if (this.ListOfMoves.Count() == 9) draw = true; // we could try to look for stalemate earlier, if we wanted // handle end of game if (win || draw) { // game over this.GameState = GameState.Finished; if (win) { WinnerId = ListOfPlayers[indexNextPlayerToMove]; LoserId = ListOfPlayers[(indexNextPlayerToMove + 1) % 2]; } // collect tasks up, so we await both notifications at the same time var promises = new List<Task>(); // inform this player of outcome var playerGrain = PlayerGrainFactory.GetGrain(ListOfPlayers[indexNextPlayerToMove]); promises.Add(playerGrain.LeaveGame(this.GetPrimaryKey(), win ? GameOutcome.Win : GameOutcome.Draw)); // inform other player of outcome playerGrain = PlayerGrainFactory.GetGrain(ListOfPlayers[(indexNextPlayerToMove + 1) % 2]); promises.Add(playerGrain.LeaveGame(this.GetPrimaryKey(), win ? GameOutcome.Lose : GameOutcome.Draw)); await Task.WhenAll(promises); return this.GameState; } // if game hasnt ended, prepare for next players move indexNextPlayerToMove = (indexNextPlayerToMove + 1) % 2; return this.GameState; }