Bulls and cows: Difference between revisions

From Rosetta Code
Content added Content deleted
(C (with ncurses... it seems rather natural to use it for this game))
(Added Java)
Line 8: Line 8:
# The player wins if the guess is the same as the randomly chosen number, and the program ends.
# The player wins if the guess is the same as the randomly chosen number, and the program ends.
# A score of one '''bull''' is accumulated for each digit in the guess that equals the corresponding digit in the randomly chosen initial number.
# A score of one '''bull''' is accumulated for each digit in the guess that equals the corresponding digit in the randomly chosen initial number.
# A score of one cow is accumulated for each digit in the guess that also appears in the randomly chosen number, but in the wrong position.
# A score of one '''cow''' is accumulated for each digit in the guess that also appears in the randomly chosen number, but in the wrong position.


=={{header|C}}==
=={{header|C}}==
Line 160: Line 160:
return EXIT_SUCCESS;
return EXIT_SUCCESS;
}</lang>
}</lang>

=={{header|Java}}==
<lang java5>import java.util.InputMismatchException;
import java.util.Random;
import java.util.Scanner;

public class BullsAndCows{
public static void main(String[] args){
Random gen= new Random();
int target= 0;
while(hasDupes(target= (gen.nextInt(9000) + 1000)));
String targetStr = target +"";
boolean guessed = false;
Scanner input = new Scanner(System.in);
int guesses = 0;
do{
int bulls = 0;
int cows = 0;
System.out.print(
"Guess a 4-digit number with no duplicate digits: ");
int guess;
try{
guess = input.nextInt();
if(hasDupes(guess)) continue;
}catch(InputMismatchException e){
continue;
}
guesses++;
String guessStr = guess + "";
for(int i= 0;i < 4;i++){
if(guessStr.charAt(i) == targetStr.charAt(i)){
bulls++;
}else if(targetStr.contains(guessStr.charAt(i)+"")){
cows++;
}
}
if(bulls == 4){
guessed = true;
}else{
System.out.println(cows+" Cows and "+bulls+" Bulls.");
}
}while(!guessed);
System.out.println("You won after "+guesses+" guesses!");
}
public static boolean hasDupes(int num){
boolean[] digs = new boolean[10];
while(num > 0){
if(digs[num%10]) return true;
digs[num%10] = true;
num/= 10;
}
return false;
}
}</lang>
Output:
<pre>Guess a 4-digit number with no duplicate digits: 5834
2 Cows and 0 Bulls.
Guess a 4-digit number with no duplicate digits: 1234
1 Cows and 0 Bulls.
Guess a 4-digit number with no duplicate digits: 4321
1 Cows and 0 Bulls.
Guess a 4-digit number with no duplicate digits: 3421
0 Cows and 1 Bulls.
Guess a 4-digit number with no duplicate digits: 8412
0 Cows and 0 Bulls.
Guess a 4-digit number with no duplicate digits: 3560
1 Cows and 1 Bulls.
Guess a 4-digit number with no duplicate digits: 3650
0 Cows and 2 Bulls.
Guess a 4-digit number with no duplicate digits: 3759
2 Cows and 2 Bulls.
Guess a 4-digit number with no duplicate digits: 3975
2 Cows and 2 Bulls.
Guess a 4-digit number with no duplicate digits: 3957
You won after 10 guesses!</pre>


=={{header|Python}}==
=={{header|Python}}==

Revision as of 05:19, 4 May 2009

Task
Bulls and cows
You are encouraged to solve this task according to the task description, using any language you may know.

This is an old game played with pencil and paper that was later implemented on computer.

The task is for the program to create a four digit random number from the digits 1 to 9, without duplication. The program should ask for guesses to this number, reject guesses that are malformed, then print the score for the guess.

The score is computed as:

  1. The player wins if the guess is the same as the randomly chosen number, and the program ends.
  2. A score of one bull is accumulated for each digit in the guess that equals the corresponding digit in the randomly chosen initial number.
  3. A score of one cow is accumulated for each digit in the guess that also appears in the randomly chosen number, but in the wrong position.

C

Library: ncurses

<lang c>#include <stdio.h>

  1. include <stdarg.h>
  2. include <stdlib.h>
  3. include <stdbool.h>
  4. include <curses.h>
  5. include <string.h>
  1. define MAX_NUM_TRIES 72
  2. define LINE_BEGIN 7
  3. define LAST_LINE 18

int yp=LINE_BEGIN, xp=0;

char number[5]; char guess[5];

  1. define MAX_STR 256

void mvaddstrf(int y, int x, char *fmt, ...) {

 va_list args;
 char buf[MAX_STR];
 
 va_start(args, fmt);
 vsprintf(buf, fmt, args);
 move(y, x);
 clrtoeol();
 addstr(buf);
 va_end(args);

}

void ask_for_a_number() {

 int i=0;
 char symbols[] = "123456789";
 move(5,0); clrtoeol();
 addstr("Enter four digits: ");
 while(i<4) {
   int c = getch();
   if ( (c >= '1') && (c <= '9') && (symbols[c-'1']!=0) ) {
     addch(c);
     symbols[c-'1'] = 0;
     guess[i++] = c;
   }
 }

}

void choose_the_number() {

 int i=0, j;
 char symbols[] = "123456789";
 while(i<4) {
   j = rand() % 9;
   if ( symbols[j] != 0 ) {
     number[i++] = symbols[j];
     symbols[j] = 0;
   }
 }

}</lang>

The following function contains the code to check how many bulls and cows there are.

