Search code examples
cswitch-statementdo-while

C - Battleship, random ship placement


So, I have to make a user vs computer Battleship game on a 10x10 board for programming class. I have to make the computer place five ships of sizes 5, 4, 3, 3 and 2 randomly.

What I did, is that i generated two random numbers between 0 and 9 as my x and y coordinates, then a third number to decide in which direction the ship will be placed. I then used a switch statement to check if there was enough space on the board to place the ship in the first place, and if there is, to modify the board array (well, that's what it was supposed to do anyway).

    int main(void)
{   int x,y, bato[5]={5,4,3,3,2}, NbCases=17, countShip, dir, lenShip, countCaseEmpt, countLenShip, nbCaseOk, countModCase,i, dirTest;
    time_t t;
    
    srand(time(&t));
    // gestir(plato a, int * bato, int x, int y)
    
    // plato coord={{5,3,2,2,2},{5,3},{5,3},{5,3},{5},{0},{1,1}};
    // plato is a custom data type defined as "int plato[10][10]"
    plato coord={0}; //plateau vide
    i=0;
    
    for (countShip=5 ; countShip>0 ; countShip--)
    {
        do{
        i++;
        printf("%d\n",i); //counter used to check if the do while loop worked at all
            
            nbCaseOk=0;
            dirTest=0;
        
            do {x=abs(rand())%10; y=abs(rand())%10;} while (coord[y][x]!=0);  //start coordinates selection
        
            dir = rand()%4;     //direction selection
        
            switch (countShip){             //ship lenght determination
                case 0: lenShip=2; break; 
                case 1: lenShip=3; break; 
                case 2: lenShip=3; break; 
                case 3: lenShip=4; break; 
                case 4: lenShip=5; break;}
        
        
            switch (dir){                   //empty case checker and square modifier
                case 0: //right
                {
                    if (x+lenShip-1<10)
                        for (countLenShip=1 ; countLenShip<lenShip ; countLenShip++)
                            if (coord[y][x+countLenShip]==0) nbCaseOk+=1;
                    
                    if (nbCaseOk==lenShip-1) {dirTest=1;
                        for (countModCase=0 ; countModCase<lenShip ; countModCase++)
                            coord[y][x+countModCase]=countShip; break;}}
                        
                case 1: //up
                {   
                    if (y+lenShip-1<10)
                        for (countLenShip=1 ; countLenShip<lenShip ; countLenShip++)
                            if (coord[y+countLenShip][x]==0) nbCaseOk+=1;
                    
                    if (nbCaseOk==lenShip-1) {dirTest=1;
                        for (countModCase=0 ; countModCase<lenShip ; countModCase++)
                            coord[y+countModCase][x]=countShip; break;}}
                        
                case 2: //left
                {
                    if (x-lenShip+1>=0)
                        for (countLenShip=1 ; countLenShip<lenShip ; countLenShip++)
                            if (coord[y][x-countLenShip]==0) nbCaseOk+=1;
                    
                    if (nbCaseOk==lenShip-1) {dirTest=1;
                        for (countModCase=0 ; countModCase<lenShip ; countModCase++)
                            coord[y][x-countModCase]=countShip; break;}}
                        
                case 3: //down
                {
                    if (y-lenShip+1>=0)
                        for (countLenShip=1 ; countLenShip<lenShip ; countLenShip++)
                            if (coord[y-countLenShip][x]==0) nbCaseOk+=1;
                    
                    if (nbCaseOk==lenShip-1) {dirTest=1;
                        for (countModCase=0 ; countModCase<lenShip ; countModCase++)
                            coord[y-countModCase][x]=countShip; break;}}
        }} while (dirTest==0);
        
        
    }
    
    aff(coord);
    
    while (NbCases>0)
    {
        printf("Rentrer une coordonnee x, puis une coordonnee y, comprises entre 0 et 9:"); //"enter a coordinate between 0 and 9 for x, then another one for y:
        scanf("%d",&x); scanf("%d",&y);
        
        NbCases+=gestir(coord, bato, x, y);
        aff(coord);
    }
    
    printf("état bateau: %d\n nombre cases: %d",coord[0][0], NbCases); //ship state and number of empty squares         
return 0;
}

My problem is that I'm getting an infinite loop. I'm pretty sure the mistake is somewhere in my switch statement. I used a debugger to see what is the thing that is causing the problem, and I noticed that the 2D array (coord) isn't modified while going through the swotch statement even if there is plenty of space for the ship to be placed. I set the condition of the do while loop to (dirTest==0), but even though dirTest is clearly equal to 1 at the end of the switch statement the the loop doesn't end.


Solution

  • Your formatting isn't helping; please try to adopt a more conventional style. However, I can see several problems.

    • The break statements inside the switch (dir) block are only reached when if (nbCaseOk==lenShip-1) evaluates as true. You are therefore liable to go ploughing through every part of this code when dir == 0.

    • for (countShip=5 ; countShip>0 ; countShip--) is OK, but unless you have a good reason to count backwards, use for (countShip=0; countShip<5 ; countShip++) instead. Anyway, countShip will have values of 5, 4, 3, 2 and 1 in the code you wrote. Not 4, 3, 2, 1, 0 as expected by the switch (countShip) code block. I'm not sure what's going on with nbCaseOk in your code, but perhaps your loop isn't exiting because lenShip is never equal to 2?

    • abs(rand())%10 is redundant. Just rand()%10 is fine.

    • On a more general note; you are repeating a lot of code here. Try handling all the dir cases with the same code (e.g., by modifying two variables dx and dy).