C++ random number trail

Hi!
I have to make a very simple game. There are 4 players in a 10x10 array, they get there random starting position and then go collecting other positions in the array. The player can go 1 position in any direction in one iteration, they can battle other players for there places, but they cant stand in the same place, because thats just useless.. I made a player class and then a few functions, everything works almost fine. There is such a thing that, sometimes, players jums 2 positions in a direction :/ Canf find why they are doing sush a thing :|

This function finds the next x,y values:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
int next()
		{
			xn=x+ran(3)-1;
			yn=y+ran(3)-1;

			
					while(yn>9 || yn<0 || xn>9 || xn<0 || xn==x && yn==y)
					{
						if(xn>9 || xn<0)
						{
							xn=x+ran(3)-1;
						}
						
						if(yn>9 || yn<0)
						{
							yn=y+ran(3)-1;
						}
						if(xn==x && yn==y)
						{
							xn=x+ran(3)-1;
							yn=y+ran(3)-1;
						}

					}
				
				x=xn;
				y=yn;
				return x,y;
		}


Battle function, checks if empty or a other player owns it:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
int check(int color)
		{
			if(field[x][y]!=0 && field[x][y]!=color)
		{
			int a,b,colorx=field[x][y];
			a=ran(6);
			b=ran(6);
			while(a==b)
			{
				a=ran(3);
				b=ran(3);
			}

				if(a>b)
			{
				field[x][y]=color;
				cout<<color<<". player got "<<x<<" "<<y<<" from "<<colorx<<". player!"<<endl;
			}
			if(a<b)
			{
				field[x][y]=colorx;
				cout<<colorx<<". player got "<<x<<" "<<y<<" from "<<color<<". player!"<<endl;
			}
		}
			return 0;
		}


Puts these both together + cheks if the current player does not have the index:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
int go(int color)
	{
		cout<<color<<". Speletaja gajiens!"<<endl;
		next();
		
	if(field[x][y]==color)
	{

		while(field[x][y]==color)
		{
			next();
		}
	
	}

	check(color);


	if(field[x][y]==0)
	{
		field[x][y]=color;
		cout<<color<<". player conquers "<<x<<" "<<y<<" coordinates!"<<endl;
	}
	
	return field[10][10];
	}


Very sorry for the long post, any help would be appreciated! I can post the full code if nessesary, maybe i have made a big mess of things :D
What does the ran(int) function do? If it's a std::rand-like function, check how it works. std::rand returns a random number inside the range [0,RAND_MAX] (RAND_MAX being a [usually irrelevant] value). You then have to use something like

(rand() % (MAXIMUM_VALUE - MINIMUM_VALUE)) + MINIMUM_VALUE

to put it in the range you want.

PS: also, you have lots of unnecessary tests that could be reduced, to improve performance and clarity. Your while loop in next() could be replaced by:

1
2
3
4
5
6
7
8
while(true) {
    if(xn > 9 || xn < 0 || xn == x)
        xn = x + ran(3) - 1;
    else if(yn > 9 || yn < 0 || yn == y)
        yn = y + ran(3) - 1;
    else
        break;
}
1
2
3
4
5
int loop()
{
   //...
   return x,y; // WTF? (It will only return y, due to C++'s rules)
}
Last edited on
ran(int max) is a rand()%max function, just so that the code would be easier to read. I though i forgot to mention something i should have mentioned..
The other two functions look ok?
I had a very similar code with yours (a bit longer though). There is a problem: xn==y && yn==y is bad, because stays at the same position, but xn==x || yn==y is ok. In your variant xn==x || yn==y is not possible. I could go that way, but then there would be a lot of unused turns for players.. Ill add my full code, nothing too complicated.

P.S. Got a question about printing a array with the use of a function (got one there), it prints only one array, if i modified it so that it takes a array and prints i recieved an error :/ Thanks in advance!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
#include<iostream>
#include<stdlib.h>
#include<time.h>
#include<string.h>
#define SK 15
#define L 10
using namespace std;

int k,i,j,field[L][L],res[L][L];

class player
{
private:
		int	x,xn,y,yn;
public:
		int ran(int max)
		{
			return rand()%max;
		}

