1、创建游戏界面
编辑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的Label控件(其初始透明度为0,即完全透明),用于增加成绩时的动画效果,其中定义了命名为tt的TranslateTransform变换效果。
(3)游戏主区控件为Canvas,命名为myCanvas。
(4)其他可以根据自己的喜好进行调整。

2、定义几个字段变量
毕竟是小游戏,直接从MainWindow.xaml.cs开始下手了。

int lblWidth = ;                     // 方块大小
int lblPadding = ; // 方块间隙 int[,] gridData = null; // 游戏主数据数组
Label[,] lblArray = null; // 用于显示成方块的Label数组 int currScore = ; // 当前成绩 bool isStarted = false; // 游戏是否已开始 Random rnd = new Random(); // 随机数

3、几个开始需要调用的方法

   3.1 游戏开始数字板
界面中的16个游戏数字为0时,只显示空的16块小板面,其颜色比背景色稍浅。

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

  3.2 生成新数
游戏开始后,需要随机生成值为2或4的两个新数字。之后,每上、下、左、右移动其中一次界面中的数字后,如果还有空位,又需要随机生成一个2或4的新数字。

/// <summary>
/// 重载生成新数
/// </summary>
/// <returns></returns>
private bool NewNum()
{
int num = rnd.Next(, ) > ? : ; int nullnum = ;
for (int y = ; y < ; y++)
{
for (int x = ; x < ; x++)
{
if (gridData[y, x] == )
nullnum++;
}
} if (nullnum < )
{
return false;
} int index = rnd.Next(, nullnum);
nullnum = ;
for (int y = ; y < ; y++)
{
for (int x = ; x < ; x++)
{
if (gridData[y, x] == )
{
nullnum++;
if (nullnum != index)
continue; gridData[y, x] = num;
}
}
} return true;
}

先统计出界面中剩余空格数,再从空格数中获取随机数作为新数位置,赋值2或4之一。

  3.3 设置Label板背景色和前景字体大小
根据gridData元素值的高低,显示不同的背景色和字体大小

/// <summary>
/// 根据数值生成方块背景色值
/// </summary>
/// <param name="num"></param>
/// <returns></returns>
private Brush SetBackground(int num)
{
Brush backColor;
switch (num)
{
case :
backColor = new SolidColorBrush(Color.FromRgb(0xee, 0xe4, 0xda));
break;
case :
backColor = new SolidColorBrush(Color.FromRgb(0xec, 0xe0, 0xc8));
break;
case :
backColor = new SolidColorBrush(Color.FromRgb(0xf2, 0xb1, 0x79));
break;
case :
backColor = new SolidColorBrush(Color.FromRgb(0xf5, 0x95, 0x63));
break;
case :
backColor = new SolidColorBrush(Color.FromRgb(0xf5, 0x7c, 0x5f));
break;
case :
backColor = new SolidColorBrush(Color.FromRgb(0xf6, 0x5d, 0x3b));
break;
case :
backColor = new SolidColorBrush(Color.FromRgb(0xed, 0xce, 0x71));
break;
case :
backColor = new SolidColorBrush(Color.FromRgb(0xed, 0xcc, 0x61));
break; case :
backColor = new SolidColorBrush(Color.FromRgb(0xec, 0xc8, 0x50));
break;
case :
backColor = new SolidColorBrush(Color.FromRgb(0xed, 0xc5, 0x3f));
break;
case :
backColor = new SolidColorBrush(Color.FromRgb(0xee, 0xc2, 0x2e));
break;
case :
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 :
case :
case :
iFontsize = ;
break; case :
case :
case :
iFontsize = ;
break; case :
case :
case :
iFontsize = ;
break; case :
case :
case :
iFontsize = ;
break; default:
iFontsize = ;
break;
}
return iFontsize;
}

  3.4 显示游戏区的所有Label控件
如果gridData元素值不为0的话,生成Label控件并添加到游戏板中。

/// <summary>
/// 重新显示所有Label
/// </summary>
private void ShowAllLabel()
{
myCanvas.Children.Clear();
ShowBackRect(); for (int y = ; y < ; y++)
{
for (int x = ; x < ; x++)
{
if (gridData[y, x] != )
{
lblArray[y, x] = new Label();
lblArray[y, x].SetValue(Canvas.LeftProperty, lblPadding * (x + ) + (double)(x * lblWidth));
lblArray[y, x].SetValue(Canvas.TopProperty, lblPadding * (y + ) + (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]);
}
}
}
}

4、初始化游戏数据

/// <summary>
/// 初始化数据
/// </summary>
private void InitData()
{
if (gridData != null) // 初始化主数据数组
gridData = null; gridData = new int[, ]
{
{ , , , },
{ , , , },
{ , , , },
{ , , , }
}; if (lblArray != null) // 初始化显示用Label数组
lblArray = null; lblArray = new Label[, ]; if (myCanvas.Children.Count > )
myCanvas.Children.Clear(); // 清除界面 NewNum(); // 生成两个新数
NewNum(); ShowAllLabel(); // 刷新游戏方块 isStarted = true;
currScore = ; // 初始化当前成绩为0 lblCurrScore.Content = currScore.ToString();// 更新当前成绩显示
}

将InitData()方法添加到BtnNewGame_Click按钮事件方法中。

现在运行游戏,不断点击开始新游戏按钮,会在不同位置生成两个2或4的数字,并显示出来。

5、判断游戏是否结束
判断每一行是否存在空位,如果有则未结束。如果该行已满,则看看是否存在相邻是否有相同的数字,如果有则说明可以合并出新空位,即未结束。
列判断方式相同。

