在本系列第一部分,我们创建了程序框架,现在我们创建游戏的界面,项目代码可以从Github下载:https://github.com/zhenl/ZL.Shudu 。代码随项目进度更新。
首先在Views目录下添加一个内容页面,名称为Game.xaml:
然后,在AppShell.xaml中增加这个页面导航:
<TabBar> <ShellContent Title="游戏" Icon="icon_about.png" Route="Game" ContentTemplate="{DataTemplate local:Game}" /> <ShellContent Title="关于" Icon="icon_about.png" Route="AboutPage" ContentTemplate="{DataTemplate local:AboutPage}" /> <ShellContent Title="Browse" Icon="icon_feed.png" ContentTemplate="{DataTemplate local:ItemsPage}" /> </TabBar>
如果这时运行程序,会发现页面底部增加了一个“游戏”分页,并且初始页面也改为这个页面。现在我们修改这个页面,改造为数独游戏界面。数独的界面是9X9的格子,这些格子组成九个九宫格,每个格子中是1-9的数字,玩家需要将所有的格子填满,并且行、列和九宫格中的数据不能重复。我们可以使用Grid进行布局,构造九行九列,每个格子中放置一个按钮(Button),用户按下按钮,弹出数字输入框,输入数字后,数字显示在按钮上,完成一个输入。
下面是页面的布局XAML:
<?xml version="1.0" encoding="utf-8" ?><ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:> <ContentPage.Content> <StackLayout x:Name="outerStack" Orientation="Vertical"> <!-- Place new controls here --> <Grid x:Name="myGrid" IsVisible="True" > <Grid.ColumnDefinitions> <ColumnDefinition Width="*" /> <ColumnDefinition Width="*" /> <ColumnDefinition Width="*" /> <ColumnDefinition Width="*" /> <ColumnDefinition Width="*" /> <ColumnDefinition Width="*" /> <ColumnDefinition Width="*" /> <ColumnDefinition Width="*" /> <ColumnDefinition Width="*" /> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="25" /> <RowDefinition Height="25" /> <RowDefinition Height="25" /> <RowDefinition Height="25" /> <RowDefinition Height="25" /> <RowDefinition Height="25" /> <RowDefinition Height="25" /> <RowDefinition Height="25" /> <RowDefinition Height="25" /> <RowDefinition Height="40" x:Name="rowButton" /> <RowDefinition Height="40" x:Name="rowResult" /> </Grid.RowDefinitions> <Label x:Name="lbFinish" Text="完成" IsVisible="false" Grid.Row="10" Grid.Column="0" Grid.ColumnSpan="2" /> <Label x:Name="lbTime" Grid.Row="10" Grid.Column="3" Grid.ColumnSpan="2" Text="" IsVisible="False"></Label> <Label x:Name="lbMessage" Grid.Row="10" Grid.Column="5" Grid.ColumnSpan="4" Text="" IsVisible="False"></Label> </Grid> <Grid x:Name="grdNumber" IsVisible="false"> <Grid.ColumnDefinitions> <ColumnDefinition Width="*" /> <ColumnDefinition Width="*" /> <ColumnDefinition Width="*" /> <ColumnDefinition Width="*" /> <ColumnDefinition Width="*" /> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="*" /> <RowDefinition Height="*" /> </Grid.RowDefinitions> </Grid> </StackLayout> </ContentPage.Content></ContentPage>
在页面初始化时,生成数字按钮、游戏界面中每个单元格按钮,并根据初始数据确定按钮的文本和使能。
public Game() { try { InitializeComponent(); SetNumButtons(); SetLayout(); SetNewGame(); } catch (Exception ex) { lbMessage.IsVisible = true; rowResult.Height = 40; lbMessage.Text = ex.Message; //throw; } }
设置数字按钮的函数代码如下:
private void SetNumButtons() { var num = 1; for (var i = 0; i < 2; i++) { for (var j = 0; j < 5; j++) { var btn = new Button(); if (num == 10) { btn.Text = "清除"; btn.Clicked += btn_Clear_Clicked; btn.FontSize = 15; } else { btn.Text = num.ToString(); btn.Clicked += btn_Num_Clicked; btn.FontSize = 16; } btn.Padding = 0; grdNumber.Children.Add(btn, j, i); numbuttons[i, j] = btn; num++; } } }
设置数独界面按钮的代码如下:
private void SetLayout() { for (var i = 0; i < 9; i++) { for (var j = 0; j < 9; j++) { int m = i / 3; int n = j / 3; var btn = new Button(); var c = new Color(0.9, 0.9, 0.9); if ((m + n) % 2 == 0) { c = new Color(0.5,0.5, 0.5); } btn.BackgroundColor = c; btn.Padding = 0; btn.Margin = 0; btn.FontSize = 20; myGrid.Children.Add(btn, i, j); btn.Clicked += Btn_Clicked; buttons[i, j] = btn; } } }
根据初始化数据,设置按钮状态的代码如下:
private void SetGame(int[,] inp) { for (var i = 0; i < 9; i++) { for (var j = 0; j < 9; j++) { chess[i, j] = inp[i, j]; } } for (var i = 0; i < 9; i++) { for (var j = 0; j < 9; j++) { var btn = buttons[i, j]; if (chess[i, j] > 0) { btn.Text = chess[i, j].ToString(); btn.IsEnabled = false; } else { btn.Text = ""; btn.IsEnabled = true; } } } this.lbFinish.IsVisible = false; this.lbTime.IsVisible = false; this.lbMessage.IsVisible = false; this.rowResult.Height = 1; lbTime.Text = ""; lbMessage.Text = ""; }
按钮的响应事件如下:
private void Btn_Clicked(object sender, EventArgs e) { currentButton = sender as Button; rowResult.Height = 1; rowButton.Height = 1; grdNumber.IsVisible = true; } private void btn_Clear_Clicked(object sender, EventArgs e) { if (currentButton == null) return; currentButton.Text = ""; grdNumber.IsVisible = false; myGrid.IsVisible = true; rowResult.Height = 40; rowButton.Height = 40; } private void btn_Num_Clicked(object sender, EventArgs e) { currentNumBtn = sender as Button; int x = -1, y = -1; for (var i = 0; i < 9; i++) { for (var j = 0; j < 9; j++) { if (buttons[i, j] == currentButton) { x = i; y = j; break; } } } var num = int.Parse(currentNumBtn.Text); if (!checkval(x, y, num)) { return; } currentButton.Text = currentNumBtn.Text; myGrid.IsVisible = true; grdNumber.IsVisible = false; rowResult.Height = 40; rowButton.Height = 40; if (IsFinish()) { lbFinish.IsVisible = true; rowResult.Height = 40; } }
判断输入状态和游戏结束的函数如下:
private bool checkval(int x, int y, int num) { for (var i = 0; i < 9; i++) { var buttonnum = string.IsNullOrEmpty(buttons[x, i].Text) ? 0 : int.Parse(buttons[x, i].Text); if (i != y && buttonnum == num) return false; } for (var i = 0; i < 9; i++) { var buttonnum = string.IsNullOrEmpty(buttons[i, y].Text) ? 0 : int.Parse(buttons[i, y].Text); if (i != x && buttonnum == num) return false; } int m = x / 3; int n = y / 3; for (int i = m * 3; i < (m + 1) * 3; i++) { for (int j = n * 3; j < (n + 1) * 3; j++) { var buttonnum = string.IsNullOrEmpty(buttons[i, j].Text) ? 0 : int.Parse(buttons[i, j].Text); if (i != x && j != y && buttonnum == num) return false; } } return true; } private bool IsFinish() { for (var i = 0; i < 9; i++) { for (var j = 0; j < 9; j++) { if (string.IsNullOrEmpty(buttons[i, j].Text)) return false; } } return true; } }
运行效果如下:
现在基本界面已经搭建完成,后续需要增加允许回退、历史记录、退出保存以及自动完成等功能。项目代码可以从Github下载:https://github.com/zhenl/ZL.Shudu 。代码随项目进度更新。
本文来自博客园,作者:寻找无名的特质,转载请注明原文链接:https://www.cnblogs.com/zhenl/p/15831901.html