コード例 #1
0
        // main algorithm, finds a rectangle to shoot
        public Rectangle GetShot()
        {
            Rectangle rect;

            // if a hit was prior to this shot, get the first field next to the hit field
            if (this._nextShots.Count > 0)
            {
                // the direction can be known, when all surrounding fields are already shot and only one is left. If thats the case, only get the first horizontal or vertical rect aligned
                if (this._hitDirection != Direction.Unknown)
                {
                    this._nextShots = this._hitDirection == Direction.Horizontal ? this._nextShots.OrderByDescending(x => x.Direction).ToList() : this._nextShots.OrderBy(x => x.Direction).ToList();
                }

                // it can happen that a rectangle in this list is already shot, so do this until we find one with an Unknown result
                while (this._nextShots.Count > 0)
                {
                    // get the first rect in the list and convert it's coordinates to integers
                    rect = this._nextShots.First().Rect;
                    var coords = Calculation.CharCoordsToInt(rect.Uid);
                    int x = coords[0], y = coords[1];

                    // don't consider already hit rectangles
                    if (this._board[x, y] == ShotResult.Unknown)
                    {
                        this._lastShotDirection = this._nextShots.First().Direction;
                        this._nextShots.RemoveAt(0);
                        return(rect);
                    }

                    this._nextShots.RemoveAt(0);
                }
            }

            // if we have no shots left to consider, get one at random, where the state is still unknown
            var shots = new List <ScanShot>();

            for (var x = 0; x < GameSize; x++)
            {
                for (var y = 0; y < GameSize; y++)
                {
                    if (this._board[x, y] == ShotResult.Unknown)
                    {
                        shots.Add(new ScanShot(new Rectangle {
                            Uid = $"x: {x}, y: {y}, {Field}"
                        }, this.OpenSpaces(x, y)));
                    }
                }
            }

            // get the rectangle with the most open spaces to cover, to maximaize hit probability
            shots = shots.OrderByDescending(x => x.OpenSpaces).ToList();
            var maxOpenSpaces = shots.FirstOrDefault().OpenSpaces;

            var scanShots2 = shots.Where(x => x.OpenSpaces == maxOpenSpaces).ToList();

            rect = scanShots2[this._rand.Next(scanShots2.Count)].Rect;

            return(rect);
        }
コード例 #2
0
        // if a shot hit, do a few things, set the result of the rect to Hit and add all rectangles next to it to the next posible shots
        public void ShotHit(Rectangle rect, bool sunk)
        {
            var coords = Calculation.CharCoordsToInt(rect.Uid);
            var x      = coords[0];
            var y      = coords[1];

            if (x < 0 || y < 0)
            {
                this._board[x, y]  = ShotResult.Unknown;
                this._hitDirection = Direction.Unknown;
                return;
            }

            // set the state of this rectangle on the board to Hit
            this._board[x, y] = ShotResult.Hit;

            // if the ship wasn't sunk, add all surrounding rects to a list of shots to try next, else try a random position again
            if (!sunk)
            {
                this._hitDirection = this._lastShotDirection;
                if (x != 0)
                {
                    this._nextShots.Add(new NextShot(new Rectangle {
                        Uid = $"x: {x - 1}, y: {y}, {Field}"
                    }, Direction.Horizontal));
                }

                if (y != 0)
                {
                    this._nextShots.Add(new NextShot(new Rectangle {
                        Uid = $"x: {x}, y: {y - 1}, {Field}"
                    }, Direction.Vertical));
                }

                if (x != GameSize - 1)
                {
                    this._nextShots.Add(new NextShot(new Rectangle {
                        Uid = $"x: {x + 1}, y: {y}, {Field}"
                    }, Direction.Horizontal));
                }

                if (y != GameSize - 1)
                {
                    this._nextShots.Add(new NextShot(new Rectangle {
                        Uid = $"x: {x}, y: {y + 1}, {Field}"
                    }, Direction.Vertical));
                }
            }
            else
            {
                this._hitDirection = Direction.Unknown;
                this._nextShots.Clear();
            }
        }
コード例 #3
0
ファイル: Farnsworth.cs プロジェクト: curtisy1/SchoolProjects
        // when we miss something, update state
        public void ShotMiss(Rectangle rect)
        {
            var coords = Calculation.CharCoordsToInt(rect.Uid);
            int x = coords[0], y = coords[1];

            if (x < 0 || y < 0)
            {
                this._state[x, y] = State.Unknown;
                return;
            }

            this._state[x, y] = State.Miss;
        }
コード例 #4
0
        // if a shot missed, set the state to Miss
        public void ShotMiss(Rectangle rect)
        {
            var coords = Calculation.CharCoordsToInt(rect.Uid);
            var x      = coords[0];
            var y      = coords[1];

            if (x < 0 || y < 0)
            {
                this._board[x, y] = ShotResult.Unknown;
                return;
            }

            this._board[x, y] = ShotResult.Miss;
        }
コード例 #5
0
ファイル: Farnsworth.cs プロジェクト: curtisy1/SchoolProjects
        // when we hit something, update state
        public void ShotHit(Rectangle rect, bool sunk)
        {
            var coords = Calculation.CharCoordsToInt(rect.Uid);
            int x = coords[0], y = coords[1];

            this._state[x, y] = sunk ? State.Sunk : State.Hit;

            // if we know that we just sunk a ship at (x,y), look at adjacent locations to see if we
            // had to have sunk a given ship (i.e. if there's only one remaining ship that has a size
            // less than the sunk length, that ship must have sunk.)
            if (sunk)
            {
                var localLeft = x;
                while (localLeft > 0 && (this._state[localLeft - 1, y] == State.Hit || this._state[localLeft - 1, y] == State.Sunk))
                {
                    --localLeft;
                }

                var localRight = x;
                while (localRight < GameSize - 1 && (this._state[localRight + 1, y] == State.Hit || this._state[localRight + 1, y] == State.Sunk))
                {
                    ++localRight;
                }

                var localAbove = y;
                while (localAbove > 0 && (this._state[x, localAbove - 1] == State.Hit || this._state[x, localAbove - 1] == State.Sunk))
                {
                    --localAbove;
                }

                var localBelow = y;
                while (localBelow < GameSize - 1 && (this._state[x, localBelow + 1] == State.Hit || this._state[x, localBelow + 1] == State.Sunk))
                {
                    ++localBelow;
                }

                var sunkWidth  = localRight - localLeft + 1;
                var sunkHeight = localBelow - localAbove + 1;
                if (sunkWidth > 1)
                {
                    var numShips = 0;
                    foreach (var w in this._remainingShips)
                    {
                        if (w <= sunkWidth)
                        {
                            ++numShips;
                        }
                    }

                    if (numShips == 1)
                    {
                        this._remainingShips.Remove(sunkWidth);
                    }
                }
                else if (sunkHeight > 1)
                {
                    var numShips = 0;
                    foreach (var w in this._remainingShips)
                    {
                        if (w <= sunkHeight)
                        {
                            ++numShips;
                        }
                    }

                    if (numShips == 1)
                    {
                        this._remainingShips.Remove(sunkHeight);
                    }
                }
            }
        }