奇怪的扫雷炸弹数字行为

时间:2017-02-12 19:14:30

标签: c# uwp-xaml

所以我为UWP制作扫雷克隆。而且,当然,我有数字说明有多少地雷。所以这就是问题(你可以在图片上看到它):

Weird behaviour

左上角,上方,右上角和左上角只是缺少数字。但是,当我第二次点击时(我没有实施预防,第二次点击打开的字段),他们添加了1个(因为我重新启动应用程序以获取另一个屏幕截图,因此放置的地雷不同):

top-left, top, top-right and left fields around the bomb have 1, others have 2

我试图通过添加2而不是1来解决这个问题,但问题仍然存在,但更加奇怪。

首先点击:

still missing

第二次点击:

all fields around the mines have 2

所以,最后这里去了codez:

using System;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;

// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238

namespace Mynesweeper
{
    public class Cell
    {
        public enum CellType
        {
            Safe = 0,
            Bomb = 1,
            Flag = 2,
            FirstClick = 3
        }

        public CellType cellState;
        public bool covered = true;
    }
    /// <summary>
    /// An empty page that can be used on its own or navigated to within a Frame.
    /// </summary>
    public sealed partial class MineField : Page
    {

        Cell[,] cells = new Cell[0, 0];
        bool isGenerated = false;
        Button[,] fieldBtns = new Button[0, 0];
        int maxMines = 0;
        int[,] nearbyBombs = new int[0, 0];

        public MineField()
        {
            this.InitializeComponent();
        }

        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            string param = e.Parameter.ToString();
            if (param == "tutorial")
            {
                MinesAmount.Text = "4";
                GenerateLevel(25, 25, 4);
            }
            else
            {
                TextBlock errTxtBlck = new TextBlock() { Name = "ErrorTextBlock", Text = "Error: no or incorrect parameter was specified when navigating to MineField.xaml\r\n\r\nIf you're the player and've downloaded the game through Windows Store, then let me know about this error by contacting me at artyomisflash@mail.ru. If you're not a player then maybe you're me and you have to fix this error.", HorizontalAlignment = Windows.UI.Xaml.HorizontalAlignment.Stretch, Margin = new Windows.UI.Xaml.Thickness(16, 0, 16, 0), TextWrapping = Windows.UI.Xaml.TextWrapping.Wrap, VerticalAlignment = Windows.UI.Xaml.VerticalAlignment.Center, FontSize = 24, TextAlignment = Windows.UI.Xaml.TextAlignment.Center };
                MainGrid.Children.Add(errTxtBlck);
                SmileyFace.Text = "...";
            }
        }

        public static int Clamp(int val, int min, int max)
        {
            if (val < min)
            {
                return min;
            }
            else if (val > max)
            {
                return max;
            }
            else
            {
                return val;
            }
        }

        void GenerateLevel(int x, int y, int mines)
        {
            cells = new Cell[x, y];
            StackPanel[] fieldRows = new StackPanel[y];
            fieldBtns = new Button[x, y];
            maxMines = mines;
            nearbyBombs = new int[x, y];
            for (int i = 0; i < y; i++)
            {
                fieldRows[i] = new StackPanel() { Name = "MineFieldPanelRow" + i, Orientation = Orientation.Horizontal };
                MineFieldPanelRows.Children.Add(fieldRows[i]);
                for (int j = 0; j < x; j++)
                {
                    fieldBtns[j, i] = new Button() { Name = "MineFieldButton" + j + "_" + i, Width = 64, Height = 64, Margin = new Thickness(4), Padding = Margin = new Thickness(0) };
                    fieldBtns[j, i].Click += MineFieldButtonClick;
                    fieldBtns[j, i].Content = new FontIcon() { Glyph = "\uE890", FontSize = 32 };
                    fieldRows[i].Children.Add(fieldBtns[j, i]);
                    cells[j, i] = new Cell()
                    {
                        covered = true
                    };
                    nearbyBombs[j, i] = 0;
                }
            }
        }

        void PlaceMines()
        {
            Random rnd = new Random();
            for (int i = 0; i < maxMines; i++)
            {
                int x = rnd.Next(0, cells.GetLength(0));
                int y = rnd.Next(0, cells.GetLength(1));
                while (cells[x, y].cellState == Cell.CellType.Bomb || cells[x, y].cellState == Cell.CellType.FirstClick)
                {
                    x = rnd.Next(0, cells.GetLength(0));
                    y = rnd.Next(0, cells.GetLength(1));
                }
                cells[x, y].cellState = Cell.CellType.Bomb;
            }
        }