		int next()
		{
			xn=x+ran(3)-1;
			yn=y+ran(3)-1;

			
					while(yn>9 || yn<0 || xn>9 || xn<0 || xn==x && yn==y)
					{
						if(xn>9 || xn<0)
						{
							xn=x+ran(3)-1;
						}
						
						if(yn>9 || yn<0)
						{
							yn=y+ran(3)-1;
						}
						if(xn==x && yn==y)
						{
							xn=x+ran(3)-1;
							yn=y+ran(3)-1;
						}

					}
				
				x=xn;
				y=yn;
				return x,y;
		}

		int start(int color)
	{
		x=ran(9);
		y=ran(9);
		if(field[x][y]!=0)
		{
			while(field[x][y]!=0)
			{
				x=ran(9);
				y=ran(9);
			}
		}
		field[x][y]=color;
		cout<<color<<". player starts at: "<<x<<" "<<y<<"!"<<endl;
		return x,y;
	}

		int check(int color)
		{
			if(field[x][y]!=0 && field[x][y]!=color)
		{
			int a,b,colorx=field[x][y];
			a=ran(6);
			b=ran(6);
			while(a==b)
			{
				a=ran(3);
				b=ran(3);
			}

				if(a>b)
			{
				field[x][y]=color;
				cout<<color<<". player got "<<x<<" "<<y<<" from "<<colorx<<". player!"<<endl;
			}
			if(a<b)
			{
				field[x][y]=colorx;
				cout<<colorx<<". player got "<<x<<" "<<y<<" from "<<color<<". player!"<<endl;
			}
		}
			return 0;
		}
		
		int go(int color)
	{
		cout<<color<<". Speletaja gajiens!"<<endl;
		next();
		
	if(field[x][y]==color)
	{

		while(field[x][y]==color)
		{
			next();
		}
	
	}

	check(color);


	if(field[x][y]==0)
	{
		field[x][y]=color;
		cout<<color<<". player conquers "<<x<<" "<<y<<" coordinates!"<<endl;
	}
	
	return field[10][10];
	}

};

int count(int color)
		{
			int point=0;
			for(i=0;i<L;i++)
			{
				for(j=0;j<L;j++)
				{
					if(field[i][j]==color)
					{
						point++;
					}
				}
			}
			return point;
		}

int print()
{	  
	  for(k=0;k<L;k++)
	{
		
		for(j=0;j<L;j++)
		{
			
			cout<<field[k][j]<< " ";
			
		}
		cout<<endl;
	}
	  return 0;
}

int resources()
{
	for(i=0;i<L;i++)
	{
		for(j=0;j<L;j++)
		{
			res[i][j]=rand()%2;
			cout<<res[i][j]<<" ";
		}
		cout<<endl;
	}
	return 0;
}

int winner_is()
{
	int score[4];
	score[0]=count(1);
	score[1]=count(2);
	score[2]=count(3);
	score[3]=count(4);
	resources();
	
	for(k=0;k<4;k++)
	{
		for(i=0;i<L;i++)
		{
		for(j=0;j<L;j++)
			{
				if(field[i][j]==(k+1))
				{
					score[k]=score[k]+res[i][j];
				}
			}
		}	
	}
	
	int pp;
	int max=0;
	for(i=0;i<4;i++)
	{
		if(score[i]>max)
		{
			max=score[i];
			pp=i+1;
		}
	}
	int tie=0;
	for(i=0;i<4;i++)
	{
		if(score[i]==max)
		{
			tie++;
		}
	}

	if(tie>1)
	{
		cout<<endl;
		cout<<"Neizskirts, saja spele uzverataja nav!"<<endl;
	}
	else
	{
		cout<<endl;
		cout<<"Un uzvaretajs ir: "<<pp<<". speletajs ar "<<max<<" punktiem!"<<endl;
	}
	return 0;
}

