HiveBrain v1.2.0
Get Started
← Back to all entries
patterncModerate

Battleship game in C

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
gamebattleshipstackoverflow

Problem

Goal: Create a simple battleship game to test what I've learned so far.

```
#include
#include
#include

void buff_clr(void)
{
char junk;
do{
junk=getchar();
}while(junk!='\n');
}
struct coord
{
int y;
int x;

}coords;

int randgen(int **ships_ptr,int n)
{
int i,j,count=0;
srand((unsigned)time(NULL));
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
ships_ptr[i][j]=rand()%2;
if(ships_ptr[i][j]==1)
{
count++;
}
}
}
return count;
}
void draw_gui(char **pseudo_gui_ptr,int n)
{
int i,j;

pseudo_gui_ptr[0][0]=' ';
for(i=1;i<(n+1);i++)
{
pseudo_gui_ptr[0][i]=i+48;
pseudo_gui_ptr[i][0]=i+48;
}

for(i=1;i<(n+1);i++)
{
for(j=1;j<(n+1);j++)
{
pseudo_gui_ptr[i][j]='+';
}
}
}
void battle(int ships_ptr, char pseudo_gui_ptr,int n, struct coord x,int count,int miss)
{

int i,j;

for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
if(x.x-1 == i && x.y-1 == j)
{
if(ships_ptr[i][j]==1)
{
if(pseudo_gui_ptr[i+1][j+1]=='O')
{
printf("\nYou've already uncovered this field!\n");
break;
}
printf("\nHit!\n");
pseudo_gui_ptr[i+1][j+1]='O';
(*count)--;
}
else
{
if(pseudo_gui_ptr[i+1][j+1]=='X')
{
printf("\nYou've already uncovered this field!\n\n");
break;
}
printf("\nMiss!\n");
pseudo_gui_ptr[i+1][j+1]='X';
(*miss)++;

Solution

#include 
#include 
#include 

void buff_clr(void)
{
    char junk;
    do{
        junk=getchar();
    }while(junk!='\n');
}

struct coord
{
    int y;
    int x;

}coords;

int randgen(int **ships_ptr,int n)


randgen tells me that I'm doing some random generation. I'd include something about map in the title.

{
    int i,j,count=0;
    srand((unsigned)time(NULL));


I wouldn't put this here. You should call this once per program, and you might generate multiple maps per program.

for(i=0;i<n;i++)
    {
        for(j=0;j<n;j++)
        {
            ships_ptr[i][j]=rand()%2;
            if(ships_ptr[i][j]==1)
            {
                count++;
            }
        }
    }
    return count;
}
void draw_gui(char **pseudo_gui_ptr,int n)
{
    int i,j;

    pseudo_gui_ptr[0][0]=' ';
    for(i=1;i<(n+1);i++)
    {
        pseudo_gui_ptr[0][i]=i+48;
        pseudo_gui_ptr[i][0]=i+48;


Use '0' instead of 48 to make it clearer what you are doing

}

    for(i=1;i<(n+1);i++)


You don't need the parens around (n+1)

{
        for(j=1;j<(n+1);j++)
        {
            pseudo_gui_ptr[i][j]='+';
        }
    }
}
void battle(int **ships_ptr, char **pseudo_gui_ptr,int n, struct coord x,int* count,int* miss)


That's getting to be a rather lot of parameters. I'd put everything inside a Game or Map struct. That way you just pass one pointer, and the everything else comes as part of that.

{

    int i,j;

     for(i=0;i<n;i++)
        {
            for(j=0;j<n;j++)
            {
                if(x.x-1 == i && x.y-1 == j)
                {


What are you doing? You don't want to do anything multiple times, so you shouldn't be using a loop. You know exactly what i and j will be so just calculate those values.

if(ships_ptr[i][j]==1)
                    {
                        if(pseudo_gui_ptr[i+1][j+1]=='O')


Reading back the GUI is generally not helpful. What if the GUI changes? Instead, I'd have a struct Tile to hold the map. Inside would be a ship and uncovered booleans. That would make things a bit simpler

{
                            printf("\nYou've already uncovered this field!\n");
                            break;
                        }
                        printf("\nHit!\n");
                        pseudo_gui_ptr[i+1][j+1]='O';
                        (*count)--;
                    }
                    else
                    {
                        if(pseudo_gui_ptr[i+1][j+1]=='X')
                        {
                            printf("\nYou've already uncovered this field!\n\n");
                            break;
                        }
                        printf("\nMiss!\n");
                        pseudo_gui_ptr[i+1][j+1]='X';
                        (*miss)++;
                    }

                }
            }
        }

}
void result(char **pseudo_gui_ptr,int n)
{
    int i,j;

    for(i=0;i<(n+1);i++)
    {
        for(j=0;j<(n+1);j++)
        {
            printf("%6c",pseudo_gui_ptr[i][j]);
        }
        printf("\n\n");
    }


I'd get rid of pseudo_gui_ptr and regenerate the output each time based on the Tile data.

}
int main(){

   int **ships;
   char **pseudo_gui;
   int i,j;
   int n;
   char switch_size,switch_difficulty;
   int difficulty=0;
   int shipcount=0;
   int x_count=0;

   printf("\t\t\tSink the ships v0.1b");

   printf("\nChoose size(S,M,L):");
   scanf("%c",&switch_size);


switch_size? Name it after what it means, not the control structure you are going to hand it to.

buff_clr();

      switch(switch_size)
   {
       case 's':
       case 'S':n=3;break;
       case 'm':
       case 'M':n=5;break;
       case 'l':
       case 'L':n=8;break;
       default:printf("\nYou've choosen poorly!");


:P

getch();
               exit(EXIT_FAILURE);
   }

   printf("\nChoose difficulty(E,H):");
   scanf("%c",&switch_difficulty);
   buff_clr();

   switch(switch_difficulty)
   {
       case 'e':
       case 'E':difficulty=(n*2)-2;break;
       case 'h':
       case 'H':difficulty=(n/2);break;
       default:printf("\nYou've choosen poorly!");
               getch();
               exit(EXIT_FAILURE);
   }

   ships=(int**)malloc(n*sizeof(int*));

   for(i=0;i<n;i++)
   {
       ships[i]=(int*)malloc(n*sizeof(int));
   }

   pseudo_gui=(char**)malloc((n+1)*sizeof(char*));

   for(i=0;i<(n+1);i++)
   {
       pseudo_gui[i]=(char*)malloc((n+1)*sizeof(char));
   }

   shipcount=randgen(ships,n);

   printf("\n\nNumber of ships to be sunk:%d",shipcount);
   printf("\nNumber of misses allowed: %d\n\n",difficulty);

   draw_gui(pseudo_gui,n);
   result(pseudo_gui,n);

   while(shipcount!=0 && x_count!=difficulty)
   {

   printf("\nEnter coordinates (x,y):");
   scanf("%d,%d",&coords.x,&coords.y);
   buff_clr();


Make you indent consistently!

```
system("cls");

