Bulls and Cows game. Part 1

Hello! The quarantine was fruitful and decided to write a time-killer toy "Bulls and Cows". The game is not that difficult, but quite interesting. Usually the game uses 4 numbers that need to be guessed. The computer guesses the number, the user enters his 4 numbers, if the digit in the user's number coincides in position with the position in the hidden number, then this is a bull, but if it is not in its place, then it is a cow. More detailed rules are easy to find on the internet. In this part, we will deal with the BackEnd, in the future we will add FrontEnd, guessing the user's number and perhaps that's all. Well, let's get started!



First of all, I created a BackEnd class that will be responsible for all the work of the program. It has fields:



    private int length;             // 
    private int[] mas;              //  
    private int[] inputArray;       //,  


The idea is as follows: the computer generates a number mas of length length, the user enters the number inputArray and sees how many bulls and cows it contains, and then wins or continues to play. First, we will output the mas array to see the number and debug the code. then we will remove this line. Let's write the output of an array of arbitrary length:



    private void printMas(int[] mas) {
        for (int i = 0; i < length; i++) {
            System.out.print(mas[i] + "   ");
        }
    } 


We pass an array to this method, which we will output through the for loop. It could have been done through the field, but since we will output mas first, and then inputArray, I decided to do this.



Now we need to create a number generation. you can do this with standard functions, but do not forget that we need different digits in the number. This means that the number 45566 will not work, but 45367 will be just right. Let's write a method for generating such a number with the verification of the digits, but first, let's find out how long the user wants to guess the number:



private void getMas() {
        Scanner scanner = new Scanner(System.in);
        do {
            System.out.println("    1  10");
            while (!scanner.hasNextInt()) {
                System.out.println(" ");
                scanner.next();
            }
            length = scanner.nextInt();
        } while (length <= 0 || length > 10);
        setMas(createMas());
    }


We create a scanner object with which we will get the number from the console. Next, we use a loop with a do while postcondition. I'll explain why this is a little later. In the body of the loop, we see a while loop. it is used to verify that a number is entered in the console, not a fraction, letters, etc. After we have verified that the number is entered into the console, we write its value in length. And now, using the do while postcondition, we check that it belongs to the interval [0,10). If a number is entered that is not included in the interval, then we again ask you to enter the length. If the number is entered correctly at once, then we generate the number using the createMas method and change the value of the mas field:



 public void setMas(int[] mas) {
        this.mas = mas;
    }


private int[] createMas() {
        int[] arr = new int[length];
        for (int i = 0; i < this.length; i++) {
            arr[i] = (int) (Math.random() * 10);
        }
        boolean checkMas = false;
        while (!checkMas) {
            for (int i = 0; i < arr.length; i++) {
                for (int j = 0; j < arr.length; j++) {
                    if (i != j) {
                        if (arr[i] == arr[j]) {
                            arr[j] = (int) (Math.random() * 10);
                        }
                    }

                }
            }


            boolean check = false;
            for (int i = 0; i < arr.length && !check; i++) {
                for (int j = 0; j < arr.length && !check; j++) {

                    if (i != j) {
                        if (arr[i] == arr[j]) {
                            check = true;
                            checkMas = false;
                        } else checkMas = true;
                    }
                }
            }

        }
        return arr;
    }


Let me explain how createMas works. First, we create an array of length length and fill it with random numbers from the interval [0,10). Math.random () generates a random number from the interval [0,1), and multiplying it by 10 we get a number in the interval [0,10). We now have an array arr, which consists of random digits. The next step is to check it for repeating numbers. I decided to do this using boolean variables. First, we compare each element with each and, if there is a match, change the element we are comparing with by a random number. After we have compared all the elements, we check the array for uniqueness of the digits. for this, I also created the check variable. Then we just compare each element with each. If you find 2 identical elements, then exit the for comparison (since! Check will return false and the loops will end),and return to the for loops to change the same numbers. After all the numbers in the array are different, the checkMas variable becomes true and the check of the array ends. Now we return the arr array and make the field mas = arr.



We now have a computer-conceived number. Let's implement guessing of this number by the user. To do this, let's write the checkInput method:



