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的Lebel控件(其初始透明度为0,即完全透明),用于增加成绩时的动画效果,其中定义了命名为tt的TranslateTransform变换效果。
(3)游戏主区控件为Canvas,命名为myCanvas。
(4)其他可以根据自己的喜好进行调整。
2、定义几个字段变量
毕竟是小游戏,直接从MainWindow.xaml.cs开始下手了。
int lblWidth = 105; // 方块大小
int lblPadding = 15; // 方块间隙
int[,] gridData = null; // 游戏主数据数组
Label[,] lblArray = null; // 用于显示成方块的Label数组
int currScore = 0; // 当前成绩
bool isStarted = false; // 游戏是否已开始
Random rnd = new Random(); // 随机数
3、几个开始需要调用的方法
3.1 游戏开始数字板
界面中的16个游戏数字为0时,只显示空的16块小板面,其颜色比背景色稍浅。
/// <summary>
/// 显示背景矩形块
/// </summary>
private void ShowBackRect()
{
for (int y = 0; y < 4; y++)
{
for (int x = 0; x < 4; x++)
{
Rectangle rect = new Rectangle();
rect.SetValue(Canvas.LeftProperty, (double)((x + 1) * lblPadding + x * lblWidth));
rect.SetValue(Canvas.TopProperty, (double)((y + 1) * lblPadding + y * lblWidth));
myCanvas.Children.Add(rect);
}
}
}
3.2 生成新数
游戏开始后,需要随机生成值为2或4的两个新数字。之后,每上、下、左、右移动其中一次界面中的数字后,如果还有空位,又需要随机生成一个2或4的新数字。
/// <summary>
/// 重载生成新数
/// </summary>
/// <returns></returns>
private bool NewNum()
{
int num = rnd.Next(0, 9) > 2 ? 2 : 4;
int nullnum = 0;
for (int y = 0; y < 4; y++)
{
for (int x = 0; x < 4; x++)
{
if (gridData[y, x] == 0)
nullnum++;
}
}
if (nullnum < 1)
{
return false;
}
int index = rnd.Next(1, nullnum);
nullnum = 0;
for (int y = 0; y < 4; y++)
{
for (int x = 0; x < 4; x++)
{
if (gridData[y, x] == 0)
{
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 2:
backColor = new SolidColorBrush(Color.FromRgb(0xee, 0xe4, 0xda));
break;
case 4:
backColor = new SolidColorBrush(Color.FromRgb(0xec, 0xe0, 0xc8));
break;
case 8:
backColor = new SolidColorBrush(Color.FromRgb(0xf2, 0xb1, 0x79));
break;
case 16:
backColor = new SolidColorBrush(Color.FromRgb(0xf5, 0x95, 0x63));
break;
case 32:
backColor = new SolidColorBrush(Color.FromRgb(0xf5, 0x7c, 0x5f));
break;
case 64:
backColor = new SolidColorBrush(Color.FromRgb(0xf6, 0x5d, 0x3b));
break;
case 128:
backColor = new SolidColorBrush(Color.FromRgb(0xed, 0xce, 0x71));
break;
case 256:
backColor = new SolidColorBrush(Color.FromRgb(0xed, 0xcc, 0x61));
break;
case 512:
backColor = new SolidColorBrush(Color.FromRgb(0xec, 0xc8, 0x50));
break;
case 1024:
backColor = new SolidColorBrush(Color.FromRgb(0xed, 0xc5, 0x3f));
break;
case 2048:
backColor = new SolidColorBrush(Color.FromRgb(0xee, 0xc2, 0x2e));
break;
case 4096:
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 2:
case 4:
case 8:
iFontsize = 55;
break;
case 16:
case 32:
case 64:
iFontsize = 50;
break;
case 128:
case 256:
case 512:
iFontsize = 40;
break;
case 1024:
case 2048:
case 4096:
iFontsize = 33;
break;
default:
iFontsize = 30;
break;
}
return iFontsize;
}
3.4 显示游戏区的所有Label控件
如果gridData元素值不为0的话,生成Label控件并添加到游戏板中。
/// <summary>
/// 重新显示所有Label
/// </summary>
private void ShowAllLabel()
{
myCanvas.Children.Clear();
ShowBackRect();
for (int y = 0; y < 4; y++)
{
for (int x = 0; x < 4; x++)
{
if (gridData[y, x] != 0)
{
lblArray[y, x] = new Label();
lblArray[y, x].SetValue(Canvas.LeftProperty, lblPadding * (x + 1) + (double)(x * lblWidth));
lblArray[y, x].SetValue(Canvas.TopProperty, lblPadding * (y + 1) + (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[4, 4]
{
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 }
};
if (lblArray != null) // 初始化显示用Label数组
lblArray = null;
lblArray = new Label[4, 4];
if (myCanvas.Children.Count > 0)
myCanvas.Children.Clear(); // 清除界面
NewNum(); // 生成两个新数
NewNum();
ShowAllLabel(); // 刷新游戏方块
isStarted = true;
currScore = 0; // 初始化当前成绩为0
lblCurrScore.Content = currScore.ToString();// 更新当前成绩显示
}
将InitData()方法添加到BtnNewGame_Click按钮事件方法中。
现在运行游戏,不断点击开始新游戏按钮,会在不同位置生成两个2或4的数字,并显示出来。
5、判断游戏是否结束
判断每一行是否存在空位,如果有则未结束。如果该行已满,则看看是否存在相邻是否有相同的数字,如果有则说明可以合并出新空位,即未结束。
列判断方式相同。
/// <summary>
/// 游戏是否结束
/// </summary>
/// <returns></returns>
private bool isGameOver()
{
for (int row = 0; row < 4; row++)
{
for (int i = 0; i < 4; i++)
{
if (gridData[row, i] == 0) // 是否有空位
{
return false;
}
}
for (int i = 0; i < 3; i++)
{
if (gridData[row, i] == gridData[row, i + 1])
{
return false;
}
}
}
for (int col = 0; col < 4; col++)
{
for (int i = 0; i < 4; i++)
{
if (gridData[i, col] == 0)
{
return false;
}
}
for (int i = 0; i < 3; i++)
{
if (gridData[i, col] == gridData[i + 1, col])
{
return false;
}
}
}
return true;
}
/// <summary>
/// 显示动画结束对话框
/// </summary>
private void ShowGameOver()
{
MessageBox.Show("游戏已经结束。", "Game Over", MessageBoxButton.OK, MessageBoxImage.Information);
isStarted = false;
}
来源:oschina
链接:https://my.oschina.net/u/4269725/blog/3521684