1 | /* This file is part of the KDE libraries |
2 | Copyright (c) 1999 Sean Harmer <sh@astro.keele.ac.uk> |
3 | |
4 | This library is free software; you can redistribute it and/or |
5 | modify it under the terms of the GNU Library General Public |
6 | License version 2 as published by the Free Software Foundation. |
7 | |
8 | This library is distributed in the hope that it will be useful, |
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
11 | Library General Public License for more details. |
12 | |
13 | You should have received a copy of the GNU Library General Public License |
14 | along with this library; see the file COPYING.LIB. If not, write to |
15 | the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
16 | Boston, MA 02110-1301, USA. |
17 | */ |
18 | #ifndef K_RANDOM_SEQUENCE_H |
19 | #define K_RANDOM_SEQUENCE_H |
20 | |
21 | #include <kdecore_export.h> |
22 | #include <QtCore/QList> |
23 | |
24 | /** |
25 | * \class KRandomSequence krandomsequence.h <KRandomSequence> |
26 | * |
27 | * A class to create a pseudo-random sequence |
28 | * |
29 | * Given a seed number, this class will produce a sequence of |
30 | * pseudo-random numbers. This would typically be used in |
31 | * applications like games. |
32 | * |
33 | * In general, you should instantiate a KRandomSequence object and |
34 | * pass along your seed number in the constructor. From then on, |
35 | * simply call getDouble or getLong to obtain the next |
36 | * number in the sequence. |
37 | * |
38 | * @author Sean Harmer <sh@astro.keele.ac.uk> |
39 | */ |
40 | class KDECORE_EXPORT KRandomSequence |
41 | { |
42 | public: |
43 | /** |
44 | * Creates a pseudo-random sequence based on the seed lngSeed. |
45 | * |
46 | * A Pseudo-random sequence is different for each seed but can be |
47 | * reproduced by starting the sequence with the same seed. |
48 | * |
49 | * If you need a single value which needs to be unpredictable, |
50 | * you need to use KRandom::random() instead. |
51 | * |
52 | * @param lngSeed Seed to initialize the sequence with. |
53 | * If lngSeed is 0, the sequence is initialized with a value from |
54 | * KRandom::random(). |
55 | */ |
56 | explicit KRandomSequence( long lngSeed = 0 ); |
57 | |
58 | /** |
59 | * Standard destructor |
60 | */ |
61 | virtual ~KRandomSequence(); |
62 | |
63 | /** |
64 | * Copy constructor |
65 | */ |
66 | KRandomSequence(const KRandomSequence &a); |
67 | |
68 | /** |
69 | * Assignment |
70 | */ |
71 | KRandomSequence &operator=(const KRandomSequence &a); |
72 | |
73 | /** |
74 | * Restart the sequence based on lngSeed. |
75 | * @param lngSeed Seed to initialize the sequence with. |
76 | * If lngSeed is 0, the sequence is initialized with a value from |
77 | * KRandom::random(). |
78 | */ |
79 | void setSeed( long lngSeed = 0 ); |
80 | |
81 | /** |
82 | * Get the next number from the pseudo-random sequence. |
83 | * |
84 | * @return a pseudo-random double value between [0,1) |
85 | */ |
86 | double getDouble(); |
87 | |
88 | /** |
89 | * Get the next number from the pseudo-random sequence. |
90 | * |
91 | * @return a pseudo-random integer value between [0, max) |
92 | * with 0 <= max < 1.000.000 |
93 | */ |
94 | unsigned long getLong(unsigned long max); |
95 | |
96 | /** |
97 | * Get a boolean from the pseudo-random sequence. |
98 | * |
99 | * @return a boolean which is either true or false |
100 | */ |
101 | bool getBool(); |
102 | |
103 | /** |
104 | * Put a list in random order. Since KDE 4.11, this function uses a more |
105 | * efficient algorithm (Fisher-Yates). Therefore, the order of the items |
106 | * in the randomized list is different from the one in earlier versions |
107 | * if the same seed value is used for the random sequence. |
108 | * |
109 | * @param list the list whose order will be modified |
110 | * @note modifies the list in place |
111 | */ |
112 | template<typename T> void randomize(QList<T>& list) { |
113 | // Fisher-Yates algorithm |
114 | for (int index = list.count() - 1; index > 0; --index) { |
115 | const int swapIndex = getLong(index + 1); |
116 | qSwap(list[index], list[swapIndex]); |
117 | } |
118 | } |
119 | |
120 | |
121 | /** |
122 | * Modulate the random sequence. |
123 | * |
124 | * If S(i) is the sequence of numbers that will follow |
125 | * given the current state after calling modulate(i), |
126 | * then S(i) != S(j) for i != j and |
127 | * S(i) == S(j) for i == j. |
128 | * |
129 | * This can be useful in game situation where "undo" restores |
130 | * the state of the random sequence. If the game modulates the |
131 | * random sequence with the move chosen by the player, the |
132 | * random sequence will be identical whenever the player "redo"-s |
133 | * his or hers original move, but different when the player |
134 | * chooses another move. |
135 | * |
136 | * With this scenario "undo" can no longer be used to repeat a |
137 | * certain move over and over again until the computer reacts |
138 | * with a favorable response or to predict the response for a |
139 | * certain move based on the response to another move. |
140 | * @param i the sequence identified |
141 | */ |
142 | void modulate(int i); |
143 | |
144 | private: |
145 | class Private; |
146 | Private *const d; |
147 | }; |
148 | |
149 | #endif |
150 | |