        private void MineFieldButtonClick(object sender, RoutedEventArgs e)
        {
            if (!isGenerated)
            {
                for (int i = 0; i < fieldBtns.GetLength(1); i++)
                {
                    for (int j = 0; j < fieldBtns.GetLength(0); j++)
                    {
                        if (fieldBtns[j, i] == sender)
                        {
                            cells[j, i].cellState = Cell.CellType.FirstClick;
                            break;
                        }
                    }
                }
                PlaceMines();
                isGenerated = true;
            }
            for (int i = 0; i < cells.GetLength(1); i++)
            {
                for (int j = 0; j < cells.GetLength(0); j++)
                {
                    if (cells[j, i].cellState == Cell.CellType.Bomb)
                    {
                        fieldBtns[j, i].Content = new FontIcon() { Glyph = "\uE783", FontSize = 32 };
                        nearbyBombs[j, i] = -1;
                        if (i - 1 > -1)
                        {
                            if (j - 1 > -1)
                            {
                                nearbyBombs[j - 1, i - 1]+=2;
                            }
                            nearbyBombs[j, i - 1]+=2;
                            if (j + 1 <= nearbyBombs.GetLength(0) - 1)
                            {
                                nearbyBombs[j + 1, i - 1]+=2;
                            }
                        }
                        if (j - 1 > -1)
                        {
                            nearbyBombs[j - 1, i]+=2;
                        }
                        if (j + 1 <= nearbyBombs.GetLength(0) - 1)
                        { 
                            nearbyBombs[j + 1, i]++;
                        }
                        if (i + 1 <= nearbyBombs.GetLength(1) - 1)
                        {
                            if (j - 1 >= 0)
                            {
                                nearbyBombs[j - 1, i + 1]++;
                            }
                            nearbyBombs[j, i + 1]++;
                            if (j + 1 <= nearbyBombs.GetLength(0) - 1)
                            {
                                nearbyBombs[j + 1, i + 1]++;
                            }
                        }
                    }
                    else if (nearbyBombs[j, i] == 0)
                    {
                        fieldBtns[j, i].Content = null;
                    }
                    else
                    {
                        int bombsNearby = nearbyBombs[j, i];
                        fieldBtns[j, i].Content = new TextBlock() { Text = bombsNearby.ToString(), FontSize = 32 };
                    }
                }
            }
        }
    }
}

XAML部分是:

<Page
    x:Class="Mynesweeper.MineField"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:Mynesweeper"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

    <Grid x:Name="MainGrid">
        <Grid.Transitions>
            <TransitionCollection>
                <EntranceThemeTransition IsStaggeringEnabled="True"/>
            </TransitionCollection>
        </Grid.Transitions>
        <StackPanel x:Name="Stats" Margin="16,16,16,0" Orientation="Horizontal" VerticalAlignment="Top" HorizontalAlignment="Center" RenderTransformOrigin="0.5,0.5">
            <TextBlock x:Name="TimeAmount" TextWrapping="Wrap" Text="0" VerticalAlignment="Center" FontSize="32" Width="64" TextAlignment="Right" Margin="0,0,16,0"/>
            <Button x:Name="Smiley" Padding="0" Width="64" Height="64" HorizontalAlignment="Center" VerticalAlignment="Stretch" FontSize="32" d:LayoutOverrides="LeftMargin, RightMargin, LeftPosition, RightPosition">
                <TextBlock x:Name="SmileyFace" Text=":)" TextLineBounds="Tight" TextAlignment="Center"/>
            </Button>
            <TextBlock x:Name="MinesAmount" TextWrapping="Wrap" Text="0" VerticalAlignment="Center" FontSize="32" Width="64" Margin="16,0,0,0"/>
        </StackPanel>
        <StackPanel x:Name="MineFieldPanelRows" Margin="0,16,0,0" VerticalAlignment="Center" HorizontalAlignment="Center" RenderTransformOrigin="0.5,0.5">
            <StackPanel.RenderTransform>
                <CompositeTransform ScaleX="0.25" ScaleY="0.25"/>
            </StackPanel.RenderTransform> <!-- specially downscaled to fit the whole field on the screen -->
        </StackPanel>

    </Grid>
</Page>

我真的不知道为什么会出现这个问题。也许我在某处弄错了?请帮忙!

2 个答案:

答案 0 :(得分:1)

你的问题是这句话:

else if (nearbyBombs[j, i] == 0)

当你仍在穿越你的网格并设置炸弹数时,你正在检查一个单元的炸弹数是否为零,所以在进行这项检查时,并不是所有的单元计算都已执行。 / p>

解决方案是首先进行一次通过来计算炸弹数量,一旦完成,然后再做一次传递来创建按钮并在其中显示炸弹数量。

答案 1 :(得分:0)

以下代码:

                    if (j - 1 > -1)
                    {
                        nearbyBombs[j - 1, i]+=2;
                    }

位于检查以确保i > 0的任何块之外。因此,如果你在i = 0时遇到过我的代码,那么你的代码将会爆炸。这让我相信你的错综复杂的if陈述是完全错误的,而且它们太错综复杂,无法试图找出准确的你弄乱你的计数的地方。就像在大海捞针一样,从我已经发现另一个错误的那一刻开始就不值得。

让我建议一个不同的方法:

  1. 当您的意思是xy时,请使用heightwidth退出,当使用ij时,请务必退出你的意思是xy。笛卡尔坐标中坐标名称的惯例是&#39; x&#39;对于横轴和&#39; y&#39;对于自17世纪中期以来的纵轴(Wikipedia),您不需要在2017年发明新的公约。

  2. 有人告诉你,即使你有一个由单个语句组成的块,也应该总是使用大括号。如果您认为这是明智的建议,请继续使用花括号敲打自己,但至少在堆栈溢出中避免使用大括号垃圾邮件,其中简洁性非常重要。

  3. 在您的代码工作之前停止使用Random()。在特定的一组坐标上放置一定数量的炸弹,确保你的东西在引入随机性之前有效。

  4. 退出嵌套if语句的复杂不可读的级联锯齿形意大利面,并做一些更简单的事情。

  5. 像这样:

    void updateBombCountsAroundBomb( int bombY, int bombX, int height, int width )
    {
        for( y = bombY - 1;  y <= bombY + 1;  y++ )
            for( x = bombX - 1;  x <= bombX + 1;  x++ )
                if( y != bombY && x != bombX )
                    if( y >= 0 && y < height && x >= 0 && x < width )
                         nearbyBombs[y, x]++;
    }
    

    一旦你有了这个工作,你可以尝试优化它,如果你想这样做,知道如果你不小心打破它,你总是可以恢复到以前的版本工作。 (测试规则。)