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. MySQL常用SQL语句总结

    1.with rollup 可以实现在分组统计数据基础上再进行相同的统计 SELECT name, SUM(score) as score_count FROM  score GROUP BY nam ...

  2. Sql 中常用时间处理函数

    1.Sql 中常用时间处理函数  GETDATE()  返回当前的日期和时间 DATEPART()  返回日期/时间的单独部分 DATEADD()   返回日期中添加或减去指定的时间间隔 DATEDI ...

  3. linux命令-开关机命令与系统痕迹命令

    一.关机和重启命令 1.sync 命令 命令名称:sync 英文原意:flush file system buffers 所在路径:/bin/sync 执行权限:所有用户 功能描述:刷新文件系统缓冲区 ...

  4. NIO零拷贝的深入分析

    深入分析通过Socket进行数据文件传递中的传统IO的弊端以及NIO的零拷贝实现原理,及用户空间和内核空间的切换方式 传统的IO流程 在这个过程中: 数据从磁盘拷贝进内核空间缓冲区 从内核空间缓冲区拷 ...

  5. Elasticsearch 6.x版本全文检索学习之聚合分析入门

    1.什么是聚合分析? 答:聚合分析,英文为Aggregation,是es除搜索功能外提供的针对es数据做统计分析的功能.特点如下所示: a.功能丰富,提供Bucket.Metric.Pipeline等 ...

  6. js实现post方式的异步请求

    <%@ page contentType="text/html;charset=UTF-8" language="java" %><html& ...

  7. 松软科技带你学前端:JavaScript 使用

    <script> 标签 在 HTML 中,JavaScript 代码必须位于 <script> 与 </script> 标签之间. 实例 <script> ...

  8. iOSMultipeerConnectivity使用

    MultipeerConnectivity是iOS7推出的多点连接框架,多用于文件传输,类似于iOS设备的airTrop隔空投放,在没有联网的情况下也能聊天传文件. 使用方法,一个设备作为广播开放Pe ...

  9. react-native自定义Modal模态框|仿ios、微信弹窗RN版

    前序 纵观每个优质项目,无论web端还是native原生应用开发,弹窗都是不可忽视的一环,能很大程度上直接决定用户体验.如:微信.支付宝.ios都有很成熟的一套弹窗UI展示场景. 最近一直沉迷在rea ...

  10. Spring Boot 2 构建可部署的war包

    默认情况下Spring Boot使用了内嵌的Tomcat服务器,项目最终被打成jar包运行,每个jar包可以被看作一个独立的Web服务器.传统的Web开发,一般会将Web应用打成一个war包,然后将其 ...