生成1&0和0的网格而不连续

时间:2016-02-21 06:47:42

标签: java

我想创建一个程序,创建一个零和一个零的网格,没有三个连续(一个或零,垂直和水平)。程序应该在每次调用时生成网格的随机排列。程序应该每行和每列产生等量的1和0(例如:12x12 - 6个零和6个)。我已经准备了一个二维整数数组,其中将存储零和1。我还准备了一个随机数发生器。我的问题是我不知道从哪里开始,如何在没有连续的情况下这样做?

以下是我到目前为止所做的示例程序:

import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import javax.swing.border.*;

import java.util.*;

public class 
SampleGrid
{

    int noOfTiles = 0;
    int status [][] = new int [12][12];

    Container contentPane;
    JFrame frame = new JFrame ();
    JPanel pnlCenter = new JPanel ();
    JPanel pnlGrid = new JPanel ();
    JPanel pnlArray [][] = new JPanel [12][12];
    JPanel pnlButton = new JPanel (new GridLayout (1, 2));
    JButton btnArray [][] = new JButton [12][12];
    JButton btnNewGame = new JButton ("New Game");
    JButton btnRestart = new JButton ("Restart");

    /**
        * Constructors
    */
    /* Default Constructors */
    public 
    SampleGrid () 
    {

    }

    public 
    SampleGrid (int noOfTiles) 
    {
        this.noOfTiles = noOfTiles;
        this.status = new int [noOfTiles][noOfTiles];

        this.pnlGrid.setLayout (new GridLayout (noOfTiles, noOfTiles));
        this.pnlArray = new JPanel [noOfTiles][noOfTiles];
        this.btnArray = new JButton [noOfTiles][noOfTiles];
    }

    public void 
    launchFrame () 
    {

        Random rand = new Random ();
        int oneCounter = 0;
        int zeroCounter = 0;
        int first = rand.nextInt (2 - 1 + 1) + 1;
        int even = rand.nextInt (2 - 1 + 1) + 1;
        int counter = 0;
        int pointer = 0;
        boolean isFirst = true;

        contentPane = frame.getContentPane ();

        for (int count = 0; count < noOfTiles; count++) {
            for (int count2 = 0; count2 < noOfTiles; count2++) {

                int random = rand.nextInt (2 - 1 + 1) + 1;
                pointer = (count + 1) * (count2 + 2);

                pnlArray [count][count2] = new JPanel ();
                btnArray [count][count2] = new JButton ();

                pnlArray [count][count2].add (btnArray [count][count2]);
                pnlArray [count][count2].setBorder (BorderFactory.createEtchedBorder (EtchedBorder.RAISED, Color.BLACK, Color.BLACK));

                // Generate the first Row
                if (count != 0) {
                    isFirst = false;
                }

                try {
                    if (isFirst) {
                        if (random == 2) {
                            if (oneCounter != 3) {
                                if (count2 != 0 || count2 != 1) {
                                    if (status [count][count2 - 1] != 2 && status [count][count2 - 2] != 2) {
                                        btnArray [count][count2].setText ("1");
                                        status [count][count2] = 1;
                                        oneCounter++;
                                    } else {
                                        btnArray [count][count2].setText ("0");
                                        status [count][count2] = 0;
                                        zeroCounter++;
                                    }
                                } else {
                                    btnArray [count][count2].setText ("1");
                                    status [count][count2] = 1;
                                    oneCounter++;
                                }
                            } else {
                                if (count2 != 0 || count2 != 1) {
                                    if (status [count][count2 - 1] != 2 && status [count][count2 - 2] != 2) {
                                        btnArray [count][count2].setText ("0");
                                        status [count][count2] = 0;
                                        zeroCounter++;
                                    } else {
                                        btnArray [count][count2].setText ("1");
                                        status [count][count2] = 1;
                                        oneCounter++;
                                    }
                                } else {
                                    btnArray [count][count2].setText ("0");
                                    status [count][count2] = 0;
                                    zeroCounter++;
                                }
                            }
                        } else {
                            if (zeroCounter != 3) {
                                if (count2 != 0 || count2 != 1) {
                                    if (status [count][count2 - 1] != 2 && status [count][count2 - 2] != 2) {
                                        btnArray [count][count2].setText ("0");
                                        status [count][count2] = 0;
                                        zeroCounter++;
                                    } else {
                                        btnArray [count][count2].setText ("1");
                                        status [count][count2] = 1;
                                        oneCounter++;
                                    }
                                } else {
                                    btnArray [count][count2].setText ("0");
                                    status [count][count2] = 0;
                                    zeroCounter++;
                                }
                            } else {
                                if (count2 != 0 || count2 != 1) {
                                    if (status [count][count2 - 1] != 2 && status [count][count2 - 2] != 2) {
                                        btnArray [count][count2].setText ("1");
                                        status [count][count2] = 1;
                                        oneCounter++;
                                    } else {
                                        btnArray [count][count2].setText ("0");
                                        status [count][count2] = 0;
                                        zeroCounter++;
                                    }
                                } else {
                                    btnArray [count][count2].setText ("1");
                                    status [count][count2] = 1;
                                    oneCounter++;
                                }
                            }
                        }
                        isFirst = false;
                    }
                } catch (ArrayIndexOutOfBoundsException aiobe) {
                    System.out.println (aiobe);
                }

                btnArray [count][count2].setOpaque(false);
                btnArray [count][count2].setContentAreaFilled(false);
                btnArray [count][count2].setBorderPainted(false);

                pnlGrid.add (pnlArray [count][count2]);
            }

            zeroCounter = 0;
            oneCounter = 0;
        }

        pnlButton.add (btnNewGame);
        pnlButton.add (btnRestart);

        pnlCenter.add (pnlGrid, BorderLayout.CENTER);

        contentPane.add (pnlCenter, BorderLayout.CENTER);
        contentPane.add (pnlButton, BorderLayout.SOUTH);
        if (noOfTiles == 6) {
            frame.setSize (500, 525);
        } else if (noOfTiles == 8) {
            frame.setSize (650, 650);
        } else {
            frame.setSize (975, 975);
        }
        frame.setLocationRelativeTo (null);
        frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
        frame.setVisible (true);
    }

    public static void main (String args []) {
        System.out.println ("Enter the number of Tiles (6 / 8 / 10): ");
        Scanner scan = new Scanner (System.in);
        int N = scan.nextInt ();
        SampleGrid grid = new SampleGrid (N);
        grid.launchFrame ();
    }

}