battle(ships,pseudo_gui,n,coords,&shipcount,&x_count);
result(pseudo_gui,n);

printf("Number of

Code Snippets

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

void buff_clr(void)
{
    char junk;
    do{
        junk=getchar();
    }while(junk!='\n');
}

struct coord
{
    int y;
    int x;

}coords;

int randgen(int **ships_ptr,int n)
{
    int i,j,count=0;
    srand((unsigned)time(NULL));
for(i=0;i<n;i++)
    {
        for(j=0;j<n;j++)
        {
            ships_ptr[i][j]=rand()%2;
            if(ships_ptr[i][j]==1)
            {
                count++;
            }
        }
    }
    return count;
}
void draw_gui(char **pseudo_gui_ptr,int n)
{
    int i,j;

    pseudo_gui_ptr[0][0]=' ';
    for(i=1;i<(n+1);i++)
    {
        pseudo_gui_ptr[0][i]=i+48;
        pseudo_gui_ptr[i][0]=i+48;
}

    for(i=1;i<(n+1);i++)
{
        for(j=1;j<(n+1);j++)
        {
            pseudo_gui_ptr[i][j]='+';
        }
    }
}
void battle(int **ships_ptr, char **pseudo_gui_ptr,int n, struct coord x,int* count,int* miss)

Context

StackExchange Code Review Q#8294, answer score: 11

Revisions (0)

No revisions yet.