Xamarin.Forms - BugSweeper App

Introduction

This is a familiar game with a new twist. To win, you must find and flag all ten bugs. Ten bugs are hidden in a 9-by-9 grid of tiles.That first double tab is always safe. Thereafter, numbers indicate the number of surrounding tiles with bugs. Flag it with a single tab. Avoid double-tabbing a tile with bug!.
 
Let's start.
 
Step 1

You can create Xamarin.Forms app by going to File >> New >> Visual C# >> Cross-platform >> Cross-Platform App (Xamarin.Native or Xamarin.Forms), enter desired name for your project, and press OK.

(Project name- BugSweeper)

 
 
Step 2

After the project creation, go to Solution Explorer >> BugSweeper(PCL) app >> click open MainPage.xaml and add the following code.

Used ToolBox items,
  • StackLayout
  • Label
  • BoxView
  • Grid
  1. <?xml version="1.0" encoding="utf-8" ?>  
  2. <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"  
  3.              xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"  
  4.              xmlns:local="clr-namespace:BugSwapperApp"  
  5.              x:Class="BugSwapperApp.MainPage">  
  6.   
  7.     <ContentView SizeChanged="OnMainContentView_SizeChanged">  
  8.         <Grid x:Name="mainGrid" ColumnSpacing="0" RowSpacing="0">  
  9.             <Grid.RowDefinitions>  
  10.                 <RowDefinition Height="7*"/>  
  11.                 <RowDefinition Height="4*"/>  
  12.             </Grid.RowDefinitions>  
  13.             <Grid.ColumnDefinitions>  
  14.                 <ColumnDefinition Width="0"/>  
  15.                 <ColumnDefinition Width="*"/>  
  16.             </Grid.ColumnDefinitions>  
  17.             <StackLayout x:Name="textStack" Grid.Row="0" Grid.Column="1" Spacing="0">  
  18.                 <StackLayout HorizontalOptions="Center" Spacing="0">  
  19.                     <Label Text="BugSweeper" Font="Bold, Large" TextColor="Navy"/>  
  20.                     <BoxView Color="Orange" HeightRequest="3"/>  
  21.                 </StackLayout>  
  22.                 <Label Text="Tab to flag/unflag a potential bug" VerticalOptions="CenterAndExpand" HorizontalOptions="Center"/>  
  23.                 <Label Text="Double-tab if you're sure it's not a bug.  
  24.  The First Double tab be safe" VerticalOptions="CenterAndExpand" HorizontalOptions="Center"/>  
  25.                 <StackLayout Orientation="Horizontal" Spacing="0" VerticalOptions="CenterAndExpand" HorizontalOptions="Center">  
  26.                     <Label BindingContext="{x:Reference board}" Text="{Binding FlaggedTileCount,StringFormat='Flagged {0}'}"/>  
  27.                     <Label BindingContext="{x:Reference board}" Text="{Binding BugCount, StringFormat=' out of {0} bugs.'}"/>  
  28.                 </StackLayout>  
  29.   
  30.                 <Label x:Name="timeLabel" Text="0:00" VerticalOptions="CenterAndExpand" HorizontalOptions="Center"/>  
  31.             </StackLayout>  
  32.             <ContentView Grid.Row="1" Grid.Column="1" SizeChanged="OnBoardContentView_SizeChanged">  
  33.                 <Grid>  
  34.                     <Grid.RowDefinitions>  
  35.                         <RowDefinition Height="*"/>  
  36.                     </Grid.RowDefinitions>  
  37.                     <Grid.ColumnDefinitions>  
  38.                         <ColumnDefinition Width="*"/>  
  39.                     </Grid.ColumnDefinitions>  
  40.                     <local:Board x:Name="board"/>  
  41.                     <StackLayout x:Name="congratulationsText" Orientation="Horizontal" HorizontalOptions="Center" VerticalOptions="Center" Spacing="0">  
  42.                         <Label Text="C" TextColor="Black"/>  
  43.                         <Label Text="O" TextColor="Black"/>  
  44.                         <Label Text="N" TextColor="Black"/>  
  45.                         <Label Text="G" TextColor="Black"/>  
  46.                         <Label Text="R" TextColor="Black"/>  
  47.                         <Label Text="A" TextColor="Black"/>  
  48.                         <Label Text="T" TextColor="Black"/>  
  49.                         <Label Text="U" TextColor="Black"/>  
  50.                         <Label Text="L" TextColor="Black"/>  
  51.                         <Label Text="A" TextColor="Black"/>  
  52.                         <Label Text="T" TextColor="Black"/>  
  53.                         <Label Text="I" TextColor="Black"/>  
  54.                         <Label Text="O" TextColor="Black"/>  
  55.                         <Label Text="N" TextColor="Black"/>  
  56.                         <Label Text="S" TextColor="Black"/>  
  57.                         <Label Text="!" TextColor="Black"/>  
  58.                         <Label Text="!" TextColor="Black"/>  
  59.                      </StackLayout>  
  60.                     <StackLayout x:Name="consolationText" Orientation="Horizontal" Spacing="0" HorizontalOptions="Center" VerticalOptions="Center">  
  61.                         <Label Text="T" TextColor="Black"/>  
  62.                         <Label Text="O" TextColor="Black"/>  
  63.                         <Label Text="O" TextColor="Black"/>  
  64.                         <Label Text="L" TextColor="Black"/>  
  65.                         <Label Text="O" TextColor="Black"/>  
  66.                         <Label Text="S" TextColor="Black"/>  
  67.                         <Label Text="T" TextColor="Black"/>  
  68.                         <Label Text="!" TextColor="Black"/>  
  69.                         <Label Text=":" TextColor="Gray"/>  
  70.                         <Label Text=")" TextColor="Green"/>  
  71.                     </StackLayout>  
  72.                     <Button x:Name="playAgainButton" Text="Play Another Game?" VerticalOptions="Center" HorizontalOptions="Center" Clicked="onplayAgainButton_Clicked" BorderColor="Black" BorderWidth="2" BackgroundColor="White" TextColor="Blue"/>  
  73.                 </Grid>  
  74.             </ContentView>  
  75.               
  76.         </Grid>  
  77.                   
  78.     </ContentView>  
  79.   
  80. </ContentPage> 


Step 3

In this step, open Solution Explorer >> BugSweeper (PCL) >> MainPage.xaml.cs and double click to open MainPage.xaml.cs. Here is the code.
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5. using System.Threading.Tasks;  
  6. using Xamarin.Forms;  
  7.   
  8. namespace BugSwapperApp  
  9. {  
  10.     public partial class MainPage : ContentPage  
  11.     {  
  12.         const string timeFormat = @"%m\:ss";  
  13.   
  14.         bool isGameInProgress;  
  15.         DateTime gameStartTime;  
  16.         public MainPage()  
  17.         {  
  18.             InitializeComponent();  
  19.   
  20.             board.GameStarted += (sender, args) =>  
  21.             {  
  22.                 isGameInProgress = true;  
  23.                 gameStartTime = DateTime.Now;  
  24.                 Device.StartTimer(TimeSpan.FromSeconds(1), () =>  
  25.                 {  
  26.                     timeLabel.Text = (DateTime.Now - gameStartTime).ToString(timeFormat);  
  27.                     return isGameInProgress;  
  28.                 });  
  29.             }; board.GameEnded += (sender, hasWon) =>  
  30.             {  
  31.                 isGameInProgress = false;  
  32.   
  33.                 if (hasWon)  
  34.                 {  
  35.                     DisplayWonAnimation();  
  36.                 }  
  37.                 else  
  38.                 {  
  39.                     DisplayLostAnimation();  
  40.                 }  
  41.             };  
  42.             PrepareForNewGame();  
  43.         }  
  44.         void PrepareForNewGame()  
  45.         {  
  46.             board.NewGameInitialize();  
  47.   
  48.             congratulationsText.IsVisible = false;  
  49.             consolationText.IsVisible = false;  
  50.             playAgainButton.IsVisible = false;  
  51.             playAgainButton.IsEnabled = false;  
  52.   
  53.             timeLabel.Text = new TimeSpan().ToString(timeFormat);  
  54.             isGameInProgress = false;  
  55.         }  
  56.   
  57.          void OnMainContentView_SizeChanged(object sender, EventArgs e)  
  58.         {  
  59.             ContentView contentView = (ContentView)sender;  
  60.             double width = contentView.Width;  
  61.             double height = contentView.Height;  
  62.   
  63.             bool isLandscape = width > height;  
  64.   
  65.             if (isLandscape)  
  66.             {  
  67.                 mainGrid.RowDefinitions[0].Height = 0;  
  68.                 mainGrid.RowDefinitions[1].Height = new GridLength(1, GridUnitType.Star);  
  69.   
  70.                 mainGrid.ColumnDefinitions[0].Width = new GridLength(1, GridUnitType.Star);  
  71.                 mainGrid.ColumnDefinitions[1].Width = new GridLength(1, GridUnitType.Star);  
  72.   
  73.                 Grid.SetRow(textStack, 1);  
  74.                 Grid.SetColumn(textStack, 0);  
  75.             }  
  76.             else // portrait  
  77.             {  
  78.                 mainGrid.RowDefinitions[0].Height = new GridLength(3, GridUnitType.Star);  
  79.                 mainGrid.RowDefinitions[1].Height = new GridLength(5, GridUnitType.Star);  
  80.   
  81.                 mainGrid.ColumnDefinitions[0].Width = 0;  
  82.                 mainGrid.ColumnDefinitions[1].Width = new GridLength(1, GridUnitType.Star);  
  83.   
  84.                 Grid.SetRow(textStack, 0);  
  85.                 Grid.SetColumn(textStack, 1);  
  86.             }  
  87.         }  
  88.   
  89.          void OnBoardContentView_SizeChanged(object sender, EventArgs e)  
  90.         {  
  91.             ContentView contentView = (ContentView)sender;  
  92.             double width = contentView.Width;  
  93.             double height = contentView.Height;  
  94.             double dimension = Math.Min(width, height);  
  95.             double horzPadding = (width - dimension) / 2;  
  96.             double vertPadding = (height - dimension) / 2;  
  97.             contentView.Padding = new Thickness(horzPadding, vertPadding);  
  98.         }  
  99.         async void DisplayWonAnimation()  
  100.         {  
  101.             congratulationsText.Scale = 0;  
  102.             congratulationsText.IsVisible = true;  
  103.   
  104.             // Because IsVisible has been false, the text might not have a size yet,   
  105.             //  in which case Measure will return a size.  
  106.             double congratulationsTextWidth = congratulationsText.Measure(Double.PositiveInfinity, Double.PositiveInfinity).Request.Width;  
  107.   
  108.             congratulationsText.Rotation = 0;  
  109.             congratulationsText.RotateTo(3 * 360, 1000, Easing.CubicOut);  
  110.   
  111.             double maxScale = 0.9 * board.Width / congratulationsTextWidth;  
  112.             await congratulationsText.ScaleTo(maxScale, 1000);  
  113.   
  114.             foreach (View view in congratulationsText.Children)  
  115.             {  
  116.                 view.Rotation = 0;  
  117.                 view.RotateTo(180);  
  118.                 await view.ScaleTo(3, 100);  
  119.                 view.RotateTo(360);  
  120.                 await view.ScaleTo(1, 100);  
  121.             }  
  122.   
  123.             await DisplayPlayAgainButton();  
  124.         }  
  125.   
  126.         async void DisplayLostAnimation()  
  127.         {  
  128.             consolationText.Scale = 0;  
  129.             consolationText.IsVisible = true;  
  130.   
  131.             // (See above for rationale)  
  132.             double consolationTextWidth = consolationText.Measure(Double.PositiveInfinity, Double.PositiveInfinity).Request.Width;  
  133.   
  134.             double maxScale = 0.9 * board.Width / consolationTextWidth;  
  135.             await consolationText.ScaleTo(maxScale, 1000);  
  136.             await Task.Delay(1000);  
  137.             await DisplayPlayAgainButton();  
  138.         }  
  139.   
  140.         async Task DisplayPlayAgainButton()  
  141.         {  
  142.             playAgainButton.Scale = 0;  
  143.             playAgainButton.IsVisible = true;  
  144.             playAgainButton.IsEnabled = true;  
  145.   
  146.             // (See above for rationale)  
  147.             double playAgainButtonWidth = playAgainButton.Measure(Double.PositiveInfinity, Double.PositiveInfinity).Request.Width;  
  148.   
  149.             double maxScale = board.Width / playAgainButtonWidth;  
  150.             await playAgainButton.ScaleTo(maxScale, 1000, Easing.SpringOut);  
  151.         }  
  152.   
  153.   
  154.   
  155.          void onplayAgainButton_Clicked(object sender, EventArgs e)  
  156.         {  
  157.             PrepareForNewGame();  
  158.         }  
  159.     }  
  160. }  

 