提前致谢!

2 个答案:

答案 0 :(得分:0)

作为一个评论:没有任何令人费解的事情(在纸面上,在思想中)。

首先在没有GUI的情况下进行纯数据。

int[] generateLineHalf1sNo111(int n, Random rand) {
    int[] line = new int[n]; // All 0.
    int onesNeeded = n / 2;
    int consecutiveOnes = 0;
    for (int i = 0; i < n && onesNeeded > 0; ++i) {

        // Because of past filling:
        boolean mustBe0 = consecutiveOnes == 2;

        // Because of following free space
        // To be at most filled two third: 110110
        boolean mustBe1 = n - i - onesNeeded / 3 < onesNeeded;

        assert !mustBe0 || !mustBe1;
        // Can always fill up with 011 011 011...

        int picked;
        if (mustBe0) {
            picked = 0;
        } else if (mustBe1) {
            picked = 1;
        } else  {
            picked = rand.nextInt(2);
        }
        if (picked == 0) {
            consecutiveOnes = 0;
        } else if (picked == 1) {
            ++consecutiveOnes;
            line[i] = 1;
            --onesNeeded;
        }
    }
    return line;
}

n - i - onesNeeded / 3是可供其使用的空间。

这里的问题是,除了填写随机的1和0之外, future 填写必须足以解决问题。

顺便说一下,我没试过。

答案 1 :(得分:0)

这是一个次优解决方案,在填充网格时使用回溯,以便满足两个约束:最多两个连续的单元格在水平和垂直方向上都应该具有相同的值,并且0和1的数量必须是在每一行和每一列都是一样的。

/**
 * Creates a m * n-grid where each entry is either 0 or 1,
 * each row contains the same amount of 1's and 0's and where no
 * three consecutive cells in horizontal or vertical direction
 * contain the same entry.
 */
