0

I am trying to make a colonization type game, where there are two teams which have soldiers randomly placed on a map, each soldier fires a missile somewhere on the map randomly.
I am having trouble placing the soldiers though. The issue is that instead of displaying the correct amount of soldiers in the right locations, they always end up filling a row instead. For example I would want teams(2,3,4,4) to return something like:

A 0 0 0
0 A B 0
B 0 0 0
0 0 0 B

But instead I am getting:

65 65 65 65
0 0 0 0
66 66 66 66
66 66 66 66

I am unsure if I can make this show up as A and B, so 65 and 66 is still ok, but there are too many. Here is some snippets of my code (I am printing the array a lot to see if it messes up somewhere)

Code to populate soldiers:

//declare the arrays
   InArray = calloc(row * col, sizeof(char));
    OutArray;

void teams(int teamAsoldiers, int teamBsoldiers, int mapRows, int mapCols){
  srand(time(0));
  const char teams[2] = {'A', 'B'};
  int maxTeamSoldiers = teamAsoldiers + teamBsoldiers;

  //Place team soldiers
  for(int j = 0; j < 2; j++){
    for(int i = 0; i < maxTeamSoldiers; i++){
      int location = ((rand() % (mapRows * mapCols)) );
      //read the elements from the file into the array
      ReadFromBinFile(sFileName,&OutArray,&nElements);
      //binary file stuff
      if(OutArray[location] == 0){ //if current is empty
        InArray[location] = teams[j];
       //write the array into the file
       WriteToBinFile(sFileName,InArray,mapSize);
       PrintArray(InArray,row,col);
        printf("-------------------\n");
      }else{
        i--;
      }
    }
  }
}

Code for reading/writing to binary file and printing the array:

//-----------------------------------------
// Write the content of an array into a bin file
//-----------------------------------------
int WriteToBinFile(char * sFileName, char * bArray, int nSize)
{
  FILE * pFile = NULL;
  if ((pFile = fopen(sFileName,"wb+"))==NULL)
  {
    printf("Error in creating the file:%s\n",sFileName);
    return -1;
  }
  else
  {
    
fwrite(bArray,sizeof(char),nSize,pFile);

    fclose(pFile);

    return 0;
  } 
}

//-----------------------------------------
// Read the content of a bin file into an array
//-----------------------------------------
int ReadFromBinFile(char * sFileName, char ** bArray, int * nSize)
{
  FILE * pFile = NULL;
  if ((pFile = fopen(sFileName,"rb+"))==NULL)
  {
    printf("Error in opening the file:%s\n",sFileName);
    return -1;
  }
  else
  {
    //calculate the size of the file
      
    //position the file pointer to the end of the file
    fseek(pFile,0,SEEK_END);
    //get the size of the file in bytes
    *nSize = ftell(pFile);

    //allocate the space for the array
    *bArray = (char *)malloc(*nSize*sizeof(char));
    fseek(pFile,0,SEEK_SET);

    //second solution reading all at once (fast)
    fread(*bArray,sizeof(char),*nSize,pFile);

    fclose(pFile);

    return 0;
  }
}


//-----------------------------------------
// print the content of an array
//-----------------------------------------
//this way it prints the array with proper visual of rows and colums
int PrintArray(char * bArray, int row, int col){
  for(int i=0;i<row;i++){
    for(int j=0;j<col;j++){
      printf("%d ",bArray[i]);
    }
    printf("\n");
  }     

  return 0;
}