int main()
{
	memset(field,0,sizeof field);
	srand(time(NULL));
	player one;
	player two;
	player three;
	player four;
	cout<<endl;
	cout<<"Speletaju sakuma koordinates:"<<endl;
	one.start(1);
	two.start(2);
	three.start(3);
	four.start(4);
	cout<<endl;
	print();
	system("pause");
	system("cls");
	for(i=0;i<SK;i++)
	{
		one.go(1);
		two.go(2);
		three.go(3);
		four.go(4);
		cout<<endl;
		print();
		system("pause");
		system("cls");
	}
	
	cout<<"Pirma speletaja iegutie punkti! "<<count(1)<<endl;
	cout<<"Otra speletaja iegutie punkti! "<<count(2)<<endl;
	cout<<"Tresa speletaja iegutie punkti! "<<count(3)<<endl;
	cout<<"Cetruta speletaja iegutie punkti! "<<count(4)<<endl;

	winner_is();
	

	return getchar();
}


I could of course hand in the programm as it is, becuase i think nobody will notice that it does not function exactly as i said it would, but i really want to make it function correctly^^
In your go function, you move, then check if the colour on that position is different from the player's, then keep moving and checking, until you get to a valid position. That way, your player can move the entire map if it gets the correct random movements. Example:

Board:
1000
0100
2010
0001

If your player is at position [0,0], your go function can check positions [1,1], [2,2] and [3,3], then find [3,2]. You player will then move from [0,0] to [3,2]. Maybe that's desirable, I'm just pointing it out.
Last edited on
Just cheked the return values, i dont need them, because each player has there own coordinates, thanks for pointing out.
Thanks mate, that kind of behavior is not desirable, any suggestions?
One can not simply move from [0,0] to [3,2].. Only to the positions next to the current loaction.
You have to check the color of that position without moving to it.
How did you find the problem so fast? From experiance?
Did a bit of correcting, deleted the color check from the go function and added the color check to the next function, how should a make a break for the check, because there is a possibility for the player to get stuck in the corner.. or by the side..

Changes:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
int next(int color)
		{
			xn=x+ran(3)-1;
			yn=y+ran(3)-1;

			
			while(yn>9 || yn<0 || xn>9 || xn<0 || (xn==x && yn==y) || field[xn][yn]==color)
					{
						if(xn>9 || xn<0 || field[xn][yn]==color)
						{
							xn=x+ran(3)-1;
						}
						
						if(yn>9 || yn<0 || field[xn][yn]==color)
						{
							yn=y+ran(3)-1;
						}
						if(xn==x && yn==y && field[xn][yn]==color)
						{
							xn=x+ran(3)-1;
							yn=y+ran(3)-1;
						}

					}
				
				x=xn;
				y=yn;
				return 0;
		}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
int go(int color)
	{
		cout<<color<<". Speletaja gajiens!"<<endl;
		next(color);
		

	check(color);


	if(field[x][y]==0)
	{
		field[x][y]=color;
		cout<<color<<". player conquers "<<x<<" "<<y<<" coordinates!"<<endl;
	}
	
	return 0;
	}


Thanks for the great input!
What you're doing is a kind of "brute force path finding", where you randomly hop around until you get to a valid position. Since your player can only move in (at most) 9 directions, you could check those directions before the random move checks, to see if there is at least one valid move.

But, if you do that, you can restrict your random moves to just these possible moves, avoiding the need to check for bounds or colours.


As for finding bugs, the first step is to know your problem. You had one that was very clear: your players sometimes moved two steps. Then you isolate the places in your code where you make movements, and look for spots (usually conditionals) where you might have done something wrong. It's not an easy task, but you get better at it the more you do it. Also, that's where encapsulation makes your task easier, because it reduces the places you have to look, by reducing the places where things can mess up other things.
Well, i made a little code to check if there are any positions to move to, seems to work flawlessly and that bothers me, can someone please take a look for possible problems? These lines were added to the next function. If numbers get equal to 9 (nowhere to move) the function stops, otherwise everything goes on as it used to.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
int numbers=0;
						for(ii=-1;ii<2;ii++)
						{
							for(jj=-1;jj<2;jj++)
							{

								if((x+ii)<0 || (y+ii)<0 || (x+ii>9) || (y+jj>9))
								{
									numbers++;
									break;
									
								}
								
									if(field[x+ii][y+jj]==color)
									{
									numbers++;
									}
								
							}
							
						}
Yeah, that's OK. I have only some stylistic observations:

- You can replace your break statement with an else if.
- I think the intention of the condition on the for loops would be more apparent if you wrote

 
for(ii = -1; ii <= 1; ++ii)

instead. But that's just an opinion.
Topic archived. No new replies allowed.