我想在8x8板上選擇隨機座標。 x和y座標只能是-8。 -6,-4,-2,0,2,4,6和8.我想爲20個對象選擇隨機座標,但我不希望任何2個對象具有相同的座標。用C++編程!挑選隨機座標而不重複?
回答
對於每個座標,您只有9個可能的值,因此共有81個可能點。最簡單的解決方案是枚舉所有可能的點(例如:在一個數組或向量中),然後隨機選擇20.
您可以通過從0到80中選擇一個索引來隨機選擇20,將該元素索引爲80的數組,然後隨機選取一個從0到79的索引,並將索引替換爲索引79,依此類推20次。然後,數組中最後20個元素將是20個不同的隨機點。
注意:你正在解釋的是[Reservoir sampling](http://en.wikipedia.org/wiki/Reservoir_sampling)(只是爲那些可能不知道它的人提供一個名字)。事實上,一旦你有20個值,你就可以停止交換,因爲那些值不會再改變。 – Joey 2010-11-13 10:59:13
@Joey:「你可以停止交換,一旦你有20個值」,這就是爲什麼我說「......等20次」。 – 2010-11-14 00:47:32
將Laurence的算法放在程序中。它的工作正常。
#include <iostream>
#include <vector>
#include <ctime>
using namespace std;
//To store x and y coordinate of a point
struct Point
{
int x, y;
};
int main()
{
vector<Point> v;
Point p;
//Populate vector with 81 combinations.
for(int i = -8; i < 10; i += 2)
{
for(int j = -8; j < 10; j += 2)
{
p.x = i;
p.y = j;
v.push_back(p);
}
}
srand(time(NULL));
int lastIndex = 80;
for(int i = 0; i < 20; i++)
{
int randNum = rand() % (81-i);
//Swap to isolate chosen points.
std::swap(v[randNum], v[lastIndex-i]);
}
//Print chosen random coordinates
cout<<"Random points chosen are "<<endl;
for(int i = 61; i < 81; i++)
{
Point p = v[i];
cout<<p.x<<"\t"<<p.y<<endl;
}
}
如果你打算使用STL,爲什麼不使用std :: random_shuffle()呢? – Blastfurnace 2010-11-13 08:22:25
@Blastfurnace:是的,但這不是我的vc快遞版本。 – bjskishore123 2010-11-13 08:27:20
我有MSVC++ Express 2010並始終使用附帶的STL。如果你有std :: vector和std :: swap,你應該有其餘的STL可用。 – Blastfurnace 2010-11-13 08:31:27
採取一切座標對在您所設定的,並把它們折騰到一個列表中,並生成列表的隨機置換(標準算法,這個存在,如算法勞倫斯是在暗示)。採取排列的前20個元素。
這是一個很好的解決方案,但它需要的內存與集合的大小成正比。有時候我想知道,當可能的座標數量是天文數字時,是否有辦法解決這個問題。如果集合中有萬億個座標對,我們如何處理這個問題,並且我們想要每次只訪問一次,但是按照隨機順序? – 2010-11-13 07:39:59
只要你可以枚舉你的點,並有效地計算任意點的位置,直接從它的序列號,你可以使用任何有效的一維採樣算法,如弗洛伊德的算法 - 見我的答案瞭解更多的細節。 – 2010-11-13 09:07:49
如果您可以枚舉電路板上的所有座標,則可以使用任何採樣算法。你在9x9網格上;只挑選20個值OUT [0,80]和範圍的然後將它們轉化爲網格座標:
// Say the number picked is "n"
int x = ((n % 9) - 4) * 2;
int y = ((n/9) - 4) * 2;
可以使用任何採樣算法來生成n
S;例如,請查看this question的答案。
這種方法明顯生成點的優點是可以在大型網格上節省相當多的內存(和處理時間)。如果它們真的很大,並且選擇了一個簡單的方法,那麼顯而易見的算法也可以正常工作:只要選擇一個隨機點,如果您已經選擇了一個點,就再試一次。這個算法唯一的問題是,如果你選擇了一大部分集合,它最終可能會做很多次重試。
例如,您可以使用std :: random_shuffle,因爲您的整數座標數量是有限的。所以只需要將這組向量/位置隨機洗牌即可。您也可以將您自己的RNG作爲函數對象傳遞給random_shuffle。
例子:
#include <algorithm> //for copy and random_shuffle
#include <utility> //for pair and make_pair
#include <vector>
...
std::vector<std::pair<int, int> > coords;
std::vector<std::pair<int, int> > coords20(20);
for(int y=-8; y<=8; y+=2)
for(int x=-8; x<=8; x+=2)
coords.push_back(std::make_pair(x,y));
std::random_shuffle(coords.begin(), coords.end());
std::copy(coords.begin(), coords.begin() + 20, coords20.begin());
- 1. 隨機挑選,而不重複
- 2. 挑選隨機顏色而不重複查找排除的顏色
- 3. 挑選隨機值
- 4. ArrayList隨機挑選
- 5. 根據體重和挑選時間挑選隨機密鑰
- 6. 挑選隨機線從標準輸出
- 7. android挑選隨機圖片?
- 8. Math.Random()挑選隨機數組
- 9. 挑選隨機名稱
- 10. 隨機化字符串而不重複
- 11. 指定隨機夥伴而不重複?
- 12. 生成隨機數字而不重複
- 13. 隨機圖像,而不使用重複
- 14. Arraylist隨機座標
- 15. 選擇隨機行不重複
- 16. PHP - 不重複隨機選擇
- 17. 從9箇中選擇四個隨機數而不重複
- 18. 從一個數組中隨機選取元素而不重複
- 19. 在SQL Server中選擇N條隨機記錄而不重複
- 20. 挑選15個隨機數字讓他們洗牌不會得到重複
- 21. Java隨機座標錯誤?
- 22. 隨機元素(座標)
- 23. 生成不同的隨機座標
- 24. 不重複的隨機數
- 25. 隨機數不重複
- 26. 隨機數字不重複
- 27. 隨機挑選3個挑選的數字
- 28. Firebase iOS Swift:如何挑選隨機userProfile?
- 29. 在c中挑選隨機數字#
- 30. 如何挑選隨機陣列中的
所以它實際上是一個9x9的板。 – starblue 2010-11-13 09:50:43