-4

I am just trying to make a simple two player game. First player enters the movie and second player guesses it by using some basics of C++.

movie[] = entered by player 1.
movie_temp[]= a temp array with '_' in it. It updates after every guess by player 2.

MY PROBLEM: Please refer the main function where I called the function movie_check(). This updates the life after every guess. I want the same to happen for my movie_temp array. When I run this program, only the lives are updated properly, on correct guess the lives are not reduced, but in next turn the array_temp is not updated and the same array is displayed again and again after each gas.

Please help me to create a function which helps to return array and save it in movie_temp (just as I did for life).

IDE: Code::Blocks Compiler: GCC Compiler

#include<iostream.h>
#include<stdlib.h>
#include<ctype.h>
#include<string.h>
#include<conio.h>

void display_movie(char movie_temp[], int);
void display_life(int);
int win_player2(char movie_temp[]);
int check_life(char movie[], char, int);


void display_movie(char movie_temp[], int len)
{
    for(int i=0 ; i<len ; i++)
        cout<<movie_temp[i];
}

void display_life(int life)
{
    for(int i=0 ; i<=life ; i++)
        cout<<"\3";
}


int check_life(char movie[], char ch, int life)
{
    int count1=0;
    for(int i=0 ; movie[i]!='\0' ; i++)
    {
        if(movie[i]==ch)
            count1++;
    }
    if(count1==0)
        return --life;
    else
        return life;
}

int win_player2(char movie_temp[])
{
    int count=0;
    for(int i=0 ; movie_temp[i]!='\0' ; i++)
   {
       if(movie_temp[i]=='_')
           count++;
   }
   if(count==0)
        return 0;
   else
        return 1;
}


int main()
{
    char movie[100], movie_temp[100], ch;
    cout<<"Enter the movie: ";
    cin.getline(movie,100);
    int len= strlen(movie);
    system("cls");


    for(int i=0 ; movie[i]!='\0' ; i++)
    {
        if(movie[i]=='a' || movie[i]=='e' || movie[i]=='i' || movie[i]=='o' ||
        movie[i]=='u' || movie[i]==' ')
            movie_temp[i]= movie[i];
        else
            movie_temp[i]='_';
    }

    int life=9;
    cout<<"\nLives left: ";
    display_life(life);


    while(life!=0 || win_player2(movie_temp)!=0)
    {
        cout<<"\n";
        display_movie(movie_temp, len);
        cout<<"\nEnter your guess: ";
        cin>>ch;
        life=check_life(movie, ch, life);
        cout<<"\n\nLives left: ";
        display_life(life);

    }
    getch();
    return 0;
}

