Solved

battleship-like C Program

Posted on 2004-08-11
32
5,826 Views
Last Modified: 2008-01-09
(500 pts)
The first part explains the program and what it should do(this is just the first part). The second part is my sourcecode.It compiles correctly,btw.I know it has something to do with my damn loops! Please help! also, i added fflush(stdin) and I think it's working correctly, please verify.
Instructions:
Part 1.1: Write a function with the following prototype:

void clearBoard (int rows, int columns, int * boardPtr);

The function should write a zero value to each element in the passed 2-D array.

Part 1.2: Write a function with the following prototype:

void showBoard (int rows, int columns, int * boardPtr);

The function should display the array. If the value of a board location is 0 to 9, print that value, otherwise print "x". Example:

int board [3][3] = { {0, 0, 1}, {99, -2, 7}, {-1, 6, 0} };
/* ... */
showBoard(3, 3, board);
/* ... */

Should display:

0 0 1
x x 7
x 6 0

Part 1.3: Write a function that reads board coordinates, with the following prototype:

int getCoords (int maxRow, int maxCol, int * row, int * col);

The function should read a character followed by a number, and convert these into a row, column pair that is output through the row, col parameters. The function should return 0 if an invalid entry was made, or a 1 if a valid entry was made. Example:

...
printf("Enter coordinates : ");
while (0 == getCoords(3, 3, &myRow, &myCol))
{
   printf("Bad coordinates!\nEnter coordinates : ");
}
printf("myRow = %d, myCol = %d\n", myRow, myCol);
...

Example output:

Enter coordinates: yy zz
Bad coordinates!
Enter coordinates : 0 0
Bad coordinates!
Enter coordinates : A10
Bad coordinates!
Enter coordinates : A 9
Bad coordinates!
Enter coordinates : B 2
myRow = 1, myCol = 1

The following chart might help illustrate how this coordinate system works:

    1     2     3     4     ...
A (0,0) (0,1) (0,2) (0,3) ...
B (1,0) (1,1) (1,2) (1,3) ...
C (2,0) (2,1) (2,2) (2,3) ...
D (3,0) (3,1) (3,2) (3,3) ...
...

Where the output row and column numbers are given as (row, column).

Part 1.4: Write a function with the following prototype:

void paintSpace (int rows, int cols, int * boardPtr);

The function should read a "Battleship" coordinate using the getCoords() and an integer value from the console. The integer value should be written to the board array corresponding to the input coordinate.

Part 1.5: Write a menu loop (in main(), for now) that asks the following:

************************************************************
0 - Clear the board.
1 - Paint a space.
2 - Show board.
3 - Play game.
4 - Quit
************************************************************
Your choice? _

If they select 0, zero all the values of the board. If they select 1, ask for coordinates and an integer value to write to the board. Then write that value to the board. If they select 2, display the board using the showBoard() function. If they select 3, tell the user that the game isn't ready yet. If they select 4, exit the program. Otherwise, tell the user their input was invalid. Use a 10x10 board

My SourceCode:
#include<stdio.h>
#include<stdlib.h>

void clearBoard(int rows, int columns, int * boardPtr);
void showBoard(int rows, int columns, int * boardPtr);
int getCoords(int maxRow, int maxCol, int *row, int *col);
void paintSpace(int rows, int cols, int * boardPtr);

void clearBoard(int rows, int columns, int * boardPtr)
{
int i;

for(i=0; i < rows * columns; i++)
   {
      *(boardPtr+i) = 0; //initialize value to 0
   }
} // End of clearBoard function.


void showBoard(int rows, int columns, int * boardPtr)
{
int i;
for(i=0; i < rows * columns; i++)
   {
   // Print newline character is row is finished.
   // If i modulus the columns is 0, then you've reached
   // the end of a row and need to print a newline.
   if(i % columns == 0)
      {
      printf("\n");
      }
   
   if ((*(boardPtr+i) >= 0) && (*(boardPtr+i) <= 9))
      {
      printf("%d ", *(boardPtr+i));
      }
   else
      {
      printf("x ");
      }
   }
}

