Exemplo n.º 1
0
        private Connect4ClientConnection waiting; //Player 1 - put into a game as soon as Player 2 is identified. Set to null once the game starts

        #endregion Fields

        #region Constructors

        /// <summary>
        /// Constructs a new Connect4Service object. Takes values to set the port it listens on,
        /// as well as a time limit for games held on this server.
        /// Throws InvalidOperationException if timelimit &lt; 1, or the port number is out of range
        /// or already being listened on.
        /// </summary>
        /// <param name="portNumber">Port for the server to listen on</param>
        /// <param name="timeLimit">Time limit for users in games on this server</param>
        public Connect4Service(int portNumber, int _timeLimit, WhoGoesFirst _choosingMethod)
        {
            if (_timeLimit <= 0)
            {
                throw new InvalidOperationException("time limit must be positive");
            }
            if (portNumber > IPEndPoint.MaxPort || portNumber < IPEndPoint.MinPort)
            {
                throw new InvalidOperationException("invalid port number");
            }
            choosingMethod = _choosingMethod;
            games = new List<Connect4Game>();
            needToIdentify = new List<Connect4ClientConnection>();
            waiting = null;
            timeLimit = _timeLimit;
            server = new TcpListener(IPAddress.Any, portNumber);
            try
            {
                server.Start();
            }
            catch (SocketException)
            {
                throw new InvalidOperationException("port already taken (or something like that)");
            }

            server.BeginAcceptSocket(ConnectionRequested, null);
            isShuttingDown = false;
        }
Exemplo n.º 2
0
        private long whiteTimeLeft; //Time remaining for White's turns

        #endregion Fields

        #region Constructors

        /// <summary>
        /// Constructs a new game between two players. Randomly selects positions (black or white), and sets
        /// up a timer to manage time left for a turn.
        /// </summary>
        /// <param name="client1">Player 1</param>
        /// <param name="client2">Player 2</param>
        /// <param name="timeLimit">Time limit for this game</param>
        public Connect4Game(Connect4ClientConnection client1, Connect4ClientConnection client2, int _timeLimit, 
            Connect4Service.WhoGoesFirst choosingMethod)
        {
            switch (choosingMethod)
            {
                case Connect4Service.WhoGoesFirst.first:
                    black = client1;
                    white = client2;
                    break;
                case Connect4Service.WhoGoesFirst.second:
                    black = client2;
                    white = client1;
                    break;
                case Connect4Service.WhoGoesFirst.random:
                    int tmp;
                    lock (r)
                    {
                        tmp = r.Next() % 2;
                    }
                    if (tmp == 0)
                    {
                        black = client1;
                        white = client2;
                    }
                    else
                    {
                        black = client2;
                        white = client1;
                    }
                    break;
                default:
                    break;
            }

            black.MoveRequest += MoveRequest;
            white.MoveRequest += MoveRequest;
            black.Resign += Resigned;
            white.Resign += Resigned;
            black.Disconnected += Disconnected;
            white.Disconnected += Disconnected;

            timeLimit = _timeLimit;

            whiteTimeLeft = _timeLimit * 1000;
            blackTimeLeft = _timeLimit * 1000;
            blacksMove = true;
            gameBoard = new BoardSquareState[6][];
            for (int i = 0; i < 6; i++)
            {
                gameBoard[i] = new BoardSquareState[7];
                for (int j = 0; j < 7; j++)
                {
                    gameBoard[i][j] = BoardSquareState.empty;
                }
            }

            itsOver = false;

            black.SendPlay(white.Name, _timeLimit, "black");
            white.SendPlay(black.Name, _timeLimit, "white");

            gameTimer = new Timer(1000); // tick every second
            Tick(null, null);
            gameTimer.Elapsed += Tick;
            gameTimer.Start();
        }
Exemplo n.º 3
0
 /// <summary>
 /// Called when a player has resigned from the game. Tells the other player that player left.
 /// </summary>
 /// <param name="player">Player that left</param>
 private void Resigned(Connect4ClientConnection player)
 {
     if (!itsOver)
     {
         string color = (player == white) ? "white" : "black";
         black.SendResigned(color);
         white.SendResigned(color);
         EndGame();
     }
 }
