练手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 ...
随机推荐
- Vue父子组件数据双向绑定,子组件可修改props
第一种,子组件通过监听父组件数据,子组件改变数据之后通知给父组件 原文链接:https://blog.csdn.net/m0_37728716/article/details/81776929 父组件 ...
- 2019年全国高校计算机能力挑战赛初赛C语言解答
http://www.ncccu.org.cn 2019年全国高校计算机能力挑战赛分设大数据算法赛,人工智能算法赛,Office高级应用赛,程序设计赛4大赛项 C语言初赛解答 1:编程1 16.现有一 ...
- maven中servlet报错:不识别此servlet问题的解决办法
原因 使用maven集成的tomcat插件的时候,tomcat的lib中,自带servlet-api和jsp. 如果maven中再次导入了这两个jar,会造成jar包冲突现象. 解决办法 我们只是想编 ...
- PHP发送短信
1.要拼接接收的手机号和短信 public function sendcode() { $parpm = input(); $valist = $this->validate($parpm, [ ...
- JAVA笔记 -- 访问权限控制
访问权限控制 没有权限控制的时候,由于所有的接口都是可以访问的.当一个类库部分代码,发现有更好的方法解决的时候,可能其他接口会发生改动.这会导致另一个地方的引用该类库的程序发生崩溃.为了解决这种问题, ...
- 并发编程-多线程,GIL锁
本章内容: 1.什么是GIL 2.GIL带来的问题 3.为什么需要GIL 4.关于GIL的性能讨论 5.自定义的线程互斥锁与GIL的区别 6.线程池与进程池 7.同步异步,阻塞非阻塞 一.什么是GIL ...
- 【Angular】学习笔记-环境部署、项目建立相关
Angular官网>搭建环境 首先要安装Node.js.官网>Download 一直next就好了. 安装node.js的目的是使用npm这些命令啦 然后这里推荐下载使用git SCM 也 ...
- 微信小程序获取input输入框内容
1.wxml <input class="weui-input" type='number' bindinput="emailInput"/> ...
- git upstream
git remote add upstream https://github.com/SchedMD/slurm git fetch upstream git rebase upstream/mast ...
- 【分享】git全套视频教程
1.课件 https://www.cnblogs.com/wfd360/p/10891140.html 2.教程列表 3.教程下载 3.1.直接在线学习 学习地址:https://study.163. ...