Exemplo n.º 1
0
        /// <inheritdoc />
        public GameMoveDetails GetMove(string gameId, int moveNumber)
        {
            if (string.IsNullOrWhiteSpace(gameId))
            {
                throw new ArgumentException(nameof(gameId));
            }

            if (moveNumber < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(moveNumber));
            }

            var game = GetById(gameId);

            if (game == null)
            {
                return(null);
            }

            LoadGameBoard(game);

            var move = game.GameBoard.Moves.ElementAtOrDefault(moveNumber);

            if (move == null)
            {
                return(null);
            }

            return(GameMoveDetails.FromEntity(game, move));
        }
Exemplo n.º 2
0
        public virtual IActionResult PlayMove([FromRoute][Required] string gameId, [FromRoute][Required] string playerName, [FromBody][Required] int column)
        {
            try
            {
                var gameMove = new GameMoveDetails()
                {
                    Player = playerName,
                    Column = column,
                    Type   = GameMove.MoveType.MOVE
                };

                var move = _gameService.PlayMove(gameId, gameMove);
                if (move == null)
                {
                    return(NotFound());
                }

                return(CreatedAtAction(nameof(GetMove), new { gameId, moveNumber = move.MoveId }, move));
            }
            catch (PlayerTurnException)
            {
                return(Conflict());
            }
            catch (PlayerNotFoundException)
            {
                return(NotFound());
            }
            // InvalidOperationException means the play was invalid
            catch (InvalidOperationException)
            {
                return(BadRequest());
            }
        }
Exemplo n.º 3
0
        /// <inheritdoc />
        public GameMove PlayMove(string gameId, GameMoveDetails newMove)
        {
            if (string.IsNullOrWhiteSpace(gameId))
            {
                throw new ArgumentException(nameof(gameId));
            }

            if (newMove == null)
            {
                throw new ArgumentNullException(nameof(newMove));
            }

            var game = GetById(gameId);

            if (game == null)
            {
                return(null);
            }

            if (GetActivePlayer(game).Name != newMove.Player)
            {
                throw new PlayerTurnException($"It is not {newMove.Player}'s turn");
            }

            if (GetGameState(game) == Game.GameState.DONE)
            {
                throw new InvalidOperationException($"Game is finished! Cannot play new moves.");
            }

            var player = game.Players.SingleOrDefault(p => p.Name == newMove.Player);

            if (player == null)
            {
                throw new PlayerNotFoundException($"{newMove.Player} does not exist in game {gameId}");
            }

            if (!game.GameBoard.DropToken(newMove.Column, player.Id))
            {
                throw new InvalidOperationException($"Could not place token in column {newMove.Column}; column is full");
            }

            var move = new GameMove()
            {
                Column   = newMove.Column,
                PlayerId = player.Id,
                MoveId   = game.GameBoard.Moves.Count() + 1, // TODO: This smells inefficient - is there a better way than re-counting? Check the generated SQL.
                Type     = newMove.Type
            };

            game.GameBoard.Moves.Add(move);
            game.State = GetGameState(game);

            Context.SaveChanges();  // TODO: Leaky abstraction; move to data layer?

            return(move);
        }
Exemplo n.º 4
0
        /// <inheritdoc />
        public IEnumerable <GameMoveDetails> GetMoves(string gameId)
        {
            if (string.IsNullOrWhiteSpace(gameId))
            {
                throw new ArgumentException(nameof(gameId));
            }

            var game = GetById(gameId);

            if (game == null)
            {
                return(null);
            }

            LoadGameBoard(game);

            return(game.GameBoard.Moves.Select(move => GameMoveDetails.FromEntity(game, move)));
        }
Exemplo n.º 5
0
        /// <inheritdoc />
        public IEnumerable <GameMoveDetails> GetMoves(string gameId, int start, int until)
        {
            if (string.IsNullOrWhiteSpace(gameId))
            {
                throw new ArgumentException(nameof(gameId));
            }

            if (start < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(start));
            }

            if (until < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(until));
            }

            if (until < start)
            {
                throw new ArgumentException("until cannot be less than start");
            }

            var game = GetById(gameId);

            if (game == null)
            {
                return(null);
            }

            LoadGameBoard(game);

            // TODO: This could be more efficient by only returning the desired rows from the database
            // instead of loading them all into memory, then converting to array, then segmenting it
            var moves = new ArraySegment <GameMove>(game.GameBoard.Moves.ToArray(), start, until - start + 1);

            return(moves.Select(move => GameMoveDetails.FromEntity(game, move)));
        }