Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version

Reversi for Windows Mobile

, 12 May 2009
The game Reversi for Windows Mobile using the Compact Framework.
using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;


namespace GameExample.Reversi
{
    /// <summary>
    /// The reserve tile game.
    /// </summary>
    public class Game
    {
        /// <summary>
        /// The board.
        /// </summary>
        private Board _board;
        /// <summary>
        /// The current player.
        /// </summary>
        private Player _currentPlayer;
        /// <summary>
        /// The possible player one moves.
        /// </summary>
        private Point[] _playerOneMoves;
        /// <summary>
        /// The possible player two moves.
        /// </summary>
        private Point[] _playerTwoMoves;
        /// <summary>
        /// Playerones current positions.
        /// </summary>
        private Point[] _playerOneCurrent;
        /// <summary>
        /// Playertwos current positions.
        /// </summary>
        private Point[] _playerTwoCurrent;

        /// <summary>
        /// Initializes a new instance of the <see cref="Game"/> class.
        /// </summary>
        /// <param name="options">The options.</param>
        public Game(GameOptions options)
        {
            if (options == null)
            {
                throw new ArgumentNullException("options");
            }
            _board = new Board(options.BoardWidth, options.BoardHeight);
            TogglePlayer();
        }

        /// <summary>
        /// Gets the current player.
        /// </summary>
        /// <value>The current player.</value>
        public Player CurrentPlayer
        {
            get
            {
                return _currentPlayer;
            }
        }

        public Player Leader
        {
            get
            {
                int p1 = PlayerOnePositions.Count, p2 = PlayerTwoPositions.Count;
                return p1 == p2 ? Player.NotSet : (p1 > p2 ? Player.PlayerOne : Player.PlayerTwo);
            }
        }

        /// <summary>
        /// Gets the board.
        /// </summary>
        /// <value>The board.</value>
        public Board Board
        {
            get
            {
                return _board;
            }
        }

        /// <summary>
        /// Gets the player one moves.
        /// </summary>
        /// <value>The player one moves.</value>
        public IList<Point> PlayerOneMoves
        {
            get
            {
                return _playerOneMoves;
            }
        }

        /// <summary>
        /// Gets the player two moves.
        /// </summary>
        /// <value>The player two moves.</value>
        public IList<Point> PlayerTwoMoves
        {
            get
            {
                return _playerOneMoves;
            }
        }

        /// <summary>
        /// Gets the player one positions.
        /// </summary>
        /// <value>The player one positions.</value>
        public IList<Point> PlayerOnePositions
        {
            get
            {
                return _playerOneCurrent;
            }
        }

        /// <summary>
        /// Gets the player two positions.
        /// </summary>
        /// <value>The player two positions.</value>
        public IList<Point> PlayerTwoPositions
        {
            get
            {
                return _playerTwoCurrent;
            }
        }

        /// <summary>
        /// Gets the current player moves.
        /// </summary>
        /// <value>The current player moves.</value>
        public IList<Point> CurrentPlayerMoves
        {
            get
            {
                return _currentPlayer == Player.PlayerOne ?
                    _playerOneMoves : _playerTwoMoves;
            }
        }

        /// <summary>
        /// Gets a value indicating whether [game over].
        /// </summary>
        /// <value><c>true</c> if [game over]; otherwise, <c>false</c>.</value>
        public bool GameOver
        {
            get {
                return _playerTwoMoves.Length == 0 &&
                    _playerOneMoves.Length == 0;
            }
        }

        /// <summary>
        /// Gets a value indicating whether [current player has move].
        /// </summary>
        /// <value>
        /// 	<c>true</c> if [current player has move]; otherwise, <c>false</c>.
        /// </value>
        public bool CurrentPlayerHasMove
        {
            get
            {
                return CurrentPlayerMoves.Count != 0;
            }
        }

