使用 Random 类随机化二维数组

Posted

技术标签:

【中文标题】使用 Random 类随机化二维数组【英文标题】:Using Random class to randomize 2d array 【发布时间】:2020-06-14 21:59:26 【问题描述】:

我正在尝试随机化二维数组中的一组预定元素。

using System;

namespace array

    public class tiles
    
        static void Main(string[] args)
        
            Random random = new Random();
            int[,] tilearr =   0, 1, 2 ,  3, 4, 5 ,  6, 7, 8  ;

            for (int i = 0; i < 3; i++)
            
                for (int j = 0; j < 3; j++)
                
                    Console.Write(tilearr[i, j] + " ");
                
                Console.WriteLine();
            

            Console.ReadLine();
        
    

我的问题是,如果我执行 tilearr[i, j] = random.Next(0, 8); 之类的操作,它会随机化数组,但不关心是否存在相同元素的任何重复项。

2 6 7
1 1 3
2 7 0

我所追求的更像是这样的:

2 4 8  1 3 0
0 3 1  5 6 8 
6 7 5, 2 4 7

【问题讨论】:

Shuffle 改为值 您想随机化数组但不重复? 如果您不想重复,您希望以随机顺序放置一组值(或项目)。这叫做 shuffle,这里有成千上万的帖子 这是来自 xanatos 的一个很棒的答案:***.com/questions/30164019/… 一个非常简单的洗牌算法是这样的:“指向”最后一个元素。现在在此之前随机选择一个元素。交换这两个元素。然后“指向”倒数第二个元素并在此之前随机选择一个元素并切换这两个元素。依此类推,直到您“指向”第一个元素。 【参考方案1】:

一个简单而中肯的解决方案是列出一个可用数字列表,然后逐个位置地从列表中随机选择数字。

像这样:

var numbers = new List<int>  0, 1, 2, 3, 4, 5, 6, 7, 8 ;
for(int x = 0; x < 3; ++x) 
    for(int y = 0; y < 3; ++y) 
        // select a random number from the list ...
        int rand = random.Next(0, numbers.Count - 1);
        tilearr[x, y] = numbers[rand];
        // ... and remove it from the list
        numbers.RemoveAt(rand);
    

【讨论】:

【参考方案2】:

正如用户Wai Ha Lee 在 cmets 中所述,随机播放将实现您所寻找的。我会推荐 Fisher Yates Shuffle。

public static void Shuffle<T>(Random random, T[,] array)

    int lengthRow = array.GetLength(1);

    for (int i = array.Length - 1; i > 0; i--)
    
        int i0 = i / lengthRow;
        int i1 = i % lengthRow;

        int j = random.Next(i + 1);
        int j0 = j / lengthRow;
        int j1 = j % lengthRow;

        T temp = array[i0, i1];
        array[i0, i1] = array[j0, j1];
        array[j0, j1] = temp;
     

我从这个answer 中检索了这个实现。

这应该像这样在你的代码中实现,

using System;

namespace array

    public class tiles
    
        static void Main(string[] args)
        
            Random random = new Random();
            int[,] tilearr =   0, 1, 2 ,  3, 4, 5 ,  6, 7, 8  ;
            Shuffle<int>(random, tilearr);

            for (int i = 0; i < 3; i++)
            
                for (int j = 0; j < 3; j++)
                
                    Console.Write(tilearr[i, j] + " ");
                
                Console.WriteLine();
            

            Console.ReadLine();
        
    

确保将 shuffle 通用函数放在您的类中。

HERE 是我在 dotnetfiddle.net 上实现的一个示例。

【讨论】:

hm 我知道名称数组不存在?我是不是做错了什么? 如果您可以复制确切的错误代码或回溯,它将帮助我理解您的意思。 在随机播放函数public static void Shuffle&lt;T&gt;(Random random, T[,] array) 中说名称数组不存在 我添加了一个我的实现示例尝试该链接中的代码以确保它不是一个简单的错误。 这只是虚拟工作室创建功能的简单错误,出于某种原因它不正确,我处于自动驾驶状态,只是没有检查它是否有问题【参考方案3】:

如果从头开始生成数组,则更容易随机化一维数组,然后将其加载到二维数组中。

static int[,] GenerateArray(int size)

    Random r = new Random();   
    var arr = new int[size, size];
    var values = Enumerable.Range(0, size * size).OrderBy(x => r.Next()).ToArray();

    for (int i = 0; i < size; i++)
        for (int j = 0; j < size; j++)
            arr[i, j] = values[i * size + j];

    return arr;

【讨论】:

【参考方案4】:

随机化的一种方法是将二维数组展平,将其随机排列,然后根据原始尺寸重新创建。如果您想使用 Linq/Extension 方法,您可以执行以下操作

Random random = new Random();
int[,] tilearr =  0, 1, 2 ,  3, 4, 5 ,  6, 7, 8 ;

var result = tilearr.OfType<int>()
       .OrderBy(x=> random.Next())
       .ChunkBy(tilearr.GetLength(1))
       .To2DArray();

其中 ChunkBy 和 To2DArray 定义为

public static class Extensions

    public static IEnumerable<IEnumerable<T>> ChunkBy<T>(this IEnumerable<T> source, int chunkSize) 
    
        return source
            .Select((x, i) => new  Index = i, Value = x )
            .GroupBy(x => x.Index / chunkSize)
            .Select(x => x.Select(v => v.Value));
    

    public static T[,] To2DArray<T>(this IEnumerable<IEnumerable<T>> source)
    
        var data = source
            .Select(x => x.ToArray())
            .ToArray();

        var res = new T[data.Length, data.Max(x => x.Length)];
        for (var i = 0; i < data.Length; ++i)
        
            for (var j = 0; j < data[i].Length; ++j)
            
                res[i,j] = data[i][j];
            
        

        return res;
    

Sample Demo

【讨论】:

以上是关于使用 Random 类随机化二维数组的主要内容,如果未能解决你的问题,请参考以下文章

用java随机生成一个6行5列的二维数组

Codeforces Round #439 (Div. 2) Problem E (Codeforces 869E) - 暴力 - 随机化 - 二维树状数组 - 差分

用指针实现二维数组行列求和

numpy创建二维数组

Numpy random函数

Numpy random函数