Exemplo n.º 4
0
        /// <summary>
        /// Attempts to make the provided move by the provided player.
        /// If the move can't be made, and it is that player's turn, calls player.SendLegality(false).
        /// If the move can be made, and it is that player's turn, calls player.SendLegality(true), and otherPlayer.SendMove(position).
        /// If it is not that player's turn, ignores request.
        /// </summary>
        /// <param name="col">Column to be moved to</param>
        /// <param name="player">Player making the move</param>
        private void MoveRequest(Connect4ClientConnection player, int col)
        {
            DateTime tmp = System.DateTime.Now;
            lock (this)
            {
                if (!itsOver)
                {
                    Connect4ClientConnection mover = (blacksMove) ? black : white;
                    Connect4ClientConnection waiter = (blacksMove) ? white : black;
                    string color = (blacksMove) ? "black" : "white";
                    BoardSquareState moveState = (blacksMove) ? BoardSquareState.black : BoardSquareState.white;

                    if (player == mover)
                    {
                        col--;
                        int row;
                        if (IsValidMove(col, out row))
                        {
                            gameTimer.Stop();
                            if (blacksMove)
                            {
                                blackTimeLeft -= (int)(tmp.Subtract(lastTime).TotalMilliseconds + 0.5);
                            }
                            else
                            {
                                whiteTimeLeft -= (int)(tmp.Subtract(lastTime).TotalMilliseconds + 0.5);
                            }
                            lastTime = tmp;

                            mover.SendLegality(true);
                            blacksMove = !blacksMove;
                            gameBoard[row][col] = moveState;
                            waiter.SendMove(col + 1);
                            if (IsWinningMove(col, row, moveState))
                            {
                                black.SendWin(color);
                                white.SendWin(color);
                                EndGame();
                            }
                            else if (BoardIsFull())
                            {
                                black.SendDraw();
                                white.SendDraw();
                                EndGame();
                            }
                            else
                            {
                                // start the next timer
                                if (blacksMove)
                                {
                                    gameTimer.Interval = (blackTimeLeft % 1000 == 0) ? 1000 : (blackTimeLeft % 1000);
                                }
                                else
                                {
                                    if (whiteTimeLeft == timeLimit * 1000)
                                    {
                                        Tick(null, null);
                                    }
                                    gameTimer.Interval = (whiteTimeLeft % 1000 == 0) ? 1000 : (whiteTimeLeft % 1000);
                                }
                                gameTimer.Start();
                            }
                        }
                        else
                        {
                            mover.SendLegality(false);
                        }
                    }
                }
            }
        }
Exemplo n.º 5
0
 /// <summary>
 /// Called if a player abruptly disconnects from the server. Informs the other player of this.
 /// </summary>
 /// <param name="player">Player that disconnected</param>
 private void Disconnected(Connect4ClientConnection player)
 {
     if (!itsOver)
     {
         if (player == white)
         {
             black.SendDisconnected("white");
             EndGame();
         }
         else
         {
             white.SendDisconnected("black");
             EndGame();
         }
     }
 }
Exemplo n.º 6
0
        /// <summary>
        /// Shuts down the server, closing all sockets currently open.
        /// </summary>
        public void Shutdown()
        {
            lock (this)
            {
                isShuttingDown = true;

                TcpListener tmp = server;
                server = null;
                tmp.Stop();

                foreach (Connect4Game g in games)
                {
                    Task.Factory.StartNew(() => g.PrepareToDie());
                }
                foreach (Connect4ClientConnection client in needToIdentify)
                {
                    client.NameSpecified -= NameSpecified;
                    client.Disconnected -= Disconnected;
                    client.CloseClient();
                }
                needToIdentify.Clear();
                if (waiting != null)
                {
                    waiting.Disconnected -= Disconnected;
                    waiting.CloseClient();
                    waiting = null;
                }
            }
        }
Exemplo n.º 7
0
 /// <summary>
 /// Called when a player identifies him/herself. Will move into a waiting position, then
 /// if each waiting position is filled, starts a game and nulls each waiting position.
 /// </summary>
 /// <param name="player">Player that did gone and named him/herself</param>
 private void NameSpecified(Connect4ClientConnection player)
 {
     lock (this)
     {
         if (!isShuttingDown)
         {
             needToIdentify.Remove(player);
             player.NameSpecified -= NameSpecified;
             if (waiting == null)
             {
                 waiting = player;
             }
             else
             {
                 Connect4ClientConnection player1 = waiting;
                 waiting = null;
                 player1.Disconnected -= Disconnected;
                 player.Disconnected -= Disconnected;
                 Connect4Game game = new Connect4Game(player1, player, timeLimit, choosingMethod);
                 game.GameHasEnded += GameFinished;
                 games.Add(game);
             }
         }
     }
 }
Exemplo n.º 8
0
 /// <summary>
 /// Called when a player has disconnected before joining a game.
 /// </summary>
 /// <param name="player">Player that disconnected</param>
 private void Disconnected(Connect4ClientConnection player)
 {
     lock (this)
     {
         player.Disconnected -= Disconnected;
         if (player == waiting)
         {
             player.CloseClient();
             waiting = null;
         }
         else
         {
             player.NameSpecified -= NameSpecified;
             needToIdentify.Remove(player);
             player.CloseClient();
         }
     }
 }
Exemplo n.º 9
0
        /// <summary>
        /// Callback for whenever a socket is attempted to be opened with the server.
        /// </summary>
        /// <param name="ar"></param>
        private void ConnectionRequested(IAsyncResult ar)
        {
            try
            {
                if (server != null)
                {
                    Socket s = server.EndAcceptSocket(ar);

                    ////// Uncomment the following line if you want to test with telnet
                    //s.Send(new byte[1] { 60 });
                    ////// Leave it commented otherwise

                    server.BeginAcceptSocket(ConnectionRequested, null);

                    lock (this)
                    {
                        Connect4ClientConnection client = new Connect4ClientConnection(s, this);
                        needToIdentify.Add(client);
                        client.NameSpecified += NameSpecified;
                        client.Disconnected += Disconnected;

                        // just in case the client identified before we hooked up to its NameSpecified event
                        if (client.Name != null)
                        {
                            NameSpecified(client);
                        }
                    }
                }
            }
            catch (Exception)
            {
            }
        }