using System; using System.Net; using System.Net.Sockets; using System.IO; using System.Threading; using System.Collections; using System.Runtime.Serialization.Formatters.Binary; using Gin_Rummy_Game; namespace Gin_Rummy_Server { class GinRummyServer { private int port=10; //Port number private static int MAX_CLIENTS=4; private ServerThread[] clientList = new ServerThread[MAX_CLIENTS]; private Thread[] clientThreads = new Thread[MAX_CLIENTS]; private ArrayList playerNames = new ArrayList(); private int numberOfPlayers=4; private IPAddress localAddr = IPAddress.Parse("127.0.0.1"); private bool endClientConnections; private void startGame() { // Used for implementing a timeout for clients to connect for (int i = 0; i < numberOfPlayers; i++) while (!clientList[i].GameStarted) { /* Wait till all client have clicked new game button*/ } } private void closeAllClientConnections() { endClientConnections = true; // Handshake with clients before closing all client connections broadcast("C"); for (int i = 0; i < numberOfPlayers; i++) while (!clientList[i].CloseConnection) { /* Wait for each client to respond */ } Console.WriteLine("Closing all client connections"); for (int i = 0; i < numberOfPlayers; i++) { clientList[i].closeClientConnection(); clientThreads[i].Abort(); } } public GinRummyServer() { int playerCount; try { TcpListener server = new TcpListener(localAddr, port); // Start listening for client requests. server.Start(); bool serverLooping = true; while (serverLooping) { playerCount = 0; while (playerCount < numberOfPlayers) { Console.WriteLine("Waiting for client " + playerCount + " to connect"); TcpClient socketForClient = server.AcceptTcpClient(); if (socketForClient.Connected) { ServerThread listenerThread = new ServerThread(socketForClient, playerCount); Thread thread = new Thread(new ThreadStart(listenerThread.runServerThread)); clientList[playerCount] = listenerThread; clientThreads[playerCount] = thread; thread.Start(); playerCount++; } } endClientConnections = false; while (!endClientConnections) { // Create the deck of cards DeckOfCards drawDeck = new DeckOfCards(false); drawDeck.shuffleDeck(); // Start the server loop to deal the cards playerCount = 0; do { clientList[playerCount].sendMessage("S" + playerCount); // Indicates start game playerNames.Add(clientList[playerCount].PlayerName); playerCount++; } while (playerCount < numberOfPlayers); Thread thread = new Thread(new ThreadStart(startGame)); thread.Start(); thread.Join(10000); // Implement a 10 second timeout if (thread.IsAlive) closeAllClientConnections(); if (!endClientConnections) { // Server loop for dealing deck Player[] players = new Player[numberOfPlayers]; for (int i = 0; i < numberOfPlayers; i++) players[i] = new AutonomousPlayer((string)playerNames[i]); // Deal the cards drawDeck.dealDeck(players, players.Length); // Create the discard deck DeckOfCards discardDeck = new DeckOfCards(true); // Initialize the discard deck and transmit discard deck topcard PlayingCard card = drawDeck.drawCard(); discardDeck.addCard(card); //Broadcast to clients PlayingCardFromDeck cardFromDeck = new PlayingCardFromDeck(card, PlayingCardFromDeck.DeckType.DISCARDDECK); broadcast(cardFromDeck); // Transmit deck sizes int[] deckLabelCounts = { drawDeck.Size, discardDeck.Size }; broadcast(deckLabelCounts); // Transmit the list of player names broadcast(playerNames); // Transmit each players hand PlayingCard[] cards = new PlayingCard[7]; for (int i = 0; i < numberOfPlayers; i++) { for (int j = 0; j < 7; j++) cards[j] = players[i].Hand[j]; clientList[i].sendObject(cards); } // Start the server loop for playing the game playerCount = 0; bool gameOver = false; while (!gameOver) { clientList[playerCount].sendMessage("P"); // Indicates turn to play clientList[playerCount].setDrawDeckTopCard(drawDeck.TopCard); while (clientList[playerCount].RP == null) { /* Wait until client has played hand and return PlayReturn object */ } if (clientList[playerCount].RP.Deck == PlayState.DeckType.NOPLAY) { // Autonomous play. cardFromDeck = new PlayingCardFromDeck(drawDeck.TopCard, PlayingCardFromDeck.DeckType.DRAWDECK); clientList[playerCount].sendObject(cardFromDeck); PlayState rp = players[playerCount].playHand(drawDeck, discardDeck); players[playerCount].upDateDecks(drawDeck, discardDeck, rp); clientList[playerCount].sendObject(rp); } else // Hand played interactively at the client players[playerCount].upDateDecks(drawDeck, discardDeck, clientList[playerCount].RP); // Send the updated hand to the client for (int j = 0; j < 7; j++) cards[j] = players[playerCount].Hand[j]; clientList[playerCount].sendObject(cards); // Reshuffle the discard deck which becomes the draw deck if draw deck empty if (drawDeck.Size == 0) { do { PlayingCard card1 = discardDeck.drawCard(); drawDeck.addCard(card1); } while (discardDeck.Size > 0); drawDeck.shuffleDeck(); PlayingCard card2 = drawDeck.drawCard(); discardDeck.addCard(card2); } // Broadcast to clients discard deck topcard cardFromDeck = new PlayingCardFromDeck(discardDeck.TopCard, PlayingCardFromDeck.DeckType.DISCARDDECK); broadcast(cardFromDeck); // Broadcast to clients the deck counts deckLabelCounts[0] = drawDeck.Size; deckLabelCounts[1] = discardDeck.Size; broadcast(deckLabelCounts); // Check for win condition if (players[playerCount].handValue(players[playerCount].Hand) == 7) { gameOver = true; broadcast("W" + playerCount); // Send the current hands of each player PlayingCard[,] hands = new PlayingCard[numberOfPlayers, 7]; for (int i = 0; i < numberOfPlayers; i++) { for (int j = 0; j < 7; j++) hands[i, j] = players[i].Hand[j]; } broadcast(hands); } clientList[playerCount].RP = null; playerCount = (playerCount + 1) % numberOfPlayers; } Console.Write("End client connections (y/n) : "); String ans = Console.ReadLine(); if (ans[0] == 'y') closeAllClientConnections(); } } } } catch (SocketException e) { Console.WriteLine("SocketException: {0}", e); } } public void broadcast(String broadcastMessage) { for (int i = 0; i < numberOfPlayers; i++) clientList[i].sendMessage(broadcastMessage); } public void broadcast(Object obj) { for (int i = 0; i < numberOfPlayers; i++) clientList[i].sendObject(obj); } public void addPlayerName(string name) { playerNames.Add(name); } public static void Main() { new GinRummyServer(); } } class ServerThread { private TcpClient client; private bool closeConnection = false; private int playerNumber; private bool gameStarted = false; private string playerName; private NetworkStream networkStream; private PlayingCard drawDeckTopCard; private PlayState rp = null; public ServerThread(TcpClient _client, int playerNo) { playerNumber = playerNo; client = _client; networkStream = client.GetStream(); } public void setDrawDeckTopCard(PlayingCard card) { drawDeckTopCard = card; } public bool GameStarted { get { if (gameStarted) { gameStarted = false; return true; } else return false; } } public bool CloseConnection { get { return closeConnection; } set { closeConnection = value; } } public PlayState RP { get { return rp; } set { rp = value; } } public void runServerThread() { playerName = getMessage(); Console.WriteLine("Player " + playerName + " connected"); while (!closeConnection) { object inputObject = readObject(); if (inputObject is string) { string inputString = (string)inputObject; if (inputString[0] == 'S') { gameStarted = true; } else if (inputString[0] == 'D') { PlayingCardFromDeck cardFromDeck = new PlayingCardFromDeck(drawDeckTopCard, PlayingCardFromDeck.DeckType.DRAWDECK); sendObject(cardFromDeck); } else if (inputString[0] == 'C') { closeConnection = true; } } else if (inputObject is PlayState) { rp = (PlayState)inputObject; } } } public void sendMessage(String message) { sendObject(message); } public void sendObject(Object obj) { BinaryFormatter bf = new BinaryFormatter(); bf.Serialize(networkStream, obj); } public string getMessage() { string message = (string) readObject(); return message; } private Object readObject() { BinaryFormatter bf = new BinaryFormatter(); Object obj = bf.Deserialize(networkStream) as Object; return obj; } public string PlayerName { get {return playerName;} } public void closeClientConnection() { client.Close(); } } }