        /// <summary>
        /// Executes a move in the game.
        /// </summary>
        /// <param name="position">The position.</param>
        /// <param name="player">The player.</param>
        public bool Move(Point position, Player player)
        {
            // Not the current players move so ignore.
            if (_currentPlayer != player)
            {
                return false;
            }
            // The move is outside the board.
            if (position.X >= _board.BoardWidth || position.Y >= _board.BoardHeight)
            {
                return false;
            }
            // Already a player in that position.
            if (_board[position.X, position.Y].Player != Player.NotSet)
            {
                return false;
            }
            
            bool validMove = false;

            validMove |= UpdateDirection(position, Direction.East, player);
            validMove |= UpdateDirection(position, Direction.North, player);
            validMove |= UpdateDirection(position, Direction.NorthEast, player);
            validMove |= UpdateDirection(position, Direction.NorthWest, player);
            validMove |= UpdateDirection(position, Direction.South, player);
            validMove |= UpdateDirection(position, Direction.SouthEast, player);
            validMove |= UpdateDirection(position, Direction.SouthWest, player);
            validMove |= UpdateDirection(position, Direction.West, player);
            if (validMove)
            {
                _board[position.X, position.Y] = new Position(player);
                TogglePlayer();
            }
            return validMove;
        }

        /// <summary>
        /// Skips this instance.
        /// </summary>
        public bool Skip()
        {
            if (CurrentPlayerMoves.Count == 0)
            {
                _currentPlayer = _currentPlayer == Player.PlayerOne ?
                    Player.PlayerTwo : Player.PlayerOne;
                return true;
            }
            return false;
        }

        //public IList<KeyValuePair<int, Point>> GetRankedMoves(Player player)
        //{
        //}
        



        /// <summary>
        /// Determines whether [is move valid] [the specified position].
        /// </summary>
        /// <param name="position">The position.</param>
        /// <param name="player">The player.</param>
        /// <returns>
        /// 	<c>true</c> if [is move valid] [the specified position]; otherwise, <c>false</c>.
        /// </returns>
        public bool IsMoveValid(Point position, Player player)
        {
            // Set other player
            Player otherPlayer = player == Player.PlayerOne ? Player.PlayerTwo : Player.PlayerOne;
            Point endPoint;
  
            // This one already has a player.
            if (_board[position.X, position.Y].Player != Player.NotSet)
            {
                return false;
            }

            if (CheckDirection(position, Direction.East, player, out endPoint) ||
                CheckDirection(position, Direction.North, player, out endPoint) ||
                CheckDirection(position, Direction.NorthEast, player, out endPoint) ||
                CheckDirection(position, Direction.NorthWest, player, out endPoint) ||
                CheckDirection(position, Direction.South, player, out endPoint) ||
                CheckDirection(position, Direction.SouthEast, player, out endPoint) ||
                CheckDirection(position, Direction.SouthWest, player, out endPoint) ||
                CheckDirection(position, Direction.West, player, out endPoint))
            {
                return true;
            }
            return false;
        }       

        /// <summary>
        /// Gets all the availible moves for a player.
        /// </summary>
        /// <param name="player"></param>
        /// <returns></returns>
        public IEnumerable<Point> GetMoves(Player player)
        {
            Position[] boardPositons = _board.Data;
            int x, y;

            for (int i = 0; i < boardPositons.Length; i++)
            {
                // This one already has a player.
                if (boardPositons[i].Player != Player.NotSet)
                {
                    continue;
                }

                //  Get the x and y
                y = i / _board.BoardWidth;
                x = i - (y * _board.BoardWidth);

                // If the move is valid then return it.
                if (IsMoveValid(new Point(x, y), player))
                {
                    yield return new Point(x, y);
                }
            }
        }

        /// <summary>
        /// Gets all the positions currently held by the player.
        /// </summary>
        /// <param name="player">The player.</param>
        /// <returns></returns>
        public IEnumerable<Point> GetPositions(Player player)
        {
            Position[] boardPositons = _board.Data;
            int x, y;
            
            for (int i = 0; i < boardPositons.Length; i++)
            {
                //  Get the x and y
                y = i / _board.BoardWidth;
                x = i - (y * _board.BoardWidth);

                if (boardPositons[i].Player == player)
                {
                    yield return new Point(x, y);
                }
            }
        }