Roberto Caboni
  • 7,252
  • 10
  • 25
  • 39
  • Where is the incorrect output that you posted coming from? Did you get it from the file written by `WriteToBinFile`? Or was it printed by the function `PrintArray` (whose definition you are not showing)? – Andreas Wenzel Feb 19 '22 at 21:25
  • It is from PrintArray (which I will now add) but the binfile also is incorrect, as it shows: 00 41 42 41 41 00 42 00 42 42 00 00 41 00 00 00 |.ABAA.B.BB..A...| – Psycho Bunnies Feb 19 '22 at 21:32
  • 1
    If you want `PrintArray` to print `A` instead of `65`, then you should change `"%d "` to `"%c "`. Also, note that the number `41` in the file is just the hexadecimal representation for the decimal number `65` and the character `A`. – Andreas Wenzel Feb 19 '22 at 21:58
  • @AndreasWenzel Thank you for letting me know, that is very helpful. I am mainly having an issue with the layout however. – Psycho Bunnies Feb 19 '22 at 22:01
  • 1
    The `Read/WriteFromBinFile` part is not relevant to the issue and you should have removed it from the question. – Roberto Caboni Feb 19 '22 at 22:09
  • Questions seeking debugging help should generally provide a [mre] of the problem, which includes a function `main` and all `#include` directives. Have you tried to create such an example only using the functions `teams`, `PrintArray` and a function `main` which allocates memory for the map (and maybe also initializes it)? Is the problem still reproducible if you do that? – Andreas Wenzel Feb 19 '22 at 22:11
  • It is very hard to guess what your program is doing, because you are 1. not showing the file contents, and 2. not showing us the way you are calling `teams`, and 3. not showing us the initial content of `OutArray`, and 4. not showing us the value of `nElements`, and 5. not showing us the value of `mapSize`. All of these problems would be solved if you provided a [mre] as described in my previous comment. – Andreas Wenzel Feb 19 '22 at 22:23
  • Why are you reading from and writing to a file, for every soldier that you want to place? It would be normal to read the entire map from file into memory (i.e. "load" the map) once, then do all the necessary modifications such as placing random soldiers, and then write the entire map from memory to the file (i.e. "save" the map) once. Doing a "load" and a "save" operation for every single soldier placed seems excessive. – Andreas Wenzel Feb 19 '22 at 22:30
  • If the map initially does not contain any data at all, but consists only of `0`'s, then it should not be necessary to do any "load" operation at all. It should only be necessary to do one "save" operation after the map has been populated. – Andreas Wenzel Feb 19 '22 at 22:34
  • 1
    Side note: It is generally better to call `srand` at the start of `main`, instead of in the function which calls `rand`. This can be important if you have several functions which call `rand`. You may want to read this: [srand() — why call it only once?](https://stackoverflow.com/q/7343833/12149471) – Andreas Wenzel Feb 19 '22 at 23:48

1 Answers1

1

I start admitting I don't know why you get the soldier placed in rows, but there are several issues I would solve before worrying about it.
The issues are all in the teams functions, in the loop where you place the soldiers (I'll omit the file I/O part, that is not relevant):

for(int j = 0; j < 2; j++){
  for(int i = 0; i < maxTeamSoldiers; i++){
    int location = ((rand() % (mapRows * mapCols)) );
    
    /* ... omissis... */

    if(OutArray[location] == 0){
      InArray[location] = teams[j];
      PrintArray(InArray,row,col);
      printf("-------------------\n");
    }else{
      i--;
    }
  }
}

The main problem is that in the inner loop, where you are supposed to place the soldiers for each team, you instead try to place maxTeamSoldiers soldiers. So, considering the outer loop, you do it twice placing in total maxTeamSoldiers*2 soldiers.

Your "trick" to decrease the loop counter whenever you find an occupied location is not a good idea, as it results in unmanteinable code. Use a while loop, instead.

The following snippet, though it might be optimized (I used your same approach), should work:

void teams(int teamAsoldiers, int teamBsoldiers, int mapRows, int mapCols){
  const char teams[2] = {'A', 'B'};
  int nrOfSoldiers[] = {teamAsoldiers, teamBsoldiers};

  if(teamAsoldiers+teamBsoldiers > mapRows * mapCols)
  {
    printf ("Too many soldiers!\n");
    return;
  }

  srand(time(0));

  //Place team soldiers
  for(int j = 0; j < 2; j++){
    int placed = 0;
    while(placed < nrOfSoldiers[j]){
      int location = ((rand() % (mapRows * mapCols)) );
        
      if(OutArray[location] == 0){ //if current is empty
        OutArray[location] = teams[j];
        placed++;
        PrintArray(OutArray,row,col);
        printf("------------\n");
      }
    }
  }
}

I used only OutArray and added a little check on the parameters to avoid your function looping forever.

Roberto Caboni
  • 7,252
  • 10
  • 25
  • 39