enter code here
lazygeek
  • 51
  • 1
  • 7
  • 5
    This would be SO much easier with `std::string`. – Fred Larson Feb 12 '14 at 15:15
  • And if you're using conio.h, why not just use `clrscr()` instead of `system("cls")`? – Fred Larson Feb 12 '14 at 15:18
  • Seems more like C tending to be C++. Other than `cout` and `cin` everything seems to be C. Use C++ structures to make your life a lot easier. – DumbCoder Feb 12 '14 at 15:18
  • The `count1=0;` right after `return life;` is unreachable code (it's also redundant, since it's only executed if `count1 == 0` in the first place). Do turn up your warning level to catch stuff like this. – Fred Larson Feb 12 '14 at 15:19
  • @FredLarson : I am a C++ beginner. I don't have any idea about std::string. Just help me make out this program. The logic's is almost correct. Just need some professional's touch. – lazygeek Feb 12 '14 at 15:29
  • @lazygeek: All the more reason to use C++ features that make your life easier. Arrays are very easily misused in C++ and are best left to the experts (who avoid them when they can). – Fred Larson Feb 12 '14 at 15:33
  • 2
    @lazygeek If whatever you're learning from hasn't mentioned std::string, I'd recommend you [pick up a good book](http://stackoverflow.com/q/388242) and learn how to use the features of the the language you're using. – The Forest And The Trees Feb 12 '14 at 15:51
  • [You can't return arrays from functions](http://stackoverflow.com/q/20063617/1530508). – ApproachingDarknessFish Feb 12 '14 at 17:28
  • @ValekHalfHeart : Yes I googled it a lot. Everyone's saying something about pinters. But I dont get it. Can you please give me a simple (very simple) example explaining returning array through pointers. I want to save that returned value into some main function. Please help me :) – lazygeek Feb 12 '14 at 17:46
  • @lazygeek Arrays are pointers, so your premise of "write a function that returns an array" is flawed. – ApproachingDarknessFish Feb 12 '14 at 17:47
  • @ValekHalfHeart : I know its flawed. Thats why I am here. Stop pointing my faults and give me a simple example. – lazygeek Feb 12 '14 at 17:49
  • @ValekHalfHeart : I just realized some of the blunders I made. Here's the code with some major corrections: http://pastebin.com/0T2U1aan – lazygeek Feb 12 '14 at 17:51
  • @lazygeek - I updated my answer with some more information on "how to return arrays from functions". Hope it helps. – Floris Feb 12 '14 at 20:28

1 Answers1

3

You make the usual mistake:

            movie_temp[i]==movie[i];

should be

            movie_temp[i]=movie[i];

Your compiler should have been screaming a warning at you... mine did:

note: use '=' to turn this equality comparison into an assignment
                movie_temp[i]==movie[i];

Context (in case you have trouble finding the line):

    if(movie[i]==ch)
        {
            movie_temp[i]==movie[i];   // <<<<<<<<<< this is the line that doesn't copy!
            count1++;
        }

update just following the warnings that the compiler was giving me, I made a few small changes to your code and now it is working. Mostly, I was heeding the "you are not returning a value!" types of warnings (when you don't explicitly return a value, the compiler will make something up - and most likely you won't find the result useful).

The key is to move the line

return movie_temp;

outside of the for loop in check_movie2:

char* check_movie2(char movie[], char movie_temp[], char ch)
{
    for(int i=0 ; movie[i]!='\0' ; i++)
    {
        if(movie[i]==ch)
            {
                movie_temp[i]=movie[i];
            }
    }
    return movie_temp;
}

There are other problems - but this is the one that was biting you the hardest.

Lesson learnt: if your compiler is warning you, LISTEN.

For your entertainment here is the code that I got to run (and that "mostly works". It doesn't currently print out lives correctly and it asks for input after I guessed the title. Also you might consider making the comparison case-insensitive as you are currently sensitive to correct capitalization).

updated added some comments and additional fixes in your code.

#include<iostream>
#include<stdlib.h>
#include<ctype.h>
#include<string.h>

using namespace std;  // <<<< if you want to use 'cout' instead of 'std::cout' etc, you need this

void display_movie(char movie_temp[], int);
void display_life(int);
int win_player2(char movie_temp[]); 
int check_movie(char movie[], char movie_temp[], char, int);
void display_movie(char movie_temp[], int len)
{
    for(int i=0 ; i<len ; i++)
    cout<<movie_temp[i];
}

void display_life(int life) //displays lives left after each guess
{
    for(int i=0 ; i<=life ; i++)
    cout<<"+";     // <<<<< I don't know what you are hoping to print with "\3"
                   // <<<<< Remember that `\` has a special meaning inside a string!
}


int check_movie(char movie[], char movie_temp[], char ch, int life)
{
    int count1=0;
    for(int i=0 ; movie[i]!='\0' ; i++)
    {
        if(tolower(movie[i])==tolower(ch))    // <<<<< consider case insensitive match 
            {
                movie_temp[i]=movie[i];
                count1++;
            }
    }
    if(count1==0)
        {
            life--;
            return life;    //if none of the character is found, life is reduced by 1.
            count1=0;
        }
    return life; // <<<<<< return life here    
}

int win_player2(char movie_temp[])
{
    int count=0;
    for(int i=0 ; movie_temp[i]!='\0' ; i++)
    {
        if(movie_temp[i]=='_')
            count++;
    }  
    return (count==0)?0:1;
}

char* check_movie2(char movie[], char movie_temp[], char ch)
{
    for(int i=0 ; movie[i]!='\0' ; i++)
    {
        if(movie[i]==ch)
            {
                movie_temp[i]=movie[i];
            }
    }
    return movie_temp;
}

int main()
{
    char movie[100], movie_temp[100], ch;
    cout<<"Enter the movie: ";
    cin.getline(movie,100);
    int len= strlen(movie);
    int life=9;
    system("cls");


    for(int i=0 ; movie[i]!='\0' ; i++)
    {
        if(movie[i]=='a' || movie[i]=='e' || movie[i]=='i' || movie[i]=='o' ||
        movie[i]=='u' || movie[i]==' ')
        movie_temp[i]= movie[i];
    else
        movie_temp[i]='_';
    }    //initially displays the movie to player 2 and shows only vowels.

    cout<<"\nLives left: ";
    display_life(life);


    while(life!=0 && win_player2(movie_temp)!=0)  // <<<<< change || to &&
    {
        cout<<"\n";
        display_movie(movie_temp, len);
        cout<<"\nEnter your guess: ";
        cin>>ch;
        life=check_movie(movie, movie_temp, ch, life); 

        /*I need to update the life after each round, or else the initially declared              
         life is passed. */

        cout<<"\n\nLives left: ";
        display_life(life);

    }
    return 0;
}

UPDATE - "returning pointers from functions"

To "return an array of values", you need to realize a number of things:

  1. A function can only "return" a simple value (int, float, pointer, ...)
  2. If you create an array inside a function, you need to make sure the space allocated remains valid after you return
  3. You can pass a pointer to a function, and let the function update values in the space pointer to

Simple example (C) on different approaches (including one that doesn't work):

does not work:

   int * foo() {
     int A[]={1,2,3,4,5};
     return A;
   }

int main(void) {
  int *X;
  X = foo();
  printf("%d", X[0]);  // UNDEFINED BEHAVIOR
  return 0;
}

This doesn't work because the array A stops existing ('goes out of scope') when the function returns. Accessing memory pointed to by X results in undefined behavior.

works, but only use in single threaded environment:

   int * foo() {
     static int A[]={1,2,3,4,5};
     return A;
   }

this works because the array is static so it is allocated differently and "survives" after the function returns. Not recommended.

pass a pointer and size of array: (example increments an array)

void foo(int *a, int n) {
  int ii;
  for(ii=0;ii<n;ii++) a[ii]++;
}

int main(void) {
  int n=5;
  int X[5] = {1,2,3,4,5};
  foo(X, 5);  // values in X will be incremented in-place

Returning value in another array:

void foo(int *A, int *B, int n) {
  int ii;
  for(ii=0; ii<n; ii++) B[ii] = 2 * A[ii];
}

int main(void) {
  int a[5] = {1,2,3,4,5};
  int b[5];
  foo(a, b, 5);
  printf("%d\n", b[0]);  // returns a value of 2
  return 0;
}

This is starting to be more sensible. Finally, if you want an array to be created by the function, you can do

int *foo(int n) {
  int *X, ii;
  X = malloc(n * sizeof *X);
  for(ii = 0; ii < n; ii++) X[ii] = 2 * ii;
  return X;
}

int main(void) {
  int *a;
  a = foo(5);
  printf("%d", a[4]); // will print 8
  free(a);  // remember to do this after you finished using the array or you get a memory leak!
  return 0;
}

I hope these additional examples and their explanation improves your understanding of these techniques a little bit.

Floris
  • 45,857
  • 6
  • 70
  • 122