int getCoords(int maxRow, int maxCol, int *row, int *col)
{
char myRowchar;
int myCol=0;
int myRownum=0;

scanf("%c %d", &myRowchar, &myCol);
myRownum = (int)myRowchar;

if(myRownum >= 97)
   {
   myRownum = myRownum - 97;
   }
else if((myRownum >=65) && (myRownum <=90))
   {
   myRownum = myRownum - 65;
   }  

if (myRownum > maxRow)
   {
   *row = 0;
   *col = 0;
   return 0;
   }
else if (myCol > maxCol)
   {
   *row = 0;
   *col = 0;
   return 0;
   }
else
   {
   *row = myRownum;
   *col = myCol - 1; // Need to compensate because array starts at 0.
   }
return 1;
}

void paintSpace(int rows, int cols, int * boardPtr)
{
int myRow = 0, myCol = 0, value = 0;

printf("Enter coordinates :");

while( 0 == getCoords(rows, cols, &myRow, &myCol))
{
   printf("Bad coordinates!\nEnter coordinates: ");
}
/*printf("myRow = %d, myCol = %d\n", myRow, myCol);*/

printf("Enter a value: ");
scanf("%d", &value);
value = *(boardPtr + (myRow*cols) + myCol) ;

}

int main()
{
int choice;
int rows = 10;
int columns = 10;
int boardPtr[rows][columns];

while(1)
{
   printf("\n*************************************************\n");
   printf("0 - Clear the board.\n");
   printf("1 - Paint a space.\n");
   printf("2 - Show board.\n");
   printf("3 - Play game.\n");
   printf("4 - Quit.\n");
   printf("*************************************************\n");
   printf("Your choice? _");
   scanf("%d", &choice);

   switch(choice)
      {
      case 0:
         clearBoard(rows, columns, (int *)boardPtr);
         break;

      case 1:
       fflush(stdin);
 paintSpace(rows, columns, (int *)boardPtr);
         break;

      case 2:
         showBoard(rows, columns, (int *)boardPtr);
         break;

      case 3:
         printf("The game isn't ready yet.\n");
         break;

      case 4:
         exit(0);

      default:
         printf("Your input was invalid.\n");
         break;
      } //End of Switch statement
   } //End of while loop
 return 0;
} //End of Program
0
Comment
Question by:simmah
  • 16
  • 9
  • 4
  • +1
32 Comments
 

Author Comment

by:simmah
ID: 11779457
can someone PLEASE PLEASE HELP ME?????
0
 
LVL 22

Assisted Solution

by:grg99
grg99 earned 150 total points
ID: 11779826
So what's the problem?    The code looks reasonably decent.  A few hints as to what's acting up might help.

0
 
LVL 22

Assisted Solution

by:grg99
grg99 earned 150 total points
ID: 11779847
You're not setting the value in paintspace(), but you ar reading it??:

value = *(boardPtr + (myRow*cols) + myCol) ;

maybe should be the other way around:

*(boardPtr + (myRow*cols) + myCol)  = value;




0
 

Author Comment

by:simmah
ID: 11779958
I just changed it to what you said and it still isnt working. basically, this is what is happening:
1. i select 'clear board' and hit enter
2.i select 2 to 'paint a space' and put in the coordinates. it correctly 'paints a space' in the background(verified it). but, it then displays the menu again(correct) followed by "You choice? _Enter coordinates :Enter a value:" all in one line! that's my issue here. what it should do is bring up the menu and give me the option of choosing 1-4 again.
Please assist.
0
 
LVL 22

Assisted Solution

by:grg99
grg99 earned 150 total points
ID: 11780104
You need to explicitly read the <enter> key, maybe with a "%d\n" format spec.
Otherwise the <enter> key is going to be read by the next scanf().

0
 

Author Comment

by:simmah
ID: 11780160
so wherever there is "scanf(...%d) add a '\n' by it?
0
 

Author Comment