        /// <summary>
        /// Checks the positions in the direction of the point to see if the move is valid.
        /// </summary>
        /// <param name="point">The point.</param>
        /// <param name="direction">The direction to check</param>
        /// <param name="player">The player that is moving.</param>
        /// <returns></returns>
        public bool CheckDirection(Point point, Direction direction, Player player, out Point endPoint)
        {
            Point directionMod = GetDirectionModifier(direction);
            int xMod = directionMod.X, yMod = directionMod.Y;
            int x = point.X + xMod, y = point.Y + yMod;

            Player otherPlayer = player == Player.PlayerOne ? Player.PlayerTwo : Player.PlayerOne;
            Player currentPlayer;
            bool hasOther = false;

            while (x > -1 && x < _board.BoardWidth &&
                    y > -1 && y < _board.BoardHeight)
            {
                // Get the current player.
                currentPlayer = _board[x, y].Player;

                // Got to the end and no match.
                if ( currentPlayer == Player.NotSet )
                {
                    break;
                }
                else if ( currentPlayer == otherPlayer )
                {
                    hasOther = true;
                }
                else if ( currentPlayer == player )
                {
                    if (hasOther)
                    {
                        endPoint = new Point(x-=xMod, y-=yMod);
                        return true;
                    }
                    endPoint = Point.Empty;
                    return false;
                }

                // Move to next position.
                x += xMod;
                y += yMod;
            }
            endPoint = Point.Empty;
            return false;

            
        }

        /// <summary>
        /// Checks the direction and claims any positions for the current player.
        /// </summary>
        /// <param name="position">The position.</param>
        /// <param name="direction">The direction.</param>
        /// <param name="player">The player.</param>
        /// <returns></returns>
        private bool UpdateDirection(Point position, Direction direction, Player player)
        {
            IEnumerable<Point> modifiedPositions;
            Point endPoint;

            if (CheckDirection(position, direction, player, out endPoint))
            {
                modifiedPositions = GetPositions(position, endPoint);
                foreach (Point p in modifiedPositions)
                {
                    _board[p.X, p.Y] = new Position(player, 0);
                }
                return true;
            }
            return false;
        }
        
        /// <summary>
        /// Toggles the player.
        /// </summary>
        private void TogglePlayer()
        {
            _currentPlayer = _currentPlayer == Player.PlayerOne ? Player.PlayerTwo : Player.PlayerOne;
            _playerOneMoves = GetMoves(Player.PlayerOne).ToArray();
            _playerTwoMoves = GetMoves(Player.PlayerTwo).ToArray();
            _playerOneCurrent = GetPositions(Player.PlayerOne).ToArray();
            _playerTwoCurrent = GetPositions(Player.PlayerTwo).ToArray();
        }
        
        /// <summary>
        /// Gets the positions in a straight line from the starting point to the endpoint.
        /// </summary>
        /// <param name="start">The start.</param>
        /// <param name="end">The end.</param>
        /// <returns></returns>
        private static IEnumerable<Point> GetPositions(Point start, Point end)
        {            

            Point directionMod = GetDirectionModifier(start,end);
            int xMod = directionMod.X, yMod = directionMod.Y;
            int x = start.X, y = start.Y;

            do
            {
                // Move to next position.
                x += xMod;
                y += yMod;

                // Return to the point
                yield return new Point(x, y);
            }
            while (x != end.X ||
                    y != end.Y );
        }
       
        /// <summary>
        /// Gets the direction modifiers.
        /// </summary>
        /// <param name="direction">The direction.</param>
        /// <returns></returns>
        private static Point GetDirectionModifier(Direction direction)
        {
            int x, y;
            switch (direction)
            {
                case Direction.East:
                    x = 1;
                    y = 0;
                    break;
                case Direction.North:
                    y = -1;
                    x = 0;
                    break;
                case Direction.NorthEast:
                    y = -1;
                    x = 1;
                    break;
                case Direction.NorthWest:
                    y = -1;
                    x = -1;
                    break;
                case Direction.South:
                    y = 1;
                    x = 0;
                    break;
                case Direction.SouthEast:
                    y = 1;
                    x = 1;
                    break;
                case Direction.SouthWest:
                    y = 1;
                    x = -1;
                    break;
                case Direction.West:
                    y = 0;
                    x = -1;
                    break;
                default:
                    x = 0;
                    y = 0;
                    break;

            }
            return new Point(x, y);
        }

        /// <summary>
        /// Gets the direction modifier.
        /// </summary>
        /// <param name="start">The starting point.</param>
        /// <param name="end">The end point.</param>
        /// <returns></returns>
        private static Point GetDirectionModifier(Point start, Point end)
        {
            return new Point(
                start.X > end.X ? -1 : ( end.X > start.X ? 1 : 0),
                start.Y > end.Y ? -1 : ( end.Y > start.Y ? 1 : 0)
                );
        }
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Ziad Elmalki

United States United States
No Biography provided

| Advertise | Privacy | Mobile
Web03 | 2.8.140721.1 | Last Updated 13 May 2009
Article Copyright 2009 by Ziad Elmalki
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid