練手WPF(二)——2048遊戲的簡易實現(上)

一、建立遊戲界面
編輯MainWindow.xaml,修改代碼以下:數組

<Window.Resources>
        <Style TargetType="Label">
            <Setter Property="Height" Value="105" />
            <Setter Property="Width" Value="105" />
            <Setter Property="HorizontalContentAlignment" Value="Center"/>
            <Setter Property="VerticalContentAlignment" Value="Center" />
            <Setter Property="FontWeight" Value="Bold"/>
            <Setter Property="Opacity" Value="0.7" />
        </Style>
        <Style TargetType="Rectangle">
            <Setter Property="Width" Value="105"/>
            <Setter Property="Height" Value="105"/>
            <Setter Property="Fill" Value="#ccc0b2"/>
        </Style>
    </Window.Resources>
    <Grid HorizontalAlignment="Left">
        <Grid.RowDefinitions>
            <RowDefinition Height="100"/>
            <RowDefinition Height="500"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="20"/>
            <ColumnDefinition Width="500"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <Image Grid.Row="0" Grid.Column="1" Source="/Images/title2048.png"/>
        <Canvas x:Name="myCanvas" Grid.Row="1" Grid.Column="1" Width="495" Height="495" Background="#b8af9e"/>
        <StackPanel Grid.Row="0" Grid.Column="2" Orientation="Horizontal" VerticalAlignment="Bottom" HorizontalAlignment="Center">
            <Button x:Name="btnNewGame" Content="新的起點" Width="80" Margin="8" Height="30" 
                    Click="BtnNewGame_Click"  Focusable="False" />
            <Button x:Name="btnOldGame" Content="舊的征程" Width="80" Margin="8" Height="30" Focusable="False"/>
        </StackPanel>
        <Grid Grid.Row="1" Grid.Column="2" Margin="10"  >
            <Grid.RowDefinitions>
                <RowDefinition Height="0.5*"/>
                <RowDefinition Height="*"/>
                <RowDefinition Height="0.5*"/>
                <RowDefinition Height="*"/>
                <RowDefinition Height="0.5*"/>
                <RowDefinition Height="*"/>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>
            <TextBlock Text="當前得分: " Width="210" FontSize="20" VerticalAlignment="Bottom"/>
            <Label x:Name="lblCurrScore" Grid.Row="1" Content="2048" Width="210" FontSize="40" 
                   Foreground="Maroon" Opacity="1" />
            <Label x:Name="lblAddScore" Grid.Row="1" Content="0" Width="210" FontSize="20" 
                   Foreground="Chocolate" Opacity="0" >
                <Label.RenderTransform>
                    <TranslateTransform x:Name="tt" X="0" Y="0"/>
                </Label.RenderTransform>
            </Label>

            <TextBlock Text="最高記錄: " Grid.Row="2" Width="210" FontSize="20" VerticalAlignment="Bottom"/>
            <Label x:Name="lblBastScore" Grid.Row="3" Content="0" Width="210" FontSize="35" 
                   Foreground="DarkGray" Opacity="1" />
            <Button x:Name="btnShowTopScore" Grid.Row="4" Content="排行榜" Width="80" Margin="8" Height="25" HorizontalAlignment="Right"
                    Focusable="False"/>
            <Button x:Name="btnExitGame" Grid.Row="5" Content="退出遊戲" Width="80" Margin="8" Height="30" 
                    HorizontalAlignment="Right" VerticalAlignment="Bottom"  Focusable="False" Click="BtnExitGame_Click"/>
        </Grid>
    </Grid>

(1)在Window資源區分別定義了Label和Rectangle的樣式,由於接下來遊戲區的4宮格中使用的主要是對Lebel控件進行顯示和移動操做的。
(2)另外還添加一個命名爲lblAddScore的Lebel控件(其初始透明度爲0,即徹底透明),用於增長成績時的動畫效果,其中定義了命名爲tt的TranslateTransform變換效果。
(3)遊戲主區控件爲Canvas,命名爲myCanvas。
(4)其餘能夠根據本身的喜愛進行調整。dom

 

二、定義幾個字段變量
畢竟是小遊戲,直接從MainWindow.xaml.cs開始下手了。字體

int lblWidth = 105;                     // 方塊大小
int lblPadding = 15;                    // 方塊間隙

int[,] gridData = null;                 // 遊戲主數據數組
Label[,] lblArray = null;               // 用於顯示成方塊的Label數組

int currScore = 0;                      // 當前成績

bool isStarted = false;                 // 遊戲是否已開始

Random rnd = new Random();             // 隨機數

 

三、幾個開始須要調用的方法

   3.1 遊戲開始數字板
界面中的16個遊戲數字爲0時,只顯示空的16塊小板面,其顏色比背景色稍淺。動畫

/// <summary>
///  顯示背景矩形塊
/// </summary>
private void ShowBackRect()
{
    for (int y = 0; y < 4; y++)
    {
        for (int x = 0; x < 4; x++)
        {
            Rectangle rect = new Rectangle();
            rect.SetValue(Canvas.LeftProperty, (double)((x + 1) * lblPadding + x * lblWidth));
            rect.SetValue(Canvas.TopProperty, (double)((y + 1) * lblPadding + y * lblWidth));
            myCanvas.Children.Add(rect);
        }
    }
}

  3.2 生成新數
遊戲開始後,須要隨機生成值爲2或4的兩個新數字。以後,每上、下、左、右移動其中一次界面中的數字後,若是還有空位,又須要隨機生成一個2或4的新數字。spa

/// <summary>
/// 重載生成新數
/// </summary>
/// <returns></returns>
private bool NewNum()
{
    int num = rnd.Next(0, 9) > 2 ? 2 : 4;

    int nullnum = 0;
    for (int y = 0; y < 4; y++)
    {
        for (int x = 0; x < 4; x++)
        {
            if (gridData[y, x] == 0)
                nullnum++;
        }
    }

    if (nullnum < 1)
    {
        return false;
    }

    int index = rnd.Next(1, nullnum);
    nullnum = 0;
    for (int y = 0; y < 4; y++)
    {
        for (int x = 0; x < 4; x++)
        {
            if (gridData[y, x] == 0)
            {
                nullnum++;
                if (nullnum != index)
                    continue;

                gridData[y, x] = num;
            }
        }
    }

    return true;
}

先統計出界面中剩餘空格數,再從空格數中獲取隨機數做爲新數位置,賦值2或4之一。

code

  3.3 設置Label板背景色和前景字體大小
根據gridData元素值的高低,顯示不一樣的背景色和字體大小orm

/// <summary>
/// 根據數值生成方塊背景色值
/// </summary>
/// <param name="num"></param>
/// <returns></returns>
private Brush SetBackground(int num)
{
    Brush backColor;
    switch (num)
    {
        case 2:
            backColor = new SolidColorBrush(Color.FromRgb(0xee, 0xe4, 0xda));
            break;
        case 4:
            backColor = new SolidColorBrush(Color.FromRgb(0xec, 0xe0, 0xc8));
            break;
        case 8:
            backColor = new SolidColorBrush(Color.FromRgb(0xf2, 0xb1, 0x79));
            break;
        case 16:
            backColor = new SolidColorBrush(Color.FromRgb(0xf5, 0x95, 0x63));
            break;
        case 32:
            backColor = new SolidColorBrush(Color.FromRgb(0xf5, 0x7c, 0x5f));
            break;
        case 64:
            backColor = new SolidColorBrush(Color.FromRgb(0xf6, 0x5d, 0x3b));
            break;
        case 128:
            backColor = new SolidColorBrush(Color.FromRgb(0xed, 0xce, 0x71));
            break;
        case 256:
            backColor = new SolidColorBrush(Color.FromRgb(0xed, 0xcc, 0x61));
            break;

        case 512:
            backColor = new SolidColorBrush(Color.FromRgb(0xec, 0xc8, 0x50));
            break;
        case 1024:
            backColor = new SolidColorBrush(Color.FromRgb(0xed, 0xc5, 0x3f));
            break;
        case 2048:
            backColor = new SolidColorBrush(Color.FromRgb(0xee, 0xc2, 0x2e));
            break;
        case 4096:
            backColor = new SolidColorBrush(Color.FromRgb(0xef, 0x85, 0x9c));
            break;
        default:
            backColor = new SolidColorBrush(Color.FromRgb(0xcc, 0xc0, 0xb2));
            break;
    }
    return backColor;
}

