• 使用Xamarin开发移动应用示例——数独游戏(二)创建游戏界面


    在本系列第一部分,我们创建了程序框架,现在我们创建游戏的界面,项目代码可以从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:Class="ZL.Shudu.Views.Game">
        <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 。代码随项目进度更新。

  • 相关阅读:
    JAVA学习日报 12/15
    JAVA学习日报 12/14
    JAVA学习日报 12/13
    如何在idea上配置meaven和tomcat!(idea2020)
    关于win10共存多个版本jdk,并如何进行最简单的切换
    Java面试知识点
    一些基本html标签的使用案例
    线性代数复习笔记
    考前加分项
    Javaweb学习12.18
  • 原文地址:https://www.cnblogs.com/zhenl/p/15831901.html
Copyright © 2020-2023  润新知