Click here to Skip to main content
15,884,693 members
Articles / Programming Languages / C#

Navy Battle Game - III

Rate me:
Please Sign up or sign in to vote.
4.65/5 (17 votes)
11 Aug 2005CPOL17 min read 86.4K   3.6K   65  
An article on creating a multi-player game using the TGSDK.
using System;
using System.Collections;
using TG.Daemon;

namespace NavyBattleDaemon
{
	/// <summary>
	/// Summary description for Game.
	/// </summary>
	class Game
	{
		public delegate void MsgToGroupEventHandler(Guid id, Hashtable msg);
		public delegate void MsgToPlayerEventHandler(Guid id, int PlayerNumber, Hashtable msg);
		public delegate void GameOverEventHandler(Guid id); // Send game-over message to all players
		public delegate void PlayerLeftGameEventHandler(Guid id, Guid playerGuid);
		public delegate void PostErrorEventHandler(string text);

		public event MsgToGroupEventHandler MsgToGroupEvent;
		public event MsgToPlayerEventHandler MsgToPlayerEvent;
		public event GameOverEventHandler GameOverEvent;
		public event PlayerLeftGameEventHandler PlayerLeftGameEvent;
		public static event PostErrorEventHandler PostErrorEvent;

		#region Navy Battle game specific data members
		private const int NumPlayers = 2;
		private Guid m_id;
		private TG.Daemon.GameGroup m_group; // Consisting of 2 players min
		private int m_turn;
		private int[][,] m_Placement = new int[2][,];
		#endregion

		public Game(Guid groupId, TG.Daemon.GameGroup group)
		{
			m_id = groupId;
			m_group = group;
		}

		public void StartFirstGame()
		{
			StartNewGame();
		}

		public void StartNewGame()
		{
			// TODO: Add code here to start up game here
		}

		public void EndGame()
		{
			// TODO: Add code here to clean up game here

			// Tell each player that the other has left the game. (which is true enough)
			Hashtable msg = new Hashtable();
			msg.Add("MsgType", "UserLeavingGame");
			msg.Add("Player", 0);
			MsgToPlayerEvent(m_id, 1, msg);
			msg["Player"] = 1;
			MsgToPlayerEvent(m_id, 0, msg);
		}

		public void MsgReceive(int playerNum, Hashtable msg)
		{
			if (msg.Contains("MsgType"))
			{
				string MsgType = (string)msg["MsgType"];
				switch(MsgType)
				{
					case "InitialPlacement":
						ProcessInitialPlacement(msg);
						break;

					case "Move":
						ProcessMove(msg);
						break;

					case "UserLeavingGame":
						ProcessUserLeavingGame(msg);
						break;
				}
			}
		}

		#region Navy Battle game message handler code
		private void ProcessInitialPlacement(Hashtable msg)
		{
			int player = (int)msg["Player"];
			int[,] Placement = (int[,])msg["Placement"];
			m_Placement[player] = Placement;

			if (m_Placement[0] != null && m_Placement[1] != null)
			{
				// send out the first update
				Hashtable updateMessage = new Hashtable();
				updateMessage.Add("MsgType", "Update");
				updateMessage.Add("Winner", -1); // no winner;
				updateMessage.Add("Turn", 0);
				//updateMessage.Add("AttackCoordinates", coordinates); none - this first time.
				MsgToGroupEvent(m_id, updateMessage);
			}
		}

		private void ProcessMove(Hashtable msg)
		{
			// Retrieve information from message
			int player = (int)msg["Player"];
			int coordinates = (int)msg["AttackCoordinates"]; //0..24
			int x = coordinates % 5;
			int y = coordinates / 5;
			int target = (player + 1) % NumPlayers; // the other player is the target

			// record the shot
			m_Placement[target][x,y] |= 2;

			// see if it was a hit
			bool hit = false;
			if ((m_Placement[target][x,y] & 1) > 0)
				hit = true;

			int winner = -1; // no winner

			// increment the turn
			m_turn = (m_turn + 1) % NumPlayers;
						
			// check for all ships destroyed.
			if (hit)
			{
				// If the 'target' player has no ships left that haven't been hit then they lose.
				// the Grid value will be 1 for an undamaged ship, 2 for a shot that missed, and 
				// 3 for a destroyed ship
				int UndamagedShips = 0;
				for(int i = 0; i < 5; i++)
				{
					for(int j = 0; j < 5; j++)
					{
						if (m_Placement[target][i,j] == 1)
							UndamagedShips++;
					}
				}
						
				// game is over
				if (UndamagedShips == 0)
				{
					winner = player;
				}
			}

			Hashtable updateMessage = new Hashtable();
			updateMessage.Add("MsgType", "Update");
			updateMessage.Add("Winner", winner);
			updateMessage.Add("Turn", m_turn);
			updateMessage.Add("AttackCoordinates", coordinates);
			updateMessage.Add("Hit", hit);

			if (winner > -1)
			{
				// this is so we can expose the winning players ship locations
				// to the losing player (kind of rubbing his nose in it)
				updateMessage.Add("Placement", m_Placement[winner]);
			}
			// Broadcast update message to both players
			MsgToGroupEvent(m_id, updateMessage);
		}

		private void ProcessUserLeavingGame(Hashtable msg)
		{
			int leavingPlayerNum = Convert.ToInt32(msg["Player"]);
			int opponent = (leavingPlayerNum + 1) % NumPlayers;
			MsgToPlayerEvent(m_id, opponent, msg);
			TG.Daemon.GamePerson leavingPlayer = (TG.Daemon.GamePerson)m_group.Players[leavingPlayerNum];
			leavingPlayer.PlayerStatus = TG.Daemon.GamePerson.UserStatus.Dropped;
			int numPlayersInTheGame = 0;

			foreach(TG.Daemon.GamePerson player in m_group.Players.Values)
			{
				if (player.PlayerStatus == TG.Daemon.GamePerson.UserStatus.Connected)
					numPlayersInTheGame += 1;
			}

			// If num players left in game is less than min players, then game is over
			PlayerLeftGameEvent(m_id, (Guid)m_group.PlayerNumberToGuid[leavingPlayerNum]);
			if (numPlayersInTheGame < NumPlayers)
				GameOverEvent(m_id);
		}
		#endregion
	}
}

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)


Written By
Founder SpreadTrends.com
United States United States
I've authored many articles that tackle real-world issues to save my peers in the development community valuable time. For example I've written articles that: show how to decode Ogg Vorbis audio files using the .NET Framework; describe best practices for Improving Entity Framework performance; and demonstrate step-by-step how to create a multi-player game.

Comments and Discussions