I building a battleship game in C. I have the following code to validate that the points of the randomly placed ship don't exceed the board limit. The code doesn't work very smoothly and the application hangs while generating the random points.
Could you recommend some optimizations to what I have?
while(1 == 1)
{
//Generates the x, y coordenates of the point
int x = rand() % 9;
int y = rand() % 9;
//Calculating the ship direction
char direction = ((rand() % 10) > 5) ? 'V' : 'H';
if(direction == 'H')
{
//Verifies that the ship placed on the acquired x coordenate of the point does not exceed the board size
//if so recalculates the value of x
while(!(((x + ships[i].length) - 1) < 10)) x = (rand() % 5);
}
else
{
//Verifies that the ship placed on the acquired y coordenate of the point does not exceed the board size
//if so recalculates the value of y
while(!(((y + ships[i].length) - 1) < 10)) y = (rand() % 5);
}
//Calculating the coordenates for each point of the ship
for(j = 0; j < ships[i].length; j++)
{
if(direction == 'H')
{
points[j].x = (x + j);
points[j].y = y;
}
else
{
points[j].x = x;
points[j].y = (y + j);
}
//Validating that the coordenate asigned to a point has not been assigned to another ship
if(verifyPos(points[j].x, points[j].y, ships, length))
{
invalid = 1;
break;
}
}
//if all the points of the ship are valid, move to the next ship
//if not recalculate the initial point and the subsequent coordenates
if(invalid == 0) break;
}
ships[i].points = points;
}
}
You need to seed the randomizer.
#include <time.h>
srand(time(NULL));
is a trivial way to do it.
Well one way of improving it would be to choose which direction the ship is going to go V or H and then only use the section of the board that it will fit into so if the ship is 4 long and verticle only use rows 1-7 (of a 10 row board) for the verticle starting point. THen you don't need to check if it will fit at all.
Looking at the code, I don't see where the points assigned in
points[j].x = x;
points[j].y = (y + j);
are cleared if a ship is invalid. As far as I can see teh points array may be filling up with invalid points.
Related
I have to create a program that generates 3 random rectangles and finds the area of each using the coordinates of the upper left point and the bottom right point (coordinates are random and between (-50;50).
The problem is that it must determine the largest rectangle and indicate whether the other two/one are/is located in it, if not - display the corresponding message.
It's not a overlap, other rectangles/rectangle must be fully in the biggest one.
Here is what I've already done:
#include <stdio.h>
#include <locale>
struct Point {
int x;
int y;
};
struct Rectangle {
struct Point topLeft;
struct Point botRight;
};
int Area(struct Rectangle r) {
int length, breadth;
length = r.botRight.x - r.topLeft.x;
breadth = r.topLeft.y - r.botRight.y;
return length * breadth;
}
int main() {
srand(time(NULL));
struct Rectangle r1, r2, r3;
r1.topLeft.x = -50 + rand() % 50;
r1.topLeft.y = -50 + rand() % 50;
r1.botRight.x = -50 + rand() % 50;
r1.botRight.y = -50 + rand() % 50;
while (r1.botRight.x <= r1.topLeft.x) {
r1.botRight.x = -50 + rand() % 50;
}
while (r1.topLeft.y <= r1.botRight.y) {
r1.topLeft.y = -50 + rand() % 50;
}
printf("\t----------RECTANGLE 1----------\n");
printf("\tTop left point is x = %d y = %d\n", r1.topLeft.x, r1.topLeft.y);
printf("\tBottom right point is x = %d y = %d\n", r1.botRight.x, r1.botRight.y);
printf("\tArea is %d\n", Area(r1));
r2.topLeft.x = -50 + rand() % 50;
r2.topLeft.y = -50 + rand() % 50;
r2.botRight.x = -50 + rand() % 50;
r2.botRight.y = -50 + rand() % 50;
while (r2.botRight.x <= r2.topLeft.x) {
r2.botRight.x = -50 + rand() % 50;
}
while (r2.topLeft.y <= r2.botRight.y) {
r2.topLeft.y = -50 + rand() % 50;
}
printf("\t----------RECTANGLE 2----------\n");
printf("\tTop left point is x = %d y = %d\n", r2.topLeft.x, r2.topLeft.y);
printf("\tBottom right point is x = %d y = %d\n", r2.botRight.x, r2.botRight.y);
printf("\tArea is %d\n", Area(r2));
r3.topLeft.x = -50 + rand() % 50;
r3.topLeft.y = -50 + rand() % 50;
r3.botRight.x = -50 + rand() % 50;
r3.botRight.y = -50 + rand() % 50;
while (r3.botRight.x <= r3.topLeft.x) {
r3.botRight.x = -50 + rand() % 50;
}
while (r3.topLeft.y <= r3.botRight.y) {
r3.topLeft.y = -50 + rand() % 50;
}
printf("\t----------RECTANGLE 3----------\n");
printf("\tTop left point is x = %d y = %d\n", r3.topLeft.x, r3.topLeft.y);
printf("\tBottom right point is x = %d y = %d\n", r3.botRight.x, r3.botRight.y);
printf("\tArea is %d\n\n", Area(r3));
if (Area(r1) >= Area(r2) && Area(r1) >= Area(r3))
printf("\tRECTANGLE 1 HAS A BIGGEST AREA --> %d\n", Area(r1));
if (Area(r2) >= Area(r1) && Area(r2) >= Area(r3))
printf("\tRECTANGLE 2 HAS A BIGGEST AREA --> %d\n", Area(r2));
if (Area(r3) >= Area(r1) && Area(r3) >= Area(r2))
printf("\tRECTANGLE 3 HAS A BIGGEST AREA --> %d\n", Area(r3));
}
Item 1:
There really is no need to use a point struct. The problem is simple enough to merely keep track to 2 values for x and 2 values for y. While we're at it, the area of each rectangle could be stored, too.
typedef struct {
int x0, x1, y0, y1, area;
} Rect;
Notice that there is no bias in the names x0 and x1. Attempting to control which coordinate pair is "top left" and which is "bottom right" is difficult. A rectangle has two horizonal edges (importantly they are not equal). Merely store the lower and higher values of y. Similarly, store only the "left & right" values of the vertical edges x... This makes life simple.
Item 2:
It's worthwhile, if possible, to think and to code without immediate concern for negative numbers.
const int wid = 101; // for -50 to +50
const int hgt = 101; // for -50 to +50
Item 3:
Generating 3 sets of values by copy/paste of code indicates that this should be done in a function called 3 times. (Imagine the next assignment is "do the same for 20 rectangles.")
Below includes two bonus "branchless" functions that return the minimum or maximum of two integer values.
int min( int x, int y ) { return y ^ ((x^y) & -(x<y)); }
int max( int x, int y ) { return y ^ ((x^y) & -(x>y)); }
void genRect( Rect *r ) {
int v0 = rand() % wid; // A random horizontal value (a vertical line)
int v1 = ( v0 + 1 + rand()%(wid-3) ) % wid; // A different horizontal value
r->x0 = min( v0, v1 ); // the lower of the two values
r->x1 = max( v0, v1 ); // and the higher
// do the same for horizontal edges (vertical boundaries)
v0 = rand() % hgt;
v1 = ( r->y0 + 1 + rand()%(hgt-3) ) % hgt;
r->y0 = min( v0, v1 );
r->y1 = max( v0, v1 );
// calc and store the area, too
r->area = (r->x1 - r->x0) * (r->y1 - r->y0);
}
Important to note is that the calculation of the second value for x and for y will never be the same as the first value. The OP code had the potential to generate a "left edge" at the right boundary, then enter an endless loop trying to generate a value that was always rejected.
As suggested in the other answer, it is now easy to qsort() the small array (big rectangles may contain smaller ones).
The search for one inside another is much simpler with comparing x0 against x0 and x1 against x1... (Likewise for the y dimension).
Because the code has been dealing with (0,0) to (100,100) inclusive, the output is where to tailor to suit the assignment.
void print( int n, Rect *r ) {
printf( "Rect %d: BotLft(%d,%d) TopRgt(%d, %d) Area %d\n",
n, r->x0 - 50, r->y0 - 50, r->x1 - 50, r->y1 - 50, r->area );
}
I leave it as an exercise for the reader to eliminate the arbitrary constants above.
Finally, it is a trivial exercise to determine if the xy boundaries of one smaller rectangle fall completely within the xy boundaries of a larger one. A single if() statement with 4 conditions would suffice.
PS: I completed the code and ran it a few times. It was only by increasing the number of candidate rectangles that luck would have it that a larger did contain a smaller. The sample size of only 3 rectangles will take a lot of iterations to, by chance, define one inside another...
First, you need an array of Rectangles and sort them by their area:
struct Rectangle rects[N];
//return:
//- negative value, if a < b
//- zero, if a == b
//- positive value, if a > b
int rect_cmp(const void *a, const void *b)
{
return Area(*((struct Rectangle*)a)) - Area(*((struct Rectangle*)b));
}
//use qsort: https://en.cppreference.com/w/c/algorithm/qsort
qsort(rects, N, sizeof(struct Rectangle), rect_cmp);
The array rects will now contain all the rectangles, sorted in ascending order, from lowest to highest area.
From now on, all you have to do is to iterate over the array and test if the largest rectangle encloses the following, subsequent rectangles.
The following code picks the largest rectangle and iterates over all subsequent rectangles to test if they are inside. Then pick the second largest and do the testing again, and so on, e.g.
for (int i=N-1; i >= 0; --i) { //current largest rectangle
for (int j=i-1; j >= 0; --j) { //test if the next rectangles in sequence are inside
if (contains(rects[i], rects[j])) {
//rect[j] inside rect[i]
} else {
//rect[j] not inside rect[i]
}
}
}
A possible outcome could be that the first rect neither contains the second and third rect but the second rect could contain the third one.
How would I uses pointers in a multidimensional array? In each direction how would I replace what I have done with pointer arithmetic? I have defined my ptr as *location. I think I need to make this change because I am getting segmentation faults when totalHops>400. Thus, explicitly changing x, y, z each time must be causing this error. Context: I am moving a particle in an L by L by L 3D space. I have a random number generator to determine whether the particle moves left, right, up, down, back or forth each time the particle randomly moves location. (Note I have designed the system to have periodic boundary conditions).
const int L = 10;
int N = L*L*L;
const int totalHops = 200;
int sites[L][L][L] = {};
int x = 0, y = 0, z = 0;
int tracker[N] = {};
int *location;
location = &sites[0][0][0];
for (int i = 1; i <= totalHops; i++) // the random walk //
{
int direction = randomInt(6); // six possible directions to move //
// along x //
if (direction == 0) { // move in negative direction //
x -= 1;
if (x == -1)
{
x = L-1;
}
}
if (direction == 1) { // move in positive direction //
x +=1;
if (x == L)
{
x = 0;
}
}
// along y //
if (direction == 2) { // move in negative direction //
y -= 1;
if (y == -1)
{
y = L-1;
}
}
if (direction == 3) { // move in positive direction //
y +=1;
if (y == L)
{
y = 0;
}
}
// along z //
if (direction == 4) { // move in negative direction //
z -= 1;
if (z == -1)
{
z = L-1;
}
}
if (direction == 5) { // move in positive direction //
z +=1;
if (z == L)
{
z = 0;
}
}
tracker[i] = sites[x][y][z]; }
Many thanks for your help in advance.
Keep in mind, that although C accommodates array notation such as 2D, 3D, ..., nD arrays to make working with them more natural from a human readability perspective. But in memory, arrays are actually created as a single block of contiguous memory. For example your array:
const int L = 10;
...
int sites[L][L][L] = {0}; //(using {0} is an idiomatic way to init. arrays to all 0
Is arranged in memory as 10*10*10 sequential sizeof(int) sections of memory, starting at the memory location pointed to by sites.
| | | | | | | | | ...| | | |
^ ^
sites + 0 sites + (10*10*10 - 1)*sizeof(int)
Because of this fact, pointer math becomes pretty straight forward:
*(sites + 0) is equivalent to sites[0][0][0]
*(sites + 1) is equivalent to sites[0][0][1]
*(sites + 2) is equivalent to sites[0][0][2]
...
*(sites + 10) is equivalent to sites[0][1][0]
...
*(sites + 100) is equivalent to sites[1][0][0]
...
*(sites + 998) is equivalent to sites[9][9][8]
*(sites + 999) is equivalent to sites[9][9][9]
The pattern between the pointer notation and array notation becomes very apparent, as the number added to the beginning of the array correlates with the arrangement of indexes in the array notation.
Based on this basic form, you can derive a way to use pointer math to represent multidimensional arrays, in your case then, using int *location; initialized to the beginning of sites can be used to track (or determine) what element of the 3D array is being looked at, or modified.
This could apply nicely to your specific problem in that tracking totalHops, and making decisions based on values outside the range of 0 - 9 in any direction for x,y,z may be more difficult than making decisions based on notation such as *(sites + 400) (per your description in OP).
So in conclusion to my segmentation fault, I have simply used the wrong variable in my tracker array. But nonetheless, as a fairly new programmer it was good to have thse conversations and thank you for all of your help! I am glad to have explored both the uses of indexing and pointers.
Array needed to be
int tracker[totalHops] = {};
recently i read this topic about generating mazes in c . see here https://www.algosome.com/articles/maze-generation-depth-first.html
and i want to write it in c . here is my code and it's not working right .
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
int check[5][5];
int v[5][5];
int border(int x , int y ){
if(x> -1 && x< 6 && y > -1 && y<6)
return 1;
else
return 0 ;
}
int wall[6][6][6][6];
void dfs ( int x , int y){
srand(time(NULL));
int s = 1/*rand() % 4 ;*/ ;
if(s=1 ){
if(border(x ,y-1)&& check[x][y-1]==0){
check[x][y]=1;
wall[x][y][x+1][y]=1;
dfs(x , y-1);
}
else
return ;
}
else if(s=2){
if(border(x+1 ,y)&&check[x+1][y]==0){
check[x][y]=1;
wall[x+1][y][x+1][y+1]=1;
dfs(x+1 , y);
}
else return ;
}
else if(s=3){
if(border(x ,y+1)&&check[x][y+1]==0){
check[x][y]=1;
wall[x][y+1][x+1][y+1]=1;
dfs(x , y+1);
}
else return ;
}
else if(s=0){
if(border(x-1 ,y)&&check[x-1][y]==0){
check[x][y]=1;
wall[x][y][x][y+1]=1;
dfs(x-1 , y);
}
else return ;
}
return ;
}
int main(){
dfs( 4, 4);
for(int i =0 ; i < 6 ; i++)
for (int j =0 ; j < 6 ; j++)
for ( int h =0 ; h <6 ; h++)
for (int k =0 ; k < 6 ; k ++)
printf("%d \n" , wall[i][j][h][k]);
return 0 ;
}
i invert my table to graph , and i want to show me the coordinates of my walls .
what's the problem ?
You have several errors – programming errors and logic errors – in your code:
When you distiguish between the directions the s=1 and so on should be s == 1. You want a comparison, not an assignment. (Your code is legal C, so there is no error.)
You call srand at the beginning of dfs, which you call recursively. This will make your single (commented) rand call always create the same random number. You should seed the pseudo random number generator only once at the beginning of main.
You can store the paths the way you do, but it is wasteful. There are only four possible paths from each cell, so you don't need an array that allows to create a path between (0,0) and (3,4), for example.
Your code would benefit from using constants or enumerated values instead of the hard-coded 5's and 6's. This will allow you to change the dimensions later easily.
But your principal error is in how you implement the algorithm. You pick one of the for directions at random, then test whether that direction leads to a valid unvisited cell. If so, you recurse. If not, you stop. This will create a single unbranched path through the cells. Note that if you start in a corner cell, you have already a 50% chance of stopping the recursion short.
But you want something else: You want a maze with many branches that leads to every cell in the maze. Therefore, when the first recursion returns, you must try to branch to other cells. The algorithm goes like this:
Make a list of all possible exits.
If there are possible exits:
Pick one exit, create a path to that exit and recurse.
Update the list of possible exits.
Note that you cannot re-use the old list of exits, because the recursion may have rendered some possible exits invalid by visiting the destination cells.
Below is code that creates a maze with the described algorithm. I've used two distinct arrays to describe horizontal and vertical paths:
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
enum {
W = 36, // width of maze
H = 25 // height of maze
};
enum {
North,
East,
South,
West,
NDir
};
char visited[H][W];
char horz[H][W - 1]; // horizontal E-W paths in the maze
char vert[H - 1][W]; // veritcal N-S paths in the maze
/*
* Fill dir with directions to unvisited cells, return count
*/
int adjacent(int dir[], int x, int y)
{
int ndir = 0;
if (y > 0 && visited[y - 1][x] == 0) dir[ndir++] = North;
if (x < W - 1 && visited[y][x + 1] == 0) dir[ndir++] = East;
if (y < H - 1 && visited[y + 1][x] == 0) dir[ndir++] = South;
if (x > 0 && visited[y][x - 1] == 0) dir[ndir++] = West;
return ndir;
}
/*
* Traverse cells depth first and create paths as you go
*/
void dfs(int x, int y)
{
int dir[NDir];
int ndir;
visited[y][x] = 1;
ndir = adjacent(dir, x, y);
while (ndir) {
int pick = rand() % ndir;
switch (dir[pick]) {
case North: vert[y - 1][x] = 1; dfs(x, y - 1); break;
case East: horz[y][x] = 1; dfs(x + 1, y); break;
case South: vert[y][x] = 1; dfs(x, y + 1); break;
case West: horz[y][x - 1] = 1; dfs(x - 1, y); break;
}
ndir = adjacent(dir, x, y);
}
}
/*
* Print a map of the maze
*/
void map(void)
{
int i, j;
for (i = 0; i < W; i++) {
putchar('_');
putchar('_');
}
putchar('\n');
for (j = 0; j < H; j++) {
putchar('|');
for (i = 0; i < W; i++) {
putchar(j < H - 1 && vert[j][i] ? ' ' : '_');
putchar(i < W - 1 && horz[j][i] ? '_' : '|');
}
putchar('\n');
}
}
int main()
{
srand(time(NULL));
dfs(0, 0);
map();
return 0;
}
You can test it here. If you replace the while in dsf with a simple if, you get more or less what you implemented. Note that this creates only a single, usually short path.
I need to make a spiral pattern made of stars '*' using nested for loops. I managed to make outter lines, now I don't know how to repeat smaller swirls in the same place.
What I should have:
*********
*
******* *
* * *
* *** * *
* * * *
* ***** *
* *
*********
Any help would be greatly appreciated.
After being thoroughly nerd-sniped, I came up with this:
#include <stdio.h>
void print_spiral(int size)
{
for (int y = 0; y < size; ++y)
{
for (int x = 0; x < size; ++x)
{
// reflect (x, y) to the top left quadrant as (a, b)
int a = x;
int b = y;
if (a >= size / 2) a = size - a - 1;
if (b >= size / 2) b = size - b - 1;
// calculate distance from center ring
int u = abs(a - size / 2);
int v = abs(b - size / 2);
int d = u > v ? u : v;
int L = size / 2;
if (size % 4 == 0) L--;
// fix the top-left-to-bottom-right diagonal
if (y == x + 1 && y <= L) d++;
printf((d + size / 2) % 2 == 0 ? "X" : " ");
}
printf("\n");
}
}
As others mentioned, it might be more intuitive to allocate an array representing the grid, and draw the spiral into the array (within which you can move freely), then print the array. But, this solution uses O(1) memory.
It could almost certainly be optimized and simplified a bit, but I'll "leave that as an exercise for the reader" as I've already spent too much time on this ;-)
Update
I'm not going to spend any more time on this, but I had an idea for a second attempt that might result in simpler code. If you check the output at increasingly large sizes, a pattern emerges:
Within each quadrant, the pattern is regular and can be easily coded. I think you would just have to carefully classify the (x, y) coordinates into one of the four quadrants and then apply the appropriate pattern.
The most sensible approach is to create a 2d array, then fill it with the * that you want.
Alternatively, you can try to come up with some "just in time" logic to avoid a buffer. This is more complicated.
I came up with an approach by thinking of the spiral as four different triangles that form a square. Here I have printed "a,b,c,d" for each of the four triangles to show what I mean:
aaaaaaaaaac
c
baaaaaac c
b c c
b baac c c
b b dd c c
b b c c
b dddddd c
b c
dddddddddd
There are two tricky parts to this. One is to align the diagonals correctly. Not so hard with with trial and error. The other tricky party is that not all squares divide into alternating lines the same way. You can see in the example above a square n=11, the left side is shifted by one. Perhaps there is a better solution, but this attempts to create alternating rows and columns.
n = 11;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
// top
if (j > i - 2 && j < n - i && i % 2 == (n&1)) printf("a");
// left
else if (j < i - 1 && j < n - i && j % 2 == (n & 1)) printf("b");
// right
else if (j > n - i -1&& j > i && j % 2 == ((n+1) & 1)) printf("c");
// bottom
else if (j < i + 1 && j > n - i - 1 && i % 2 == ((n + 1) & 1)) printf("d");
else printf(" ");
}
printf("\n");
}
I would recommend taking a look at the NCurses library. It contains many methods for moving the cursor in the terminal window, such as mvaddch() and curs_set().
Here is a document that contains everything you'd need to know on how to use NCurses.
However, if you don't want to use external libraries, then you could define a 2D array of ints or bools and then print a * where an index is 1 or true, respectively.
Example of the latter:
#include <stdbool.h> //You need to include this header file if you want to use 'bool's
...
//Using a 10x10 array for this example
bool stars[10][10] = { /* initialize the 2D array here */ };
...
//Get the length of a row
int rowLength = (sizeof stars[0]) / (sizeof stars[0][0]);
//Get the amount of rows
int rowAmount = (sizeof stars) / (sizeof stars[0]));
//Print the spiral using the array "stars"
for(int r = 0; r < rowAmount; r++){
for(int c = 0; c < rowLength; c++){
if(stars[r][c])
printf("*");
else
printf(" ");
}
printf("\n");
}
...
This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
I have a tic tac toe board that I'm working on for fun and I've come across a problem. Basically I generate the two x,y coordinates randomly and then run them through a while loop. If the coordinate position hasn't been marked, then it marks the spot. Else it'll continue running and generate a new pair of coordinates. This seems to work for the first four times that the function is called, but then any subsequent uses of the function cause it to spiral out of control. Hoping someone might be able to point me in the right direction as well as tell me if logic is incorrect somewhere. Constructive criticism is great.
Thanks in advance and here's the code for the X's move function (the O has almost the same code):
void Xmove(struct config *cp) {
int ran1, ran2;
srand((unsigned) time(NULL));
ran1 = rand() % 3;
ran2 = rand() % 3;
if(cp->grid[1][1] == ' ') {
cp->grid[1][1] = 'X';
printGrid(cp);
return;
}
while(ran1 == 1 && ran2 == 1) {
ran1 = (rand() % 3);
ran2 = (rand() % 3);
}
int looper = 1;
while (looper) {
if(cp->grid[ran1][ran2] != 'O' && cp->grid[ran1][ran2] != 'X') {
cp->grid[ran1][ran2] = 'X';
printGrid(cp);
looper = 0;
}
ran1 = (rand() % 3);
ran2 = (rand() % 3);
}
}
Back to the the original question about your infinite loop and your code, You cannot make the loop break solely on the assumption of finding an empty slot and filling it. You should not be even entering the loop if there are no slots left available. In fact, you should not even call either Move() function at all if there are no open tiles to fill, and honestly that should be maintained as a decrement-counter of the config struct.
But that aside, detection of open-tiles-remaining could be done a number of ways. One is presented below that requires no other modifications to the config table, etc. This you can easily do by building a list of viable tiles, and choosing a single random entry from that. The following replaces everything past your initial check for the center slot being open.
// build a table of open tiles
int ar[9] = {0};
int n=0,i=0,j=0;
for (i=0;i<3;++i)
for (j=0;j<3;++j)
if (cp->grid[i][j] != 'O' && cp->grid[i][j] != 'X')
ar[n++] = i*3+j;
// now you have the list of available tiles
// in `ar[0..n-1]`. choose ONE via `rand()`
if (n > 0)
{
n = ar[rand()%n];
cp->grid[n/3][n%3] = 'X'; // or 'O'
}
I'd eliminate the random looping altogether, instead every time I needed to make a move I would generate a random permutation of the digits 0-9 inclusive, and use that to walk the board, looking for where to put an X or an O as needed. Something like this:
int randperm[9], i = 0;
/* fill the array randperm with the numbers 0 through 8 in
* order
*/
for(i = 0; i != 9; i++)
randperm[i] = i;
/* Now mix the numbers up, so that the array ends up in
* some "random" order: that is, generate a permutation
* of the digits 0-8.
*/
for(i = 8; i > 0; i--)
{
int j = rand() % (i+1);
int temp = randperm[j];
randperm[j] = randperm[i];
randperm[i] = temp;
}
/* Now try to find a spot. We will use our randperm array to
* determine which cell to look at. Remember that the array
* contains the numbers 0-8 in some random order.
*/
for(i = 0; i != 9; i++)
{
/* We split a number from 0-8 into two numbers (x and y),
* each from 0 to 2:
*
* 0 -> 0 0, 1 -> 1 0, 2 -> 2 0,
* 3 -> 0 1, 4 -> 1 1, 5 -> 2 1,
* 6 -> 0 2, 7 -> 1 2, 8 -> 2 2
*
* notice that (y * 3) + x = randperm[i]
*/
int x = randperm[i] % 3;
int y = randperm[i] / 3;
/* check if the spot at grid[x][y] is available, if it is
* take it and return.
*/
}
/* If we get here there's no spot to put an X or an O... board is full */