by:simmah
ID: 11780172
can you please be a bit more specific as to where?
thank you.
0
 

Author Comment

by:simmah
ID: 11780212
I might be confusing you. I think the program does what it's supposed to, but it's just added extra wording. here is the input/output format(i havent begun working on choice 3 which is the last one, so dont worry about that) If you can, please compile/run it and you'll know exactly what im talking about.

************************************************************
0 - Clear the board.
1 - Paint a space.
2 - Show board.
3 - Play game.
4 - Quit
************************************************************
Your choice? 1
Enter coordinates: a0
Bad coordinates!
Enter coordinates: xx yy
Bad coordinates!
Enter coordinates: A -1
Bad coordinates!
Enter coordinates: A1
Enter value to be written at (0, 0): 1
************************************************************
0 - Clear the board.
1 - Paint a space.
2 - Show board.
3 - Play game.
4 - Quit
************************************************************
Your choice? 1
Enter coordinates: j 11
Bad coordinates!
Enter coordinates: j 10
Enter value to be written at (9, 9): 2
************************************************************
0 - Clear the board.
1 - Paint a space.
2 - Show board.
3 - Play game.
4 - Quit
************************************************************
Your choice? 1
Enter coordinates: j9
Enter value to be written at (9, 8): 2
************************************************************
0 - Clear the board.
1 - Paint a space.
2 - Show board.
3 - Play game.
4 - Quit
************************************************************
Your choice? 1
Enter coordinates: F 5
Enter value to be written at (5, 4): 3
************************************************************
0 - Clear the board.
1 - Paint a space.
2 - Show board.
3 - Play game.
4 - Quit
************************************************************
Your choice? 1
Enter coordinates: g6
Enter value to be written at (6, 5): 3
************************************************************
0 - Clear the board.
1 - Paint a space.
2 - Show board.
3 - Play game.
4 - Quit
************************************************************
Your choice? 1
Enter coordinates: H7
Enter value to be written at (7, 6): 3
************************************************************
0 - Clear the board.
1 - Paint a space.
2 - Show board.
3 - Play game.
4 - Quit
************************************************************
Your choice? 2
1 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 3 0 0 0 0 0
0 0 0 0 0 3 0 0 0 0
0 0 0 0 0 0 3 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 2 2
************************************************************
0 - Clear the board.
1 - Paint a space.
2 - Show board.
3 - Play game.
4 - Quit
************************************************************
Your choice? 3
************************************************************
0
 
LVL 23

Assisted Solution