Step 4
 
Open Solution Explorer >> BugSweeper(PCL) >> right click and select New Item. In this popup window, select Cross Platform >> Class.

This way, you can add a new class. Now, create a new class named Board.cs and double-click to get into its design view and insert the code given below.
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5. using System.Threading.Tasks;  
  6. using Xamarin.Forms;  
  7.   
  8. namespace BugSwapperApp  
  9. {  
  10.     class Board : AbsoluteLayout  
  11.     {  
  12.         const int COLS = 9;           
  13.         const int ROWS = 9;          
  14.         const int BUGS = 10;  
  15.         Tile[,] tiles = new Tile[ROWS, COLS];  
  16.         int flaggedTileCount;  
  17.         bool isGameInProgress;                
  18.         bool isGameInitialized;               
  19.         bool isGameEnded;  
  20.   
  21.         public event EventHandler GameStarted;  
  22.         public event EventHandler<bool> GameEnded;  
  23.         public Board()  
  24.         {  
  25.             for (int row = 0; row < ROWS; row++)  
  26.                 for (int col = 0; col < COLS; col++)  
  27.                 {  
  28.                     Tile tile = new Tile(row, col);  
  29.                     tile.TileStatusChanged += OnTileStatusChanged;  
  30.                     this.Children.Add(tile);  
  31.                     tiles[row, col] = tile;  
  32.                 }  
  33.   
  34.             SizeChanged += (sender, args) =>  
  35.             {  
  36.                 double tileWidth = this.Width / COLS;  
  37.                 double tileHeight = this.Height / ROWS;  
  38.   
  39.                 foreach (Tile tile in tiles)  
  40.                 {  
  41.                     Rectangle bounds = new Rectangle(tile.Col * tileWidth,  
  42.                                                      tile.Row * tileHeight,  
  43.                                                      tileWidth, tileHeight);  
  44.                     AbsoluteLayout.SetLayoutBounds(tile, bounds);  
  45.                 }  
  46.             };  
  47.   
  48.             NewGameInitialize();  
  49.         }  
  50.   
  51.         public void NewGameInitialize()  
  52.         {  
  53.             // Clear all the tiles.  
  54.             foreach (Tile tile in tiles)  
  55.                 tile.Initialize();  
  56.   
  57.             isGameInProgress = false;  
  58.             isGameInitialized = false;  
  59.             isGameEnded = false;  
  60.             this.FlaggedTileCount = 0;  
  61.         }  
  62.   
  63.         public int FlaggedTileCount  
  64.         {  
  65.             set  
  66.             {  
  67.                 if (flaggedTileCount != value)  
  68.                 {  
  69.                     flaggedTileCount = value;  
  70.                     OnPropertyChanged();  
  71.                 }  
  72.             }  
  73.             get  
  74.             {  
  75.                 return flaggedTileCount;  
  76.             }  
  77.         }  
  78.   
  79.         public int BugCount  
  80.         {  
  81.             get  
  82.             {  
  83.                 return BUGS;  
  84.             }  
  85.         }  
  86.   
  87.   
  88.         // Not called until the first tile is double-tapped.  
  89.         void DefineNewBoard(int tappedRow, int tappedCol)  
  90.         {  
  91.             // Begin the assignment of bugs.  
  92.             Random random = new Random();  
  93.             int bugCount = 0;  
  94.   
  95.             while (bugCount < BUGS)  
  96.             {  
  97.                 // Get random row and column.  
  98.                 int row = random.Next(ROWS);  
  99.                 int col = random.Next(COLS);  
  100.   
  101.                 // Skip it if it's already a bug.  
  102.                 if (tiles[row, col].IsBug)  
  103.                 {  
  104.                     continue;  
  105.                 }  
  106.   
  107.                 // Avoid the tappedRow & Col & surrounding ones.  
  108.                 if (row >= tappedRow - 1 &&  
  109.                     row <= tappedRow + 1 &&  
  110.                     col >= tappedCol - 1 &&  
  111.                     col <= tappedCol + 1)  
  112.                 {  
  113.                     continue;  
  114.                 }  
  115.   
  116.                 // It's a bug!  
  117.                 tiles[row, col].IsBug = true;  
  118.   
  119.                 // Calculate the surrounding bug count.  
  120.                 CycleThroughNeighbors(row, col,  
  121.                     (neighborRow, neighborCol) =>  
  122.                     {  
  123.                         ++tiles[neighborRow, neighborCol].SurroundingBugCount;  
  124.                     });  
  125.   
  126.                 bugCount++;  
  127.             }  
  128.         }  
  129.   
  130.         void CycleThroughNeighbors(int row, int col, Action<intint> callback)  
  131.         {  
  132.             int minRow = Math.Max(0, row - 1);  
  133.             int maxRow = Math.Min(ROWS - 1, row + 1);  
  134.             int minCol = Math.Max(0, col - 1);  
  135.             int maxCol = Math.Min(COLS - 1, col + 1);  
  136.   
  137.             for (int neighborRow = minRow; neighborRow <= maxRow; neighborRow++)  
  138.                 for (int neighborCol = minCol; neighborCol <= maxCol; neighborCol++)  
  139.                 {  
  140.                     if (neighborRow != row || neighborCol != col)  
  141.                         callback(neighborRow, neighborCol);  
  142.                 }  
  143.         }  
  144.   
  145.         void OnTileStatusChanged(object sender, TileStatus tileStatus)  
  146.         {  
  147.             if (isGameEnded)  
  148.                 return;  
  149.   
  150.             // With a first tile tapped, the game is now in progress.  
  151.             if (!isGameInProgress)  
  152.             {  
  153.                 isGameInProgress = true;  
  154.   
  155.                 // Fire the GameStarted event.  
  156.                 if (GameStarted != null)  
  157.                 {  
  158.                     GameStarted(this, EventArgs.Empty);  
  159.                 }  
  160.             }  
  161.   
  162.             // Update the "flagged" bug count before checking for a loss.  
  163.             int flaggedCount = 0;  
  164.   
  165.             foreach (Tile tile in tiles)  
  166.                 if (tile.Status == TileStatus.Flagged)  
  167.                     flaggedCount++;  
  168.   
  169.             this.FlaggedTileCount = flaggedCount;  
  170.   
  171.             // Get the tile whose status has changed.  
  172.             Tile changedTile = (Tile)sender;  
  173.   
  174.             // If it's exposed, some actions are required.  
  175.             if (tileStatus == TileStatus.Exposed)  
  176.             {  
  177.                 if (!isGameInitialized)  
  178.                 {  
  179.                     DefineNewBoard(changedTile.Row, changedTile.Col);  
  180.                     isGameInitialized = true;  
  181.                 }  
  182.   
  183.                 if (changedTile.IsBug)  
  184.                 {  
  185.                     isGameInProgress = false;  
  186.                     isGameEnded = true;  
  187.   
  188.                     // Fire the GameEnded event!  
  189.                     if (GameEnded != null)  
  190.                     {  
  191.                         GameEnded(thisfalse);  
  192.                     }  
  193.                     return;  
  194.                 }  
  195.   
  196.                 // Auto expose for zero surrounding bugs.  
  197.                 if (changedTile.SurroundingBugCount == 0)  
  198.                 {  
  199.                     CycleThroughNeighbors(changedTile.Row, changedTile.Col,  
  200.                         (neighborRow, neighborCol) =>  
  201.                         {  
  202.                             // Expose all the neighbors.  
  203.                             tiles[neighborRow, neighborCol].Status = TileStatus.Exposed;  
  204.                         });  
  205.                 }  
  206.             }  
  207.   
  208.             // Check for a win.  
  209.             bool hasWon = true;  
  210.   
  211.             foreach (Tile til in tiles)  
  212.             {  
  213.                 if (til.IsBug && til.Status != TileStatus.Flagged)  
  214.                     hasWon = false;  
  215.   
  216.                 if (!til.IsBug && til.Status != TileStatus.Exposed)  
  217.                     hasWon = false;  
  218.             }  
  219.   
  220.             // If there's a win, celebrate!  
  221.             if (hasWon)  
  222.             {  
  223.                 isGameInProgress = false;  
  224.                 isGameEnded = true;  
  225.   
  226.                 // Fire the GameEnded event!  
  227.                 if (GameEnded != null)  
  228.                 {  
  229.                     GameEnded(thistrue);  
  230.                 }  
  231.                 return;  
  232.             }  
  233.         }  
  234.     }  
  235. }  
 

