### 在随机场所将棋子放在棋盘上的最佳方法是什么？

#### [英]What is the best way to put 20 pieces on a chessboard in random places?

An idea I had to solve this, is to make up an buffer of size 8x8, fill it up with pointers to my checkers (all 20 of them), and the rest leave 0 (null), then run a shuffling algorithm on the buffer, and thats it (just read it as a 8x8 array)

1. I was wondering if there's a better way to do this.
2. 我想知道是否有更好的方法来做到这一点。

3. I need to write it in C#, and my proposal wouldn't work in the way I described it
4. 我需要用C#编写它,我的提议不会像我描述的那样工作

anyone ?

## 4 个解决方案

### #1

To piggyback on Borzio's idea, as you approach the twentieth piece, there is a 1 in 3 chance that you will have to re-generate the random number and try again. With 20 pieces, you're probably still safe, but were you to have, say, 40 pieces, there would be better than a 1 in 2 chance and you might be stuck waiting a while.

1. Construct the board array, all empty.
2. 构造板阵列,全部为空。

3. Copy a reference to each board square to a list (`emptySquareList`).
4. 将对每个板方块的引用复制到列表(emptySquareList)。

5. Loop for each piece you want to add:
1. Generate a random number between `0` and `emptySquareList.Length-1`.
2. 生成0到emptySquareList.Length-1之间的随机数。

3. Put the piece in that square
4. 把那块放在那个方块里

5. Remove the square from the `emptySquareList`.
6. 从emptySquareList中删除方块。

6. 为要添加的每个部分循环:生成0到emptySquareList.Length-1之间的随机数。将片段放在该正方形中从emptySquareList中删除正方形。

This way, you're always maintaining a list of empty squares, and choosing from them. Note that an array of indexes into your board array works just as well and might be faster (`Enumerable.Range(0,64)`).

I encourage you to experiment with the random-and-check algorithm, as well as this one; see which one's more efficient.

### #2

An 8x8 matrix which contains either pointers (c++) to piece objects or references (c#/java) seems like a very reasonable design.

You could use an 1D array that is 64 elements big (you can easily map 2D indexes to a 1D array) and use something like this:

``````using System;
using System.Linq;

Piece[] board = whatever();

// New random number generator.
Random random = new Random();

// LINQ query orders each element by the next random number.
Piece[] randomBoard = (from piece in board
orderby random.Next()
select piece).ToArray();
``````

NOTE: I'm not a c# programmer, but this seems reasonable.

To convert an x,y pair to an array index, you use this algorithm:

``````int index = (y * 8) + x;
``````

NOTE2: I don't know if you have to follow placement rules of checkers or not, if you do, you need to do something more clever. You could maybe have an array 32 elements big (representing all black squares). Shuffle around in that, then assign each element in the 32 big array to each "black" square of the real 64 element array.

### #3

To answer the question that has been posed:

1. Place the first chess piece in a random spot that isn't already occupied
2. 将第一个棋子放在一个尚未占用的随机位置

3. Repeat for the other 19 pieces
4. 重复其他19件

Seriously, you haven't given us enough information to go on to answer this question at all. Here's some questions:

• Which chess pieces?
• 哪个棋子?

• Which colors (there's 16 of each), and does color matter? Will whites have to avoid being captured by blacks, and vice versa?
• 哪种颜色(每种颜色有16种),颜色是否重要?白人是否必须避免被黑人俘获,反之亦然?

Assuming there's no rules to follow, except that you need to place all 20 on the board, ie. no collisions, this will do what you want:

``````Piece[] pieces = ... your 20 pieces here
Piece[] board = new Piece[8 * 8];
Random r = new Random();
foreach (Piece piece in pieces)
{
while (true)
{
Int32 location = r.Next(board.Length);
if (board[location] == null)
{
board[location] = piece;
break;
}
}
}
``````

A simpler solution, provided you already have helper-routines somewhere, would be to just place them at the start of the 64-element array, then shuffle the entire array. This would shuffle those 20 pieces and the 44 empty squares around, and would effectively place them in random spots.

### #4

If you have to follow placement rules, given your 8x8 matrix example, I would also consider it a 1d array as Evan pointed out -- (see his math for determining x & y) --

Black and white squares are the odd and even index values; But, hey, you never said you needed placement rules -- I also presume you aren't looking for c# code but more "logic" level ideas...

If you are trying for a Linq-Challenged solution, consider the following;

1. Construct the "board" array, all empty; (64 elements)
2. 构造“board”数组,全部为空; (64个元素)

3. Construct the "game piece" array consisting of your pieces
4. 构建由您的作品组成的“游戏片”阵列

5. Create a loop from 1 to # of pieces
6. 创建一个从1到#的循环

7. Generate a random number between 1 and # of board spaces (64)
8. 生成1到1个板空间之间的随机数(64)

9. If board space pointed to by #4 is !0, redo step 4 (or you can "while" !0)
10. 如果#4指向的电路板空间为!0,则重做步骤4(或者你可以“同时”!0)

11. Place the piece (# from loop in step 3) into square X from step 4
12. 将该块(步骤3中的循环#)放入步骤4的方形X中

Just ONE idea of which are sure to be many --

Hope it helps ...