(C#)如何均匀地,但随机地填充2个不同数字的2D数组?

时间:2016-02-24 23:31:07

标签: c# random multidimensional-array

对于随机抽动的tic-tac-toe游戏模拟器,我需要利用2D阵列来模拟2个玩家之间的回合。为了填充数组,我一直在使用一个简单的随机数生成器来生成0到1之间的随机数。

    //create 2D array
  const int ROWS = 3;
  const int COLS = 3;
  int[,] tictactoeArray = new int[ROWS, COLS];
   //create random variable
  Random rand = new Random();

   //method to fill array with random values between 0 and 1.
  private void RandomizeArray(ref int[,] iArray)
  {
      for (int row = 0; row < ROWS; row++)
      {
          for (int col = 0; col < COLS; col++)
          {
              tictactoeArray[row, col] = rand.Next(2);
          }
      }
  }

但是当我使用这样的随机数生成器时,我偶尔会得到与tic-tac-toe相关的不可能的值组合。因为价值1将发生6次或更多次,并使游戏对另一个“玩家”不公平。我已经进行了大量的搜索,但还没有找到一种方法(或多或少)均匀地分配2个值。有什么建议吗?

5 个答案:

答案 0 :(得分:2)

你需要模拟玩家的回合。而不是随机生成1或2,您可以按照以下算法假设

0. initialize all 9 positions with 0  on tic-tac-toe board
1. select a number between 0 to 8 randomly. ( which denotes one of 9 positions)
2. put 1 in that position
3. select another number  between 0 to 8 randomly ( if it collides with number previously selected pull other  random number.  
4. put 2 in that position. 
5. repeat till all the  9 positions are filled.

方法2 ..

create a Linked list of 9 numbers (from 1 to 9). 
draw a number (name it x) between 1 to size of the Set ( which will be 9 for first draw)
read the value at the  position 'x' and put 1 in that position 
remove the element at position x
draw another number x ( between 1 to 8 this time ) and put 2 in that position.
remove the element at position x.
keep doing till linked list is empty.

答案 1 :(得分:0)

问题标题的字面答案是这样的:

var random = new Random();
var randomValues = new[] { 0, 0, 0, 0, 0, 1, 1, 1, 1, 1 } // enough values to fill board
    .Select(x => new { Weight = random.Next(), Value = x }) // add random weight
    .OrderBy(x => x.Weight) // order by weight to create random sort
    .Take(9) // only need 9 of the 10 values
    .ToList();
var ticTacToeBoard = new int[3, 3];
var index = 0;
for (int row = 0; row < 3; row++) // fill the two-dimensional array
{
    for (int column = 0; column < 3; column++)
    {
        ticTacToeBoard[row, column] = randomValues[index].Value;
        index++;
    }
}

大多数时候,这个&#34;随机而无需替换&#34;技术将导致一个可能的结束游戏板,但是,你偶尔会得到一个连续3个零 3个游戏的游戏板,这将是无效的。要解决这个问题,你可以将上面的代码放在一个循环中,只有在有效游戏板的情况下才退出循环。

那就是说,我同意@ meetthakkar实际模拟游戏的方法对这个特定问题更有意义。

答案 2 :(得分:0)

在一维数组中预先创建x和o然后随机随机地移动它似乎更简单

            //Both X and O always get at least 4 moves
            List<int> common = new List<int> { 0, 0, 0, 0, 1, 1, 1, 1 };

            //Either X or O gets a 5th move, make this equally likely
            Random rand = new Random();
            common.Add(rand.Next(0, 2));

            //Randomly shuffle the X's and O's, this creates a completed tic tac toe board
            //This can have more than one winner since we aren't stopping when someone wins
            //as would normally be done
            var randomBoard = common.OrderBy(x => rand.Next()).ToArray();

            //Convert to a 2 dimensional array if desired
            int[,] twoDRandomBoard = new int[3, 3];
            for (int i = 0; i < randomBoard.Length; i++)
                twoDRandomBoard[i / 3, i%3] = randomBoard[i];

你最终会得到一些有两个“赢家”的董事会,但如果你认为整个董事会已满,这就是你在问题中所表现出来的方式。如果你想在某人获胜后停止,那么这将是不同的,但这将适用于随机完整的董事会。

答案 3 :(得分:0)

好吧,我可能有点困惑,但是从那个开始填充1或0表示的井字棋盘是没有意义的,可能是1或2。

建议执行以下操作:

private static ThreadLocal<Random> rand = new ThreadLocal<Random>(()=>new Random());

const int PLAYER_ONE = 1;
const int PLAYER_TWO = 2;

//color decided by who goes first in tic-tac-toe?
private static int playingColor;

private static void PlayRound(int[][] board)
{
    var playableCoords = new List<Tuple<int,int>>();

    for(int x=0;x<board.Length;x++)
        for(int y=0;y<board[x].Length;y++)
            if(board[x][y] == 0)
                playableCoords.Add(Tuple.Create(x,y));

    //check for a terminal board state before you do this method
    if(!playableCoords.Any()) return;

    var randm = rand.Value;

    var vl = playableCoords[ randm.Next(playableCoords.Count - 1) ];

    board[vl.Item1][vl.Item2] = playingColor ;
}

有更有效的方法可以做到这一点,如果你正在处理一个有很多可能组合的棋盘,那么我会建议保留一个可用位置的记录并从那里开始,但是对于一个3x3游戏看不到需要这样做。

如果您想要这样做直到它已满,请执行以下操作:

var board = new int[3][3];
for(int i=0;i<9;i++)
{ 
    playingColor = (i%1)+1;
    PlayRound(board);
}

对我来说没有意义,但这就是你如何模拟游戏。

答案 4 :(得分:0)

void RandomizeArray(ref int[,] iArray)
    {
        for (int row = 0; row < ROWS; row++)
        {
            for (int col = 0; col < COLS; col++)
            {
                Random rand = new Random();
                tictactoeArray[row, col] = rand.Next(2);
            }
        }
    }

请将Random rand = new Random()放入功能正文中。 每次制作一个新兰特时可能会更好。