I am trying to design the game Bulls and Cows
we have a word to guess eg:"fame"(four lettered)
if i type abcd bulls=0 cows=0
efgh bulls=0 cows=1 (if the letter is at the same positon as the word we give bulls. If the letter is in the word but not at the same position we give cows.

one more thing
if i write seme i should get bull=2 cow=0
i mean if there is a bull for the letter cow will be 0 for that letter which is my problem.The cows is a problem
eg:fgeh should give bulls=1 cows=1
eg:mmmm should give bulls=1 cows=0

i hope u got the game logic


here is my code

import java.io.*;
class BullsandCows
{
public static void main(String args[])throws IOException
{int count=0;int count2=0;
String str="fame";int tries=0;
System.out.println("enter 4 lettered word");
if(count!=4)
{
do
{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
String str2=br.readLine();
if(str2.length()==4)
{
for(int i=0;i<4;i++)
{
if(str.charAt(i)==str2.charAt(i))
count=count+1; 
}
for(int i=0;i<4;i++)
{
for(int j=i+1;j<4;j++)
{
if(str.charAt(i)==str2.charAt(j))
count2=count2+1;
}
}
}
System.out.println("bulls= "+count);
System.out.println("cows= "+count2);
if(count==4)
{
System.out.println("congrats");
System.exit(0);
}
else
{
System.out.println("try again");
tries++;
}

count=0;
count2=0;
}
while(tries<=3);
if(tries>=3)
System.out.println("word is "+"fame");
}
}
}

thanks

You used code tags, but there's no indentation so it doesn't help much. Here's your code:

import java.io.*;

class BullsandCows
{

    public static void main(String args[]) throws IOException
    {
        int count = 0;
        int count2 = 0;
        String str = "fame";
        int tries = 0;
        System.out.println("enter 4 lettered word");
        if (count != 4)
        {
            do
            {
                BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
                String str2 = br.readLine();
                if (str2.length() == 4)
                {
                    for (int i = 0; i < 4; i++)
                    {
                        if (str.charAt(i) == str2.charAt(i))
                        {
                            count = count + 1;
                        }
                    }
                    for (int i = 0; i < 4; i++)
                    {
                        for (int j = i + 1; j < 4; j++)
                        {
                            if (str.charAt(i) == str2.charAt(j))
                            {
                                count2 = count2 + 1;
                            }
                        }
                    }
                }
                System.out.println("bulls= " + count);
                System.out.println("cows= " + count2);
                if (count == 4)
                {
                    System.out.println("congrats");
                    System.exit(0);
                }
                else
                {
                    System.out.println("try again");
                    tries++;
                }

                count = 0;
                count2 = 0;
            }
            while (tries <= 3);
            if (tries >= 3)
            {
                System.out.println("word is " + "fame");
            }
        }
    }
}

Your problem is that, when calculating the number of cows, you make no attempt to check whether the letter in question is a bull. it can't be both. You are making the determinations of bull and cows independent of each other, but it isn't. If it's a bull, it's not a cow.

So check for a bull first, and then if and only if it's not a bull, check to see if it's a cow.

Write out every conceivable example on paper and see what it is exactly what you do in your own head when calculating. Then write the program. You need the algorithm first.


[EDIT]
Actually, I'm getting less sure of that explanation. Your loops might have taken care of that possibility already. I didn't look closely enough earlier. I'm going to puzzle over this one for a bit...
[/EDIT]

akulkarni,
in loop on line 30 to 36: Think what happens when i == 3... you need to reset j to 0. That way you check letters before variable i.
try

for(int j=i+1;j>3;j++) {
  if (j>3) j = 0;
  if(str.charAt(i)==str2.charAt(j)) count2=count2+1;
}

please, mark it solved if you think it is.

OK, scratch some of that last post. I do think you need an overall redesign, though, and you need to go over it on paper and get the algorithm down. Repeated letters in either the guess or the word may be a serious problem, but even without that, you have a problem. Try entering "fame" backwards. You should get four cows. You only get two. Why? Because of this j-loop:

for (int i = 0; i < 4; i++)
                    {
                        for (int j = i + 1; j < 4; j++)
                        {
                            if (str.charAt(i) == str2.charAt(j))
                            {
                                count2 = count2 + 1;
                            }
                        }
                    }

You need to check the EARLIER letters as well as the later letters. Type in "emaf" and look at what happens when you check the letter at position 2 ('m'. It's in position 1 of the guess, but j is never equal to 1, so it misses that "cow".

Oh, sorry VernonDozier, I didn't see your answer.

No worries. We're posting on top of each other. I think you actually beat me on this one since I had second thoughts on my first post :)

i did some changes.I made j=0 and compared count2 with count1 hope this works for all combinations. I have tried a few but failed with ffff mmmm aaaa eeee it gives 4 cows which should be 0
heres the code

import java.io.*;
class BullsandCowstest
{

    public static void main(String args[]) throws IOException
    {
        int count = 0;int x;
        int count2 = 0;
        String str = "fame";
        int tries = 0;
        System.out.println("enter 4 lettered word");
        if (count != 4)
        {
            do
            {
                BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
                String str2 = br.readLine();
                
                    for (int i = 0; i < 4; i++)
                    {
                        if (str.charAt(i) == str2.charAt(i))
                        {
                            count = count + 1;
                        }
                    }
                    for (int i = 0; i < 4; i++)
                    {
                        for (int j = 0; j < 4; j++)
                        {
                            if (str.charAt(i) == str2.charAt(j))
                            {
                                count2 = count2 + 1;
                            }
                        }
                    }
                if(count>count2)
	x=count-count2;
	else
	x=count2-count;
                System.out.println("bulls= " + count);
                System.out.println("cows= " + x);
                if (count == 4)
                {
                    System.out.println("congrats");
                    System.exit(0);
                }
                else
                {
                    System.out.println("try again");
                    tries++;
                }

                count = 0;
                count2 = 0;
            }
            while (tries <= 3);
            if (tries >= 3)
            {
                System.out.println("word is " + "fame");
            }
        }
    }
}

thanks

Now my advice from my first post is more relevant because you make no attempt here to check whether something that you're marking as a cow was also marked as a bull. With your code, you can do that. Revise it so that you cannot.

Second, you have a lot of flaws regarding multiple letters in the word and/or guess. You need to go back to the drawing board and write an algorithm for solving this. Forget about solving it using a computer for now. Take a pencil and paper and jot down the exact process that you use when you do it in your head or on paper. Don't skip any steps, no matter how small.

Once you've written down the algorithm step by step, it'll be easier to put it into code.

Dear vernon,

I might get flamed for this but no worries. I did put down an algo what i discovered was ....in the first loop if i put another "if"

if(str2.charAt(i)==str2.charAt(i+1))

...put a count.

But i get a run time error(which is natural) "array out of bounds ".This wasnt the case in c++.I hope u will help me

Dear vernon,

I might get flamed for this but no worries. I did put down an algo what i discovered was ....in the first loop if i put another "if"

if(str2.charAt(i)==str2.charAt(i+1))

...put a count.

But i get a run time error(which is natural) "array out of bounds ".This wasnt the case in c++.I hope u will help me

I won't flame you, I'll just disagree strongly. I see no algorithm. An algorithm is a detailed, step-by-step plan to solve the problem. It should not be language specific. If you have one, you haven't posted it. The code you have isn't going to work, because, as mentioned before, you calculate the number of cows and the number of bulls completely independently, which is wrong. the bulls is the easier part of this program. Cows are harder since there is a problem of duplicate letters and a problem of making sure the same index isn't marked as both a cow and a bull.

The problem is that we do things on paper and it's obvious to us what we're doing, so we don't write down the exact detailed steps or we combine them since we mistakenly assume it's trivial. A computer program isn't smart at all. You have to tell it everything, no matter how small.

The program you have above should behave the same in C++ as in Java, aside from some syntax changes, including out-of-bounds errors. You can't/shouldn't go past the end of the array in either language. C++ might just let you get away with it without complaining as much.

for now i have given the user a condition that he shouldnt repeat letters in his guess.I checked in wikipedia about the game and i saw that the condition is ok

I did on paper but it looks tough.Do u have any hint.I will try to post the algorithm. I have got so used to writing codes in computer that i have forgotten the algo way which is wrong i know.

I have had sleepless nights for my level of programming skills.

Thanks anyways.

keep in touch .U have been kind and helpful

for now i have given the user a condition that he shouldnt repeat letters in his guess.I checked in wikipedia about the game and i saw that the condition is ok

I did on paper but it looks tough.Do u have any hint.I will try to post the algorithm. I have got so used to writing codes in computer that i have forgotten the algo way which is wrong i know.

I have had sleepless nights for my level of programming skills.

Thanks anyways.

keep in touch .U have been kind and helpful

How 'bout this for an algorithm? Let's say you have the correct word of "nine". The guess is "anna". That's one bull and one cow.

nine   (the word)
anna   (the guess)
icbi  (i = incorrect, c = cow, b = bull)

Have a couple of markers that you can use to "mark" cows and bulls so they aren't double-counted. Make the markers characters that cannot be used in the real word. How about if '!' represents a cow or bull in the real word and '#' represents a cow or bull in the guess (make sure these characters are different from each other)?

Initialize cows and bulls to 0 and go through letter by letter. Do the bulls first (* signifies current comparison):

*
nine
anna

No match (n != a). Move on to next letter:

*
nine
anna

No match (i != n). Move on to next letter:

*
nine
anna

Match (n == n). Increment number of bulls and change the letters:

*
ni!e
an#a

Move to last letter. No match (e != a):

*
ni!e
an#a

NOW do the cows, comparing "ni!e" to "an#a". Same idea. When you find a cow, substitute '!' in the original and '#' in the guess so there can't be duplicates. You should get 1 bull, 1 cow. Try this algorithm for any guess and any correct word, with any number of duplicate letters you like. I think it should work.

Yes i think i can do that. Thats quite smart.I will post the program as soon as possible.

thanks

Dear Vernon,

I hope u will kindly accept my thanks with a reply. I did the program just as u told. It was great. I wonder how u could think of such good string manipulation.Anyways, hope to be in regular touch with you, friend.

heres the code

import java.io.*;
class bullstest1
{
    public static void main(String args[])throws IOException
           {
             String s1="anna";
             String s2;
             int i,j;int count=0;int count2=0;
            BufferedReader br=new              BufferedReader(new              InputStreamReader(System.in));
            s2=br.readLine();
            char [] s1c=s1.toCharArray();
            char [] s2c=s2.toCharArray();
            for(i=0;i<4;i++)
                {
                   if(s1.charAt(i)==s2.charAt(i))
                      {
                       s1c[i]='!';
                       s2c[i]='#';
                       count=count+1;
                       }
                }
                 for(i=0;i<4;i++)
                    {
                       for(j=0;j<4;j++)
                            {
                                 if(s1c[i]==s2c[j])
                                    {
                                        s1c[i]='!';
                                        s2c[i]='#';
                                         count2=count2+1;
                                    }
                             }
                     }
                         System.out.println("Bulls= "+count);
                         System.out.println("Cows= "+count2);
	}
}

note:i am not used to indents so pls adjust

wait a minute!
akulkarni: did you try to compile and run it? did you run it several times with diferent strings?
Try inputing "naan".
What happens?
Bulls: 0;
Cows: 3;
What happens with "nana"?
Bulls: 2,
Cows: 1.
See what's going on? The problem is that when you modifiy s1c you also modify s2c, but at the same index!!!
My advice, you either don't modify s1c (the one on line 29, of course) and just delete this line. The other possibility is also modifying s2c but on j index as in s2c[j]='#'; , that is line 30.

Take care

Comments
Good observation.

wait a minute!
akulkarni: did you try to compile and run it? did you run it several times with diferent strings?
Try inputing "naan".
What happens?
Bulls: 0;
Cows: 3;
What happens with "nana"?
Bulls: 2,
Cows: 1.
See what's going on? The problem is that when you modifiy s1c you also modify s2c, but at the same index!!!
My advice, you either don't modify s1c (the one on line 29, of course) and just delete this line. The other possibility is also modifying s2c but on j index as in s2c[j]='#'; , that is line 30.

Take care

Yes, you should CHANGE the characters that you just COMPARED:

if(s1c[i] == s2c[j] )
{
    s1c[i] ='!';
    s2c[j] ='#';  // I changed the green part of this line.
    count2=count2+1;
}

Red matches red, green matches green.

yes i was actually noticing it.It was a typo i guess.

is this ok now

import java.io.*;
class bullstest2
{
    public static void main(String args[])throws 

IOException
           {
             String s1="anna";
             String s2;
             int i,j;int count=0;int count2=0;int tries=0;
            do
              {
              System.out.println("enter ur guess(4 

             lettered)");
             BufferedReader br=new              

              BufferedReader(new              

             InputStreamReader(System.in));
            s2=br.readLine();
            if(s2.length()!=4)
                  {
	    System.out.println("enter 4 lettered         

                   word please");	
                   System.exit(0);
                   }
            char [] s1c=s1.toCharArray();
            char [] s2c=s2.toCharArray();
            for(i=0;i<4;i++)
                {
                   if(s1.charAt(i)==s2.charAt(i))
                      {
                       s1c[i]='!';
                       s2c[i]='#';
                       count=count+1;
                       }
                }
                 for(i=0;i<4;i++)
                    {
                       for(j=0;j<4;j++)
                            {
                                 if(s1c[i]==s2c[j])
                                    {
                                        s1c[i]='!';
                                        s2c[j]='#';
                                         count2=count2+1;
                                    }
                             }
                     }
                         System.out.println("Bulls= 

"+count);
                         System.out.println("Cows= 

"+count2);	
                   if(count==4)
                     {
                    System.out.println("correct, 

congrats");
                    System.exit(0);
                    }
                   else
                    {
                   System.out.println("try again");
                  tries++;
                    }
                  count=0;
                  count2=0;
          }
         while(tries<=5);

    }

}

Is this ok now?

Is this ok now?

You tell us. Run it and see. Throw everything at it that you can think of. Throw every conceivable guess at it and see if it handles everything correctly. Try to think of a way for it to fail and see if it does. Try words with no repeated letters, try word with repeated letters, try words with all cows, all bulls, neither, etc. Most important (hint hint :) ), try entering a word that's the wrong length. You are telling the user to enter something, then ending the program before they can do what you asked them to do!!!


While you're at it, make the game more versatile. Right now they're stuck with "anna". Pretty boring game after you've guessed correctly! Who wants to play this game twice? Change it so that they can enter whatever word they want. A few tweaks to your code and it's a two player game where you're not stuck with just guessing "anna" every time:

class bullstest2
{

    public static void main(String args[]) throws IOException
    {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        System.out.println ("Player 1 :Enter a word for player 2 to guess : ");
        String s1 = br.readLine();
        int numLetters = s1.length();

        String s2;
        int i, j;
        int count = 0;
        int count2 = 0;
        int tries = 0;
        do
        {
            System.out.println("Player 2 : enter ur guess : ");
            s2 = br.readLine();
            if (s2.length() != numLetters)
            {
                System.out.println("enter " + Integer.toString (numLetters) + " lettered word please");
                System.exit(0);
            }
            char[] s1c = s1.toCharArray();
            char[] s2c = s2.toCharArray();
            for (i = 0; i < numLetters; i++)
            {
                if (s1.charAt(i) == s2.charAt(i))
                {
                    s1c[i] = '!';
                    s2c[i] = '#';
                    count = count + 1;
                }
            }
            for (i = 0; i < numLetters; i++)
            {
                for (j = 0; j < numLetters; j++)
                {
                    if (s1c[i] == s2c[j])
                    {
                        s1c[i] = '!';
                        s2c[j] = '#';
                        count2 = count2 + 1;
                    }
                }
            }
            System.out.println("Bulls= " + count);
            System.out.println("Cows= " + count2);
            if (count == numLetters)
            {
                System.out.println("correct, congrats");
                System.exit(0);
            }
            else
            {
                System.out.println("try again");
                tries++;
            }
            count = 0;
            count2 = 0;
        }
        while (tries <= 5);
    }
}

Your code gave me :( (and my compiler :P ) a headache. The formatting makes it impossible to read. I was actually surprised, but my compiler complained too. It didn't like the multi-line println statements. Format the code so it's readable. Netbeans will do it for you. Look at my code and your code. Which one do you want to look at when you're trying to decide what is inside a block of code and what isn't when you're debugging?


[EDIT]
Didn't follow my own advice and actually RUN my revised code. There was a bug translating your code (fixed now).
[/EDIT]

ok.thanks.

I am planing to use the getrandom method to generate random numbers upto 20 and put a switch case statement with different strings for each number. i also need to add 3 levels to the game.i agree with you about the length of the word to be guessed.

You know Vernon sir what i think is that there are so many things we can add to a game and enhance its features..we fall short of ideas at time(just a friendly message)

I would like ur opinion about the random method and i will be grateful to get more suggestions from you

i am working on the problem u faced with the multilined statements and other with ur compiler

tc

ok.thanks.

I am planing to use the getrandom method to generate random numbers upto 20 and put a switch case statement with different strings for each number. i also need to add 3 levels to the game.i agree with you about the length of the word to be guessed.

You know Vernon sir what i think is that there are so many things we can add to a game and enhance its features..we fall short of ideas at time(just a friendly message)

I would like ur opinion about the random method and i will be grateful to get more suggestions from you

i am working on the problem u faced with the multilined statements and other with ur compiler
tc

Having a bunch of words and picking one of them randomly to have the user guess is a good idea. There are all sorts of word lists out there that you can read in from a file, or you can hard code them into your program. I don't think I see a need for a switch statement. I think that would unnecessarily length the code.

Suppose you have a Vector or an ArrayList or whatever full of words. Randomly select an index, say 7.

ArrayList<String> words;
int randomIndex;

// fill in words and generate a random number for randomIndex.

String s1 = (String) words.get (randomIndex);

Or use a plain old String array and hard-code it. Same idea. i don't see the need for a switch statement.


Regarding the lines, I don't know if it's just my compiler. I think you can't have a quoted String span more than line, as in:

String someString = "abcdef
ghijk";

Instead, if you have to have it span two lines, do this:

String someString = "abcdef" +
"ghijk";

But I think it looks nicer all on one line:

String someString = "abcdefghijk";
This article has been dead for over six months. Start a new discussion instead.