<lang c>bool take_it_or_not() {

 int i;
 int cows=0, bulls=0;
 for(i=0; i < 4; i++) {
   if ( number[i] == guess[i] ) {
     bulls++;
   } else if ( strchr(number, guess[i]) != NULL ) {
     cows++;
   }
 }
 move(yp, xp);
 addstr(guess); addch(' ');
 if ( bulls == 4 ) { yp++; return true; }
 if ( (cows==0) && (bulls==0) ) addch('-');
 while( cows-- > 0 ) addstr("O");
 while( bulls-- > 0 ) addstr("X");
 yp++;
 if ( yp > LAST_LINE ) {
   yp = LINE_BEGIN;
   xp += 10;
 }
 return false;

}

bool ask_play_again() {

 int i;
 while(yp-- >= LINE_BEGIN) {
   move(yp, 0); clrtoeol();
 }
 yp = LINE_BEGIN; xp = 0;
 move(21,0); clrtoeol();
 addstr("Do you want to play again? [y/n]");
 while(true) {
   int a = getch();
   switch(a) {
   case 'y':
   case 'Y':
     return true;
   case 'n':
   case 'N':
     return false;
   }
 }

}


int main() {

 bool bingo, again;
 int tries = 0;
 initscr(); cbreak(); noecho();
 clear();
 number[4] = guess[4] = 0;
 mvaddstr(0,0, "I choose a number made of 4 digits (from 1 to 9) without repetitions\n"
               "You enter a number of 4 digits, and I say you how many of them are\n"
               "in my secret number but in wrong position (cows or O), and how many\n"
               "are in the right position (bulls or X)");
 do {
   move(20,0); clrtoeol(); move(21, 0); clrtoeol();
   srand(time(NULL));
   choose_the_number();
   do {
     ask_for_a_number();
     bingo = take_it_or_not();
     tries++;
   } while(!bingo && (tries < MAX_NUM_TRIES));
   if ( bingo ) 
     mvaddstrf(20, 0, "You guessed %s correctly in %d attempts!", number, tries);
   else
     mvaddstrf(20,0, "Sorry, you had only %d tries...; the number was %s", 

MAX_NUM_TRIES, number);

   again = ask_play_again();
   tries = 0; 
 } while(again);
 nocbreak(); echo(); endwin();
 return EXIT_SUCCESS;

}</lang>

Java

<lang java5>import java.util.InputMismatchException; import java.util.Random; import java.util.Scanner;

public class BullsAndCows{ public static void main(String[] args){ Random gen= new Random(); int target= 0; while(hasDupes(target= (gen.nextInt(9000) + 1000))); String targetStr = target +""; boolean guessed = false; Scanner input = new Scanner(System.in); int guesses = 0; do{ int bulls = 0; int cows = 0; System.out.print( "Guess a 4-digit number with no duplicate digits: "); int guess; try{ guess = input.nextInt(); if(hasDupes(guess)) continue; }catch(InputMismatchException e){ continue; } guesses++; String guessStr = guess + ""; for(int i= 0;i < 4;i++){ if(guessStr.charAt(i) == targetStr.charAt(i)){ bulls++; }else if(targetStr.contains(guessStr.charAt(i)+"")){ cows++; } } if(bulls == 4){ guessed = true; }else{ System.out.println(cows+" Cows and "+bulls+" Bulls."); } }while(!guessed); System.out.println("You won after "+guesses+" guesses!"); }

public static boolean hasDupes(int num){ boolean[] digs = new boolean[10]; while(num > 0){ if(digs[num%10]) return true; digs[num%10] = true; num/= 10; } return false; } }</lang> Output:

Guess a 4-digit number with no duplicate digits: 5834
2 Cows and 0 Bulls.
Guess a 4-digit number with no duplicate digits: 1234
1 Cows and 0 Bulls.
Guess a 4-digit number with no duplicate digits: 4321
1 Cows and 0 Bulls.
Guess a 4-digit number with no duplicate digits: 3421
0 Cows and 1 Bulls.
Guess a 4-digit number with no duplicate digits: 8412
0 Cows and 0 Bulls.
Guess a 4-digit number with no duplicate digits: 3560
1 Cows and 1 Bulls.
Guess a 4-digit number with no duplicate digits: 3650
0 Cows and 2 Bulls.
Guess a 4-digit number with no duplicate digits: 3759
2 Cows and 2 Bulls.
Guess a 4-digit number with no duplicate digits: 3975
2 Cows and 2 Bulls.
Guess a 4-digit number with no duplicate digits: 3957
You won after 10 guesses!

Python

<lang python>

Bulls and cows. A game pre-dating, and similar to, Mastermind.

import random

digits = '123456789' size = 4 chosen = .join(random.sample(digits,size))

  1. print chosen # Debug

print I have chosen a number from %s unique digits from 1 to 9 arranged in a random order. You need to input a %i digit, unique digit number as a guess at what I have chosen % (size, size) guesses = 0 while True:

   guesses += 1
   while True:
       # get a good guess
       guess = raw_input('\nNext guess [%i]: ' % guesses).strip()
       if len(guess) == 4 and \
          all(char in digits for char in guess) \
          and len(set(guess)) == size:
           break
       print "Problem, try again. You need to enter %i unique digits from 1 to 9" % size
   if guess == chosen:
       print '\nCongratulations you guessed correctly in',guesses,'attempts'
       break
   bulls = cows = 0
   for i in range(size):
       if guess[i] == chosen[i]:
           bulls += 1
       elif guess[i] in chosen:
           cows += 1
   print '  %i Bulls\n  %i Cows' % (bulls, cows)</lang>

Sample output:

I have chosen a number from 4 unique digits from 1 to 9 arranged in a random order.
You need to input a 4 digit, unique digit number as a guess at what I have chosen

Next guess [1]: 79
Problem, try again. You need to enter 4 unique digits from 1 to 9

Next guess [1]: 7983
  2 Bulls
  2 Cows

Next guess [2]: 7938

Congratulations you guessed correctly in 2 attempts