1

ブロックを順番にスタックに配置するために、最終的に各ノード (要素 0 ~ 8 の int[]) をパスに格納する 8 パズル ソルバーを実行しています。int[,] を表示する WPF GUI があります。

foreach (var node in stack)
        {
            int[,] unstrung = node.unstringNode(node); // turns node of int[] into board of  int[,]
            blocks.setBoard(unstrung); // sets the board to pass in to the GUI
            DrawBoard(); // Takes the board (int[,]) and sets the squares on the GUI to match it.
            Thread.Sleep(500);
        }

GUI に最初のボードが表示され、[解決] をクリックすると、最終的な (順序どおりの) ボードが正しく表示されます。私がやりたいことは、ボード上の各ノードをしばらく表示し、最終的に順序どおりのボードに到達することです。Thread.Sleep を使用すると、GUI は最終ノードを表示する前に設定された時間だけ一時停止します。このコードが各ノードで 500ms ごとにボードを表示しない理由について何か考えはありますか?

参考までに、ノードの Console.Write からの出力例を次に示します。
4,2,3,6,1,0,7,5,8
4,2,0,6,1,3,7,5,8
4 ,0,2,6,1,3,7,5,8
4,1,2,6,0,3,7,5,8
4,1,2,0,6,3,7,5,8
0,1,2,4,6,3,7,5,8
1,0,2,4,6,3,7,5,8
1,2,0,4,6,3,7,5, 8
1,2,3,4,6,0,7,5,8
1,2,3,4,0,6,7,5,8
1,2,3,4,5,6,7,0 ,8
1,2,3,4,5,6,7,8,0

4

1 に答える 1

1

編集:

私の元の回答は、 a のThread代わりに aを使用したことで反対票を投じられたためTimer、タイマーを使用した例を次に示します。

スレッドを使用するためのコードが短かったので、すぐに解決策を示したかったのです。

また、タイマーの代わりにスレッドを使用することで、パラメーターを別の方法で渡したり、ループを再構築したりする必要がなくなりました。

これが、正しい方法が 1 つしかないと単純に主張するのではなく、別の解決策の長所と短所を議論することをお勧めする理由です。

関数を使用しtimer_Tickて位置を更新します。

パラメータを別の方法で渡し、ループを再構築する必要があるため、元のコードが複雑になることに気付くかもしれません。

public partial class Form1 : Form
{
    private Point pos = new Point(1,1);
    private float[] vel = new float[2];
    private Size bounds = new Size(20,20);
    private Timer ticky = new Timer();      //System.Windows.Forms.Timer
    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        ticky.Interval = 20;
        ticky.Tick += ticky_Tick;
        vel[0] = 4; vel[1] = 0;
        ticky.Start();
    }
    void ticky_Tick(object sender, EventArgs e)
    {
        updatePosition();
        //This tells our form to repaint itself (and call the OnPaint method)
        this.Invalidate();
    }
    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);
        e.Graphics.FillEllipse(new SolidBrush(Color.LightBlue), new Rectangle(pos, bounds));
    }
    private void updatePosition()
    {
        pos = new Point(pos.X + (int)vel[0], pos.Y + (int)vel[1]);
        vel[1] += .5f; //Apply some gravity
        if (pos.X + bounds.Width > this.ClientSize.Width)
        {
            vel[0] *= -1;
            pos.X = this.ClientSize.Width - bounds.Width;
        }
        else if (pos.X < 0)
        {
            vel[0] *= -1;
            pos.X = 0;
        }
        if (pos.Y + bounds.Height > this.ClientSize.Height)
        {
            vel[1] *= -.90f; //Lose some velocity when bouncing off the ground
            pos.Y = this.ClientSize.Height - bounds.Height;
        }
        else if (pos.Y < 0)
        {
            vel[1] *= -1;
            pos.Y = 0;
        }
    }
}

結果:

結果

タイマーを使用して、あらゆる種類の遅延フォーム描画を行うことができます。

もっと

元の解決策:

//Create a separate thread so that the GUI thread doesn't sleep through updates:
using System.Threading;

new Thread(() => {
    foreach (var node in stack)
    {
        //The invoke only needs to be used when updating GUI Elements
        this.Invoke((MethodInvoker)delegate() {
            //Everything inside of this Invoke runs on the GUI Thread
            int[,] unstrung = node.unstringNode(node); // turns node of int[] into board of  int[,]
            blocks.setBoard(unstrung); // sets the board to pass in to the GUI
            DrawBoard(); // Takes the board (int[,]) and sets the squares on the GUI to match it.
        });
        Thread.Sleep(500);
    }
}).Start();
于 2014-04-29T17:18:37.013 に答える