/// <summary>
/// 游戏是否结束
/// </summary>
/// <returns></returns>
private bool isGameOver()
{
for (int row = ; row < ; row++)
{
for (int i = ; i < ; i++)
{
if (gridData[row, i] == ) // 是否有空位
{
return false;
}
}
for (int i = ; i < ; i++)
{
if (gridData[row, i] == gridData[row, i + ])
{
return false;
}
}
} for (int col = ; col < ; col++)
{
for (int i = ; i < ; i++)
{
if (gridData[i, col] == )
{
return false;
}
}
for (int i = ; i < ; i++)
{
if (gridData[i, col] == gridData[i + , col])
{
return false;
}
}
} return true;
} /// <summary>
/// 显示动画结束对话框
/// </summary>
private void ShowGameOver()
{
MessageBox.Show("游戏已经结束。", "Game Over", MessageBoxButton.OK, MessageBoxImage.Information);
isStarted = false;
}

练手WPF(二)——2048游戏的简易实现(上)的更多相关文章

  1. 练手WPF(三)——扫雷小游戏的简易实现(中)

    八.随机布雷 /// <summary> /// 随机布地雷 /// </summary> /// <param name="mineNum"> ...

  2. 练手WPF(一)——模拟时钟与数字时钟的制作(上)

    一.Visual Studio创建一个WPF项目. 简单调整一下MainWindow.xaml文件.主要使用了两个Canvas控件,分别用于显示模拟和数字时钟,命名为AnalogCanvas.digi ...

  3. 练手WPF(二)——2048游戏的简易实现(下)

    接着上一篇继续~~~ 6.动画显示增加分数 /// <summary> /// 动画显示增加得分 /// </summary> /// <param name=" ...

  4. 练手WPF(三)——扫雷小游戏的简易实现(上)

    一.创建项目1.创建WPF项目,设置初始化窗口大小(初级难度):高x宽为430x350.2.添加文件夹Images,并添加相关图片. 3.xaml中引入图片资源. <Window.Resourc ...

  5. 练手WPF(四)——贪吃蛇小游戏的简易实现(上)

    一. 游戏界面首先,按照惯例,编辑MainWindow.xaml,先将游戏界面制作好.非常简单:(1)主游戏区依然使用我们熟悉的Canvas控件,大小为640X480像素,设定每小格子为20px,所以 ...

  6. 练手WPF(三)——扫雷小游戏的简易实现(下)

    十四.响应鼠标点击事件    (1)设置对应坐标位置为相应的前景状态 /// <summary> /// 设置单元格图样 /// </summary> /// <para ...

  7. 练手WPF(四)——贪吃蛇小游戏的简易实现(下)

    八.生成新的单节蛇身我们这里先说说游戏小原理好了,游戏运行后,通过计时器事件不断生成新的单节蛇身类SnakeNode,添加到List中的0位置,原来的蛇头变成了第二节.该节新蛇头的坐标通过蛇头前进方向 ...

  8. 微信小程序框架分析小练手(二)——天气微信小程序制作

    简单的天气微信小程序. 一.首先,打开微信开发者工具,新建一个项目:weather.如下图: 二.进入app.json中,修改导航栏标题为“贵州天气网”. 三.进入index.wxml,进行当天天气情 ...

  9. 练手WPF(一)——模拟时钟与数字时钟的制作(中)

    今天接着制作数字时钟 数字时钟主要用到Path控件,主要用于定义数字笔划的形状. (1)添加一个DigitLine类 数字时钟的数字8由7笔组成,看如下定义的字段字符串数组PathDatas,每个st ...

随机推荐

  1. Linux下部署SSM,通过启动tomcat即可运行

    Linux下部署SSM项目 1. Java环境配置(JRE&JDK) 安装JDK8:sudo yum install java-1.8.0-openjdk 将操作系统配置为默认使用JDK8:s ...

  2. idea从mapper接口跳到xml文件

  3. MacOS~jenkins里解决docker执行权限问题

    一 全局配置项设置 需要添加全局变量项,例如名称docker,路径/usr/local 添加一个jenkinsfile文件,用于运行docker命令 pipeline { agent any tool ...

  4. .Net Core MVC中过滤器简介

    在.Net Framework MVC 中有四种过滤器,授权过滤器(Authorize).Action 过滤器.结果过滤器(Result).异常过滤器(Exception)四种过滤器.在.Net Co ...

  5. iPhone每一代的屏幕尺寸比例是多少?

    参考链接: https://www.jianshu.com/p/8f566ce3bc2c https://zhidao.baidu.com/question/1668756575750668747.h ...

  6. Mac版Sourcetree的安装使用

    本人也在亲测,感觉很有效,和大家分享,参考链接: https://www.jianshu.com/p/b8d0547a8449

  7. Docker启动时提示Get Permission Denied while trying to connect解决方法

    环境描述 vmware15虚拟机安装centos7.4 64位系统,docker版本19.03.2 问题描述 安装完docker后,执行docker相关命令 docker run ubuntu:15. ...

  8. Spring高级注解

    目录: 1.使用限定注解:2.自定义限定注解:3.自定义bean的生命周期: 开发环境:IntelliJ IDEA 2019.2.2Spring Boot版本:2.1.8新建一个名称为demo的Spr ...

  9. C#后台架构师成长之路-高阶知识体系核心

    了解了这些东西,熟悉了运用基本都是高工级别的了,其他修修补补就行了.... 1.三种预定义特性:attributeUsage.Conditional.obsolete,允许创建自定义特性,派生自Sys ...

  10. Pycharm界面的子窗口不见了,怎么办?

    pycharm程序界面一般有很多子窗口,如图1所示. 图1  Pycharm子窗口 如果你发现某些子窗口不见了,图2是最过分的情形,无须担心. 图2  Pycharm界面的子窗口不见了 打开项目视图子 ...