/// <summary>
/// 根據數值設置方塊字體大小
/// </summary>
/// <param name="num"></param>
/// <returns></returns>
private int SetFontSize(int num)
{
    int iFontsize;
    switch (num)
    {
        case 2:
        case 4:
        case 8:
            iFontsize = 55;
            break;

        case 16:
        case 32:
        case 64:
            iFontsize = 50;
            break;

        case 128:
        case 256:
        case 512:
            iFontsize = 40;
            break;

        case 1024:
        case 2048:
        case 4096:
            iFontsize = 33;
            break;

        default:
            iFontsize = 30;
            break;
    }
    return iFontsize;
}

 

  3.4 顯示遊戲區的全部Label控件
若是gridData元素值不爲0的話,生成Label控件並添加到遊戲板中。blog

/// <summary>
/// 從新顯示全部Label
/// </summary>
private void ShowAllLabel()
{
    myCanvas.Children.Clear();
    ShowBackRect();

    for (int y = 0; y < 4; y++)
    {
        for (int x = 0; x < 4; x++)
        {
            if (gridData[y, x] != 0)
            {
                lblArray[y, x] = new Label();
                lblArray[y, x].SetValue(Canvas.LeftProperty, lblPadding * (x + 1) + (double)(x * lblWidth));
                lblArray[y, x].SetValue(Canvas.TopProperty, lblPadding * (y + 1) + (double)(y * lblWidth));
                lblArray[y, x].SetValue(Label.ContentProperty, gridData[y, x].ToString());
                lblArray[y, x].SetValue(Label.BackgroundProperty, SetBackground(gridData[y, x]));
                lblArray[y, x].SetValue(Label.FontSizeProperty, (double)SetFontSize(gridData[y, x]));
                myCanvas.Children.Add(lblArray[y, x]);
            }
        }
    }
}

 

四、初始化遊戲數據遊戲

/// <summary>
/// 初始化數據
/// </summary>
private void InitData()
{
    if (gridData != null)                       // 初始化主數據數組
        gridData = null;

    gridData = new int[4, 4]
    {
        { 0, 0, 0, 0 },
        { 0, 0, 0, 0 },
        { 0, 0, 0, 0 },
        { 0, 0, 0, 0 }
    };

    if (lblArray != null)                       // 初始化顯示用Label數組
        lblArray = null;

    lblArray = new Label[4, 4];

    if (myCanvas.Children.Count > 0)
        myCanvas.Children.Clear();              // 清除界面

    NewNum();                                   // 生成兩個新數
    NewNum();

    ShowAllLabel();                             // 刷新遊戲方塊

    isStarted = true;
    currScore = 0;                              // 初始化當前成績爲0

    lblCurrScore.Content = currScore.ToString();// 更新當前成績顯示
}

將InitData()方法添加到BtnNewGame_Click按鈕事件方法中。

如今運行遊戲,不斷點擊開始新遊戲按鈕,會在不一樣位置生成兩個2或4的數字,並顯示出來。
事件

 

五、判斷遊戲是否結束
判斷每一行是否存在空位,若是有則未結束。若是該行已滿,則看看是否存在相鄰是否有相同的數字,若是有則說明能夠合併出新空位,即未結束。
列判斷方式相同。

/// <summary>
/// 遊戲是否結束
/// </summary>
/// <returns></returns>
private bool isGameOver()
{
    for (int row = 0; row < 4; row++)
    {
        for (int i = 0; i < 4; i++)
        {
            if (gridData[row, i] == 0)  // 是否有空位
            {
                return false;
            }
        }
        for (int i = 0; i < 3; i++)
        {
            if (gridData[row, i] == gridData[row, i + 1])
            {
                return false;
            }
        }
    }

    for (int col = 0; col < 4; col++)
    {
        for (int i = 0; i < 4; i++)
        {
            if (gridData[i, col] == 0)
            {
                return false;
            }
        }
        for (int i = 0; i < 3; i++)
        {
            if (gridData[i, col] == gridData[i + 1, col])
            {
                return false;
            }
        }
    }

    return true;
}

/// <summary>
/// 顯示動畫結束對話框
/// </summary>
private void ShowGameOver()
{
    MessageBox.Show("遊戲已經結束。", "Game Over", MessageBoxButton.OK, MessageBoxImage.Information);
    isStarted = false;
}
相關文章
相關標籤/搜索