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. [专题总结]初探插头dp

    彻彻底底写到自闭的一个专题. 就是大型分类讨论,压行+宏定义很有优势. 常用滚动数组+哈希表+位运算.当然还有轮廓线. Formula 1: 经过所有格子的哈密顿回路数. 每个非障碍点必须有且仅有2个 ...

  2. C语言程序设计100例之(23):数列求和

    例23  数列求和 问题描述 已知某数列前两项为2和3,其后继项根据前面最后两项的乘积,按下列规则生成: ① 若乘积为一位数,则该乘积即为数列的后继项: ② 若乘积为二位数,则该乘积的十位上的数字和个 ...

  3. Java:程序不过是几行代码的集合

    程序不过是几行代码的集合.就像下面这样: public class Test { public static void main(String[] args) { System.out.println ...

  4. Spring 框架基础(02):Bean的生命周期,作用域,装配总结

    本文源码:GitHub·点这里 || GitEE·点这里 一.装配方式 Bean的概念:Spring框架管理的应用程序中,由Spring容器负责创建,装配,设置属性,进而管理整个生命周期的对象,称为B ...

  5. Redis实战(一)Redis简介及环境安装(Windows)

    提到Redis,大家肯定都听过,并且应该都在项目中或多或少的使用过,也许你觉得Redis用起来挺简单的呀,但如果有人问你下面的几个问题(比如同事或者面试官),你能回答的上来吗? 什么是Redis? R ...

  6. JavaScript的概念,引入,基本数据类型

    08.05自我总结 JavaScript 一.概念 JavaScript(下文我们会用简称JS来代替)是脚本编程语言,JS语言开发的文件是以.js为后缀,通过在html文件中引入该js文件来控制htm ...

  7. 添加商品到购物车add_to_cart.php(学生笔记)

    <?php session_start();//启动session $goods_id = $_POST['goods_id'];//获取商品id $number = $_POST['num'] ...

  8. 设计院老师良心汇总:值得牢记的15个CAD基础技巧,能帮大忙

    哈喽!你们的CAD魔鬼(老师)来喽! 良心CAD技巧汇总,设计院师傅精心汇总,值得你牢记的15个CAD基础技巧,满满的都是干货,日常最常见的问题以及解决方法这里都汇总给你,给你高效的绘图体验,关键时刻 ...

  9. PHP http_response_code 网络函数

    定义和用法 http_response_code - 获取/设置响应的 HTTP 状态码 版本支持 PHP4 PHP5 PHP7 不支持 支持  支持 语法 http_response_code ([ ...

  10. Web 安全总结

    同源策略 如果两个 URL 的协议.域名和端口都相同,我们就称这两个 URL 同源. 同源策略限制了来自不同源的 JavaScript 脚本对当前 DOM 对象读和写的操作. 同源策略限制了不同源的站 ...