by:Mysidia
Mysidia earned 150 total points
ID: 11780225
[Not to nit pick, but, for any production use scanf would probably not be ideal, because it has limited flexibility.. it doesn't give the program much information about the actual input (like where the user hit enter)... if a scanf fails, you don't get to know why exactly, and if  you use just plain %s... well, you now have a buffer overflow possibility.


In any event, one thing that stands out is that you're using scanf, but not checking if it succeeded or not.

Try instead of   scanf("%d", &choice);

if (scanf("%d", &choice) < 1)
{
    continue;
}

sscanf / scanf / vscanf / etc.  return the number of arguments matched.

if Scanf returns 0 or -1, then "choice" has not been set or there was a format error.
If it returns one then one argument was set.

I think the main issue here is that the input is not being consumed at the place you expect.

Look at...  scanf("%c %d", &myRowchar, &myCol);

This looks like it may be a problem to me... the thing is that %c will happily consume a white space character
as input,  including a carriage return.

Then the piece that's left (the letter) will remain in the input and not be consumed by the %d later, that scanf
will fail and scan nothing, since you tried to scan a letter with %d.

I suggest something more like

        if (scanf("%[a-dA-D] %d", myRowStr, &myCol) < 2)
             /* format error handling code */
        else
        switch(toupper(*myRowStr)) {
              .... code here ...
        }

By the way, it makes no sense to flush an input string:  the scanf call will block until the actual input
from stdin is available.  (Flushing output streams makes sense though)
0
 
LVL 23

Assisted Solution

by:Mysidia
Mysidia earned 150 total points
ID: 11780245
Wait... sorry.. not this
   if (scanf("%d", &choice) < 1)
   {
    continue;
   }

but

   if (scanf("%d", &choice) < 1)
   {
        printf("Scanf: Format error");

        exit(0);        
   }

continue would of course just repeat that scanf you have

You could also eat space before doing scanf with %c as input, i.e.

char letter = 1;

while (letter != EOF)
{
    letter = getchar();
    if (letter == EOF || isspace(letter))
        continue;
    ungetc(letter, stdin);
    break;
}



0
 

Author Comment

by:simmah
ID: 11780329
I put this:
 if (scanf("%d", &choice) < 1)
   {
        printf("Scanf: Format error");

        exit(0);        
   }
next to my scanf()s and it doesnt run properly. it just stalls and i keep hitting enter after my input.
I also used the other suggestions you gave. Maybe im just not putting it in the right place.
0
 

Author Comment

by:simmah
ID: 11780334
it's
correctly letting me type in the value of the coordinate area, but it's re-
looping the entire menu and then some. so, instead of giving me:
************************************************************
0 - Clear the board.
1 - Paint a space.
2 - Show board.
3 - Play game.
4 - Quit
************************************************************
Your choice? 1 (input)
Enter coordinates: F 5 (input)
Enter a value: 3 (input)

IT GIVES ME:
************************************************************
0 - Clear the board.
1 - Paint a space.
2 - Show board.
3 - Play game.
4 - Quit
************************************************************
Your choice? 1 (my input)
Enter coordinates: F 5 (my input)
Enter a value:
************************************************************
0 - Clear the board.
1 - Paint a space.
2 - Show board.
3 - Play game.
4 - Quit
************************************************************
Your choice? _Enter Coordinates :Enter values:3(this is where i put my input(?))
0
 

Author Comment

by:simmah
ID: 11780347
It's 10:34pm (central US). I will be going to sleep and will check back again tomorrow. thank you for your assistance.
0
 
LVL 9

Assisted Solution

by:ankuratvb
ankuratvb earned 200 total points
ID: 11780531
One thing you can do is fflush(stdin) after each scanf statement.

This will remove any Newline characters left in the input stream,and the program will function correctly.

0
 
LVL 9

Assisted Solution

by:ankuratvb
ankuratvb earned 200 total points
ID: 11780555
You should also try to refine your getcoords function.

Right now,it accepts coordinates like 'aa'.

When the column value is greater than maxcol,it should display Bad Co-ordinates as well.

0
 
LVL 9

Assisted Solution

by:ankuratvb
ankuratvb earned 200 total points
ID: 11780578
When you do:
scanf("%c %d", &myRowchar, &myCol);

and the value in myCol is invalid(for e.g. a letter,the original value in myCol is retained)

you set myCol to 0 initially,which is never greater than maxCol,so the error message is never displayed.

set myCol initially to maxCol+1
int myCol=maxCol+1;
0
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
LVL 23

Assisted Solution

by:Mysidia
Mysidia earned 150 total points
ID: 11780612
I tried running it and can't get output like that it seems to work fine..

Well, I had to add a

   fflush(stdout);

statement before each prompt for the prompts to actually sync or even show up.  
Try adding these and see if it's still a problem.. remember stdlib does buffer any
output not terminated with \n

   printf("Your choice? _");
   fflush(stdout);
 ...
   printf("Enter coordinates : ");
   fflush(stdout);
   while(...)
        printf
        fflush
...
0
 

Author Comment

by:simmah
ID: 11783652
This is how my sourcode looks at the bottom. I have put fflush(stdout),fflush(stdin) on before/after all prompts. I set myCol to what was said and it stalled once more. either way, i am still getting the same out as stated in my comment"Date: 08/11/2004 08:23PM PDT".
#include<stdio.h>
#include<stdlib.h>

void clearBoard(int rows, int columns, int * boardPtr);
void showBoard(int rows, int columns, int * boardPtr);
int getCoords(int maxRow, int maxCol, int *row, int *col);
void paintSpace(int rows, int cols, int * boardPtr);

void clearBoard(int rows, int columns, int * boardPtr)
{
int i;

for(i=0; i < rows * columns; i++)
   {
      *(boardPtr+i) = 0; //initialize value to 0
   }
} // End of clearBoard function.


void showBoard(int rows, int columns, int * boardPtr)
{
int i;
for(i=0; i < rows * columns; i++)
   {
   // Print newline character is row is finished.
   // If i modulus the columns is 0, then you've reached
   // the end of a row and need to print a newline.
   if(i % columns == 0)
      {
      printf("\n");
      }
   
   if ((*(boardPtr+i) >= 0) && (*(boardPtr+i) <= 9))
      {
      printf("%d ", *(boardPtr+i));
      }
   else
      {
      printf("x ");
      }
   }
}

int getCoords(int maxRow, int maxCol, int *row, int *col)
{
char myRowchar;
int myCol=0;
int myRownum=0;
 fflush(stdout);
scanf("%c %d", &myRowchar, &myCol);
 fflush(stdin);
myRownum = (int)myRowchar;

if(myRownum >= 97)
   {
   myRownum = myRownum - 97;
   }
else if((myRownum >=65) && (myRownum <=90))
   {
   myRownum = myRownum - 65;
   }  

if (myRownum > maxRow)
   {
   *row = 0;
   *col = 0;
   return 0;
   }
else if (myCol > maxCol)
   {
   *row = 0;
   *col = 0;
   return 0;
   }
else
   {
   *row = myRownum;
   *col = myCol - 1; // Need to compensate because array starts at 0.
   }
return 1;
}

void paintSpace(int rows, int cols, int * boardPtr)
{
int myRow = 0, myCol = 0, value = 0;

printf("Enter coordinates :");

while( 0 == getCoords(rows, cols, &myRow, &myCol))
{
   printf("Bad coordinates!\nEnter coordinates: ");
}
/*printf("myRow = %d, myCol = %d\n", myRow, myCol);*/

printf("Enter a value: ");
 fflush(stdout);
scanf("%d", &value);
 fflush(stdin);
*(boardPtr + (myRow*cols) + myCol)  = value;


}

int main()
{
int choice;
int rows = 10;
int columns = 10;
int boardPtr[rows][columns];

while(1)
{
   printf("\n*************************************************\n");
   printf("0 - Clear the board.\n");
   printf("1 - Paint a space.\n");
   printf("2 - Show board.\n");
   printf("3 - Play game.\n");
   printf("4 - Quit.\n");
   printf("*************************************************\n");
   printf("Your choice? _");
   fflush(stdout);  
 scanf("%d", &choice);
   fflush(stdin);

   switch(choice)
      {
      case 0:
         clearBoard(rows, columns, (int *)boardPtr);
         break;

      case 1:
       fflush(stdin);
 paintSpace(rows, columns, (int *)boardPtr);
         break;

      case 2:
         showBoard(rows, columns, (int *)boardPtr);
         break;

      case 3:
         printf("The game isn't ready yet.\n");
         break;

      case 4:
         exit(0);

      default:
         printf("Your input was invalid.\n");
         break;
      } //End of Switch statement
   } //End of while loop
 return 0;
} //End of Program


0
 

Author Comment

by:simmah
ID: 11783665
please try compiling/running it to see exactly what im talking about when i say there is a clutter of statements after i input the coordinates...it'll take the value i assign the coordinates, but the clutter is there first.
0
 
LVL 9

Assisted Solution

by:ankuratvb
ankuratvb earned 200 total points
ID: 11783999
Hi simmah,

What compiler are you on?

It seems to work on my Borland compiler here.

Also,
From your output,do you give a space at the start here?
                       
Enter coordinates: F 5 (my input)
                         ^
Enter a value:
************************************************************
0 - Clear the board.
1 - Paint a space.
2 - Show board.
3 - Play game.
4 - Quit
************************************************************
Your choice? _Enter Coordinates :Enter values:3(this is where i put my input(?))
0
 

Author Comment

by:simmah
ID: 11784158
Im using cygwin and have customized it for the gcc compiler.
im not giving any spaces anywhere.
0
 
LVL 22

Assisted Solution

by:grg99
grg99 earned 150 total points
ID: 11784169
One way to get around this output flushing problem is to change the printf's into:

fprintf( stderr, .... );

You see, stderr is NOT buffered at all, so you should see the prompts immediately.

I don't know why your stdout isnt flushing right....  you could try adding a "\n" at the end of each string, as some C's only flush when they get an end-of-line.

One or the other of those should help....


0
 

Author Comment

by:simmah
ID: 11784234
so i should get rid of all of my fflush(stdin)'s and stdouts and just put fprintf(stderr,"hello"); for all printf statements?
0
 
LVL 9

Assisted Solution

by:ankuratvb
ankuratvb earned 200 total points
ID: 11784615
Try this:

int getCoords(int maxRow, int maxCol, int *row, int *col)
{
char myRowchar;
int myCol=maxCol+1;
int myRownum=maxRow+1;
fflush(stdout);
scanf("%c%d", &myRowchar, &myCol);
fflush(stdin);
myRownum = (int)myRowchar;
...
0
 

Author Comment

by:simmah
ID: 11784788
it doesnt work. I put exactly what you put in. when i entered correct coordinates(a6), it printed out 'bad coordinates!' then asked for the value...
0
 
LVL 9

Assisted Solution

by:ankuratvb
ankuratvb earned 200 total points
ID: 11785001
Check the value of myRowchar and myCol after scanf("%c%d", &myRowchar, &myCol); in getcoords()

Put a printf("%c %d",myRowchar,myCol); to see what values are stored.
0
 

Author Comment

by:simmah
ID: 11785746
i did, it shows a '11' before and '11' after and gives 'bad coordinates' error message. so, myrowchar and mycol are throwing out 1's
0
 
LVL 9

Assisted Solution

by:ankuratvb
ankuratvb earned 200 total points
ID: 11786028
You tested this on 10x10 board,right?

IMO,myCol gets the value 11 from maxCol=10 +1, and myrowchar is either empty('') or gets the \n from the previous scanf().

Try putting the fflush(stdin) before the scanf instead of after.
0
 

Author Comment

by:simmah
ID: 11786192
I did, it's still giving me an 11.
0
 
LVL 9

Accepted Solution

by:
ankuratvb earned 200 total points
ID: 11786250
So,your scanf is failing.
It has to be that myrowchar gets the \n from the previous scanf and myCol gets the alphabet of your coordinates,thus it fails.

Put :

char ch;
ch=getchar();

before the scanf() in getcoords()
0
 

Author Comment

by:simmah
ID: 11787015
it works a bit. below, you can see f6 repeats itself twice.
Enter coordinates:f6 (my input)
                         
Enter a value:
************************************************************
0 - Clear the board.
1 - Paint a space.
2 - Show board.
3 - Play game.
4 - Quit
************************************************************
f 6f 6Enter values:3(this is where i put my input)
0
 
LVL 9

Expert Comment

by:ankuratvb
ID: 11790321
Well,now your \n is consumed at the enter value prompt.
Put a ch=getchar() after all your scanf() statements and remove all the fflush(stdin) and stdout.
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

An Outlet in Cocoa is a persistent reference to a GUI control; it connects a property (a variable) to a control.  For example, it is common to create an Outlet for the text field GUI control and change the text that appears in this field via that Ou…
This is a short and sweet, but (hopefully) to the point article. There seems to be some fundamental misunderstanding about the function prototype for the "main" function in C and C++, more specifically what type this function should return. I see so…
The goal of this video is to provide viewers with basic examples to understand how to use strings and some functions related to them in the C programming language.
Video by: Grant
The goal of this video is to provide viewers with basic examples to understand and use nested-loops in the C programming language.

707 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now