练手WPF(二)——2048游戏的简易实现(上)
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游戏的简易实现(上)的更多相关文章
- 练手WPF(三)——扫雷小游戏的简易实现(中)
八.随机布雷 /// <summary> /// 随机布地雷 /// </summary> /// <param name="mineNum"> ...
- 练手WPF(一)——模拟时钟与数字时钟的制作(上)
一.Visual Studio创建一个WPF项目. 简单调整一下MainWindow.xaml文件.主要使用了两个Canvas控件,分别用于显示模拟和数字时钟,命名为AnalogCanvas.digi ...
- 练手WPF(二)——2048游戏的简易实现(下)
接着上一篇继续~~~ 6.动画显示增加分数 /// <summary> /// 动画显示增加得分 /// </summary> /// <param name=" ...
- 练手WPF(三)——扫雷小游戏的简易实现(上)
一.创建项目1.创建WPF项目,设置初始化窗口大小(初级难度):高x宽为430x350.2.添加文件夹Images,并添加相关图片. 3.xaml中引入图片资源. <Window.Resourc ...
- 练手WPF(四)——贪吃蛇小游戏的简易实现(上)
一. 游戏界面首先,按照惯例,编辑MainWindow.xaml,先将游戏界面制作好.非常简单:(1)主游戏区依然使用我们熟悉的Canvas控件,大小为640X480像素,设定每小格子为20px,所以 ...
- 练手WPF(三)——扫雷小游戏的简易实现(下)
十四.响应鼠标点击事件 (1)设置对应坐标位置为相应的前景状态 /// <summary> /// 设置单元格图样 /// </summary> /// <para ...
- 练手WPF(四)——贪吃蛇小游戏的简易实现(下)
八.生成新的单节蛇身我们这里先说说游戏小原理好了,游戏运行后,通过计时器事件不断生成新的单节蛇身类SnakeNode,添加到List中的0位置,原来的蛇头变成了第二节.该节新蛇头的坐标通过蛇头前进方向 ...
- 微信小程序框架分析小练手(二)——天气微信小程序制作
简单的天气微信小程序. 一.首先,打开微信开发者工具,新建一个项目:weather.如下图: 二.进入app.json中,修改导航栏标题为“贵州天气网”. 三.进入index.wxml,进行当天天气情 ...
- 练手WPF(一)——模拟时钟与数字时钟的制作(中)
今天接着制作数字时钟 数字时钟主要用到Path控件,主要用于定义数字笔划的形状. (1)添加一个DigitLine类 数字时钟的数字8由7笔组成,看如下定义的字段字符串数组PathDatas,每个st ...
随机推荐
- [译]Vulkan教程(01)入门
[译]Vulkan教程(01)入门 接下来我将翻译(https://vulkan-tutorial.com)上的Vulkan教程.这可能是我学习Vulkan的最好方式,但不是最理想的方式. 我会用“d ...
- python 学习 (1-3)
流程控制if语句 语法种类: 第⼀种语法: if 条件: #引号是将条件与结果分开. 结果1. # 四个空格,或者⼀个tab键,这个是告诉程序满⾜这个条件的 结果2. 如果条件是真(True) ...
- Hyperledger Fabric相关文件解析
1相关文件说明 这一部分涉及相关配置文件的解析, 网络的启动涉及到多个文件,本文按以下顺序进行分析: . ├── base │ ├── docker-compose-base.yaml #1 │ ...
- 关于hover与after,before已及first-letter,first-line的联用
0920自我总结 关于hover与after,before已及first-letter,first-line的联用 一.写法 元素:hover::after{样式} 元素:hover::before{ ...
- HTML元素分类 块级元素 内联元素 块级内联元素
概述 HTML中存在许多元素,如<h1>,<p>,<a>,<block>,<image>,这些元素可分为三类,依次是块级元素,内联元素,块级 ...
- 微信小程序——仿jqueryValidate表单验证插件WxValidate的二次封装(一)
在做web开发时,表单验证插件我们前端用的是jqueryValidate,由于个人主要精力是在后台JAVA开发上,为了让插件与后台更好的结合和使用,通过JAVA的自定义组件将表单全部重新写了一边,同时 ...
- P1005 Spell It Right
# P1005 Spell It Right 原题 Given a non-negative integer N, your task is to compute the sum of all the ...
- 转战物联网·基础篇09-选择MQTT协议还是CoAP协议
前面章节介绍过,MQTT协议和CoAP协议都是物联网中比较流行的协议,都对传输量做了很大的精简,传输开销小,以适应物理网的网络环境. XMPP协议也有人说是适合物联网通信的,但它是基于XML, ...
- activeMQ - how to install and run
apache activeMQ how to install and run https://www.cnblogs.com/lyxy/p/5969116.html
- ActiveMQ持久化到MySQL以及使用SSL协议通讯
最近公司事情稍微少了点,研究下怎么优化几个系统的交互,因为我们目前使用的是长链接的同步接口,就考虑用下MQ来处理下.由于公司对安全有要求且和CA业务有关,则使用了SSL协议.此文使用的是Activem ...