Step 5

Now, we need to add images. For that, go to Solution Explorer >> BugSweeper(PCL) >> right-click on BugSweeper(PCL) project and select Add>> Existing Item. In this popup window, select images to insert and the images are used for tiles.
  1. BugSwapperApp.Microsoft.png  
  2. BugSwapperApp.Microsoft.png  
Step 6

In this step, similarly, create a new class named Tile.cs. Here is the code for this class.
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5. using System.Threading.Tasks;  
  6. using Xamarin.Forms;  
  7.   
  8. namespace BugSwapperApp  
  9. {  
  10.     enum TileStatus  
  11.     {  
  12.         Hidden,  
  13.         Flagged,  
  14.         Exposed  
  15.     }  
  16.     class Tile : Frame  
  17.     {  
  18.         TileStatus tileStatus = TileStatus.Hidden;  
  19.         Label label;  
  20.         Image flagImage, bugImage;  
  21.         static ImageSource flagImageSource;  
  22.         static ImageSource bugImageSource;  
  23.         bool doNotFireEvent;  
  24.   
  25.         public event EventHandler<TileStatus> TileStatusChanged;  
  26.   
  27.         static Tile()  
  28.         {  
  29.             flagImageSource = ImageSource.FromResource("BugSwapperApp.Microsoft.png");  
  30.             bugImageSource = ImageSource.FromResource("BugSwapperApp.Xbox.png");  
  31.         }  
  32.   
  33.         public Tile(int row , int col)  
  34.         {  
  35.             this.Row = row;  
  36.             this.Col = col;  
  37.   
  38.             this.BackgroundColor = Color.Yellow;  
  39.             this.OutlineColor = Color.Blue;  
  40.             this.Padding = 2;  
  41.   
  42.             label = new Label  
  43.             {  
  44.                 Text = " ",  
  45.                 TextColor = Color.Yellow,  
  46.                 BackgroundColor = Color.Blue,  
  47.                 HorizontalTextAlignment = TextAlignment.Center,  
  48.                 VerticalTextAlignment = TextAlignment.Center,  
  49.             };  
  50.   
  51.             flagImage = new Image  
  52.             {  
  53.                 Source = flagImageSource,  
  54.   
  55.             };  
  56.   
  57.             bugImage = new Image  
  58.             {  
  59.                 Source = bugImageSource  
  60.             };  
  61.   
  62.             TapGestureRecognizer singleTap = new TapGestureRecognizer  
  63.             {  
  64.                 NumberOfTapsRequired = 1  
  65.             };  
  66.             singleTap.Tapped += OnSingleTap;  
  67.             this.GestureRecognizers.Add(singleTap);  
  68.             if (Device.OS != TargetPlatform.Windows && Device.OS != TargetPlatform.WinPhone)  
  69.             {  
  70.                 TapGestureRecognizer doubleTap = new TapGestureRecognizer  
  71.                 {  
  72.                     NumberOfTapsRequired = 2  
  73.                 };  
  74.                 doubleTap.Tapped += OnDoubleTap;  
  75.                 this.GestureRecognizers.Add(doubleTap);  
  76.   
  77.   
  78.             }  
  79.         }  
  80.   
  81.         public int Row { private setget; }  
  82.   
  83.         public int Col { private setget; }  
  84.   
  85.         public bool IsBug { setget; }  
  86.   
  87.         public int SurroundingBugCount { setget; }  
  88.   
  89.         public TileStatus Status  
  90.         {  
  91.             set  
  92.             {  
  93.                 if (tileStatus != value)  
  94.                 {  
  95.                     tileStatus = value;  
  96.   
  97.                     switch (tileStatus)  
  98.                     {  
  99.                         case TileStatus.Hidden:  
  100.                             this.Content = null;  
  101.  
  102. #if FIX_WINDOWS_PHONE_NULL_CONTENT  
  103.   
  104.                             if (Device.OS == TargetPlatform.WinPhone || Device.OS == TargetPlatform.Windows) {  
  105.                                 this.Content = new Label { Text = " " };  
  106.                             }  
  107.  
  108. #endif  
  109.                             break;  
  110.   
  111.                         case TileStatus.Flagged:  
  112.                             this.Content = flagImage;  
  113.                             break;  
  114.   
  115.                         case TileStatus.Exposed:  
  116.                             if (this.IsBug)  
  117.                             {  
  118.                                 this.Content = bugImage;  
  119.                             }  
  120.                             else  
  121.                             {  
  122.                                 this.Content = label;  
  123.                                 label.Text =  
  124.                                         (this.SurroundingBugCount > 0) ?  
  125.                                             this.SurroundingBugCount.ToString() : " ";  
  126.                             }  
  127.                             break;  
  128.                     }  
  129.   
  130.                     if (!doNotFireEvent && TileStatusChanged != null)  
  131.                     {  
  132.                         TileStatusChanged(this, tileStatus);  
  133.                     }  
  134.                 }  
  135.             }  
  136.             get  
  137.             {  
  138.                 return tileStatus;  
  139.             }  
  140.         }  
  141.   
  142.         // Does not fire TileStatusChanged events.  
  143.         public void Initialize()  
  144.         {  
  145.             doNotFireEvent = true;  
  146.             this.Status = TileStatus.Hidden;  
  147.             this.IsBug = false;  
  148.             this.SurroundingBugCount = 0;  
  149.             doNotFireEvent = false;  
  150.         }  
  151.   
  152.   
  153.   
  154.         bool lastTapSingle;  
  155.         DateTime lastTapTime;  
  156.   
  157.   
  158.         void OnSingleTap(object sender, object args)  
  159.         {  
  160.   
  161.             switch (this.Status)  
  162.             {  
  163.                 case TileStatus.Hidden:  
  164.                     this.Status = TileStatus.Flagged;  
  165.                     break;  
  166.   
  167.                 case TileStatus.Flagged:  
  168.                     this.Status = TileStatus.Hidden;  
  169.                     break;  
  170.   
  171.                 case TileStatus.Exposed:  
  172.   
  173.                     break;  
  174.             }  
  175.         }  
  176.   
  177.         void OnDoubleTap(object sender, object args)  
  178.         {  
  179.             this.Status = TileStatus.Exposed;  
  180.         }  
  181.     }  
  182. }  
 
 
Step 7

Click ' F5 ' or Build to run your projects. Running this project, you will have the result like below.

 
 
Finally, we have successfully created a Xamarin.Forms BugSweeper Application.

Up Next
    Ebook Download
    View all
    Learn
    View all