public int[][] makeGrid(int n, int m) {
    // since we want the same number of 1's and 0's per row and
    // per column, both n and m must be even numbers
    if (n % 2 == 1) {
        throw new IllegalArgumentException("n must be an even number");
    }
    if (m % 2 == 1) {
        throw new IllegalArgumentException("m must be an even number");
    }

    int[][] grid = new int[n][m];

    // initialize grid: cells that have not yet been assigned a
    // value shall be marked with -1
    for (int y = 0; y < m; y++) {
        for (int x = 0; x < n; x++) {
            grid[x][y] = -1;
        }
    }

    Random random = new Random();

    int[][] colCounts = new int[n][2];
    int[][] rowCounts = new int[m][2];

    // we're filling the grid from top to bottom and from left to
    // right. Instead of using two ints (say, x and y), we
    // awkwardly use an int-array with two entries. The only
    // reason for that is hideous construction is so that we can
    // implement 'backtrack' as a separate method.
    int[] xy = new int[2];
    for (xy[1] = 0; xy[1] < m; xy[1]++) {
        for (xy[0] = 0; xy[0] < n; xy[0]++) {
            // if the grid cell we're currently looking at is
            // empty, we set it to either 1 or 0 at random, unless
            // we've already exhausted the maximum number of 1's
            // or 0's per row or column, in which case we have to
            // use whatever is the opposite value.
            if (grid[xy[0]][xy[1]] == -1) {
                int cell;
                if (rowCounts[xy[1]][0] == n / 2) {
                    if (colCounts[xy[0]][1] == n / 2) {
                        backtrack(xy, n, m);
                        continue;
                    } else {
                        cell = 1;
                    }
                } else if (rowCounts[xy[1]][1] == n / 2) {
                    if (colCounts[xy[0]][0] == n / 2) {
                        backtrack(xy, n, m);
                        continue;
                    } else {
                        cell = 0;
                    }
                } else {
                    cell = random.nextInt(2);
                }

                // if the chosen value resulted in a constraint
                // violation, we cannot leave it. By decrementing
                // xy[0], we make sure that the inner for-loop above
                // will come back here again in the next
                // step. When it does, it will go into the 'else'
                // case below because grid[xy[0]][xy[1]] is now no longer
                // -1
                if (!setGrid(grid, xy[0], xy[1], cell, n, m, colCounts, rowCounts)) {
                    xy[0]--;
                }
            } else {
                // the grid value at (xy[0],xy[1]) was set before, but the
                // value then chosen apparently lead to a
                // constraint violation. Whatever value that was,
                // let's try the other value instead.
                if (!setGrid(grid, xy[0], xy[1], 1 - grid[xy[0]][xy[1]], n, m, colCounts, rowCounts)) {
                    // the other value did not work either, so we
                    // have to backtrack further to find a remedy.
                    // Undo the grid value and move back to
                    // previous grid position.
                    colCounts[xy[0]][grid[xy[0]][xy[1]]]--;
                    rowCounts[xy[1]][grid[xy[0]][xy[1]]]--;
                    grid[xy[0]][xy[1]] = -1;
                    backtrack(xy, n, m);
                }
            }
        }
    }

    return grid;
}

protected boolean setGrid(int[][] grid, int x, int y, int cell, int n, int m, int[][] colCounts, int[][] rowCounts) {
    // if a grid value was already set before at (x,y) the
    // colCounts and rowCounts were changed accordingly, too. We
    // have to undo that change first.
    if (grid[x][y] != -1) {
        colCounts[x][grid[x][y]]--;
        rowCounts[y][grid[x][y]]--;
    }

    grid[x][y] = cell;

    // now, we can update the colCounts and rowCounts according to
    // the value we just set
    colCounts[x][cell]++;
    rowCounts[y][cell]++;

    // check whether no more than two cells in a row have the same
    // value
    if (x-2 >= 0) {
        if (grid[x-2][y] == cell &&
            grid[x-1][y] == cell) {
            return false;
        }
    }

    // check whether no more than two cells in a column have the
    // same value
    if (y-2 >= 0) {
        if (grid[x][y-2] == cell &&
            grid[x][y-1] == cell) {
            return false;
        }
    }

    return true;
}

private void backtrack(int[] xy, int n, int m) {
    // move one column to the left, if possible, otherwise move
    // one row up
    if (xy[0] == 0) {
        if (xy[1] == 0) {
            // we cannot backtrack any further
            throw new IllegalArgumentException("No solution possible for n=" + n + ", m=" + m);
        }
        // backtrack to the last column in the
        // previous row
        xy[0] = n - 2;
        xy[1]--;
    } else {
        // backtrack to the previous column
        xy[0] -= 2;
    }
}

除了由于这里使用的可怕的xy数组而接近不可读之外,当单元格值的随机分配做出“坏”决定时,该解决方案也会遇到问题,这只会导致问题。在这种情况下,它必须一直回溯到最初引入问题的位置。如果您考虑12x12网格,其中每个单元格为0或1,则会创建2 ^ 144个可能分配的搜索空间。你可以想象,在那个空间进行详尽的搜索是很棘手的。

由于代码的可读性问题以及上述实用性考虑因素,我不情愿地发布此解决方案。不过,您可能仍希望了解一下,或许它可以激励您(或其他人)获得更好的解决方案。