private void checkInput() {
        Scanner scanner = new Scanner(System.in);
        int[] arr = new int[length];
        if (length == 1) System.out.println(" " + length + "   ");
        else {
            if (length > 1 && length < 5) {
                System.out.println(" " + length + "   ");
            } else {
                if (length > 4 && length < 11) {
                    System.out.println(" " + length + "   ");
                }
            }
        }
        boolean checkMas = false;
        while (!checkMas) {
            for (int i = 0; i < length; i++) {
                do {
                    System.out.println("  ");
                    while (!scanner.hasNextInt()) {
                        System.out.println(" ");
                        scanner.next();
                    }
                    arr[i] = scanner.nextInt();
                    if(arr[i] < 0 || arr[i]>=10) System.out.println("   0  9 ");
                } while (arr[i] < 0 || arr[i] >= 10);
            }
            
            boolean check = checkInputArray(arr);
            if (check) {
                checkMas = true;
            } else {
                System.out.println("    ");
                System.out.println("  ");
            }
        }
        setInputArray(arr);

    }


Similarly, we create scanner and an auxiliary array arr of length length. Next comes a bunch of ifs, which are responsible for no more than matching a number and a phrase. After them there is a direct input and verification of the user's number. So that there is no disagreement in the logic with the user, I decided to make it so that the user would enter each number separately.



for (int i = 0; i < length; i++) {
                do {
                    System.out.println("  ");
                    while (!scanner.hasNextInt()) {
                        System.out.println(" ");
                        scanner.next();
                    }
                    arr[i] = scanner.nextInt();
                    if(arr[i] < 0 || arr[i]>=10) System.out.println("   0  9 ");
                } while (arr[i] < 0 || arr[i] >= 10);
            }


It is in this section of the code that the number is entered and checked. The work is similar to entering the length of the array, so I see no reason to explain it. Then the user array is checked for the presence of the same numbers. To do this, let's write the checkInputArray method:



private boolean checkInputArray(int[] arr) {
        boolean checkMas = false;
        boolean check = false;
        for (int i = 0; i < arr.length && !check; i++) {
            for (int j = 0; j < arr.length && !check; j++) {

                if (i != j) {
                    if (arr[i] == arr[j]) {
                        check = true;
                        checkMas = false;
                    } else checkMas = true;
                }
            }
        }
        return checkMas;
    }


Checking is similar to checking a hidden array, so I won't dwell on it. If the user's number contains duplicate numbers, then we ask you to enter the whole number again. And so on until it is entered correctly. Then we change the value of the inputArray field to our auxiliary array arr. Just in case, I will give the code:



public void setInputArray(int[] inputArray) {
        this.inputArray = inputArray;
    }


At this point, we have two arrays: the hidden array and the input array. It's time to find out how many bulls and how many cows the user found.



We will find out this using the checkCowAndBull method:



private int[] checkCowAndBull() {
        int[] arr = new int[2];
        int cow = 0;
        int bull = 0;
        for (int i = 0; i < length; i++) {
            for (int j = 0; j < length; j++) {

                if (mas[i] == inputArray[j]) {
                    if (i == j) bull++;
                    else cow++;
                }
            }
        }
        arr[0] = cow;
        arr[1] = bull;
        return arr;
    }


We are creating an auxiliary 2 element array. The first is the number of cows, the second is the number of bulls. Then we iterate over both arrays, comparing the elements. If the elements are equal and their indices are equal, then we increase the number of bulls, otherwise we increase the number of cows. After that, we write the values ​​to the array and return it.



It's time to figure out what was in the constructor of the BackEnd class all this time.



public BackEnd() {
        getMas();
        //printMas(mas);
        boolean win = false;
        while (!win) {
            checkInput();
            System.out.println(" :");
            printMas(inputArray);
            System.out.println();
            int[] arr = checkCowAndBull();
            if (arr[1] == length) {
                win = true;
                System.out.println("!  !");
            } else {
                System.out.println("   " + arr[0] + " , " + arr[1] + " ");
                System.out.println("  ");
            }
        }
    }


First, we generate the intended array. I output it for debugging, but this function is not needed for the game. Since we do not know from what attempt the user will guess the number, we start the while loop until the appropriate moment. Then we ask the user to enter his number, display the entered array, check the number of bulls and cows. If the number of bulls matches the length of the array, then the number is guessed and the game is over. Otherwise, the number of bulls and cows is displayed and the game continues.



It remains only to add the creation of an instance of the class to man:



public class main {
    public static void main(String[] args) {
        BackEnd bk = new BackEnd();
    }
}


We launch, check, play.



Thank you for your attention, the second part will be coming soon.



All Articles