Task: Bulls and cows








VB: Option Explicit

Sub Main_Bulls_and_cows()
Dim strNumber As String, strInput As String, strMsg As String, strTemp As String
Dim boolEnd As Boolean
Dim lngCpt As Long
Dim i As Byte, bytCow As Byte, bytBull As Byte
Const NUMBER_OF_DIGITS As Byte = 4
Const MAX_LOOPS As Byte = 25 

    strNumber = Create_Number(NUMBER_OF_DIGITS)
    Do
        bytBull = 0: bytCow = 0: lngCpt = lngCpt + 1
        If lngCpt > MAX_LOOPS Then strMsg = "Max of loops... Sorry you loose!": Exit Do
        strInput = AskToUser(NUMBER_OF_DIGITS)
        If strInput = "Exit Game" Then strMsg = "User abort": Exit Do
        For i = 1 To Len(strNumber)
            If Mid(strNumber, i, 1) = Mid(strInput, i, 1) Then
                bytBull = bytBull + 1
            ElseIf InStr(strNumber, Mid(strInput, i, 1)) > 0 Then
                bytCow = bytCow + 1
            End If
        Next i
        If bytBull = Len(strNumber) Then
            boolEnd = True: strMsg = "You win in " & lngCpt & " loops!"
        Else
            strTemp = strTemp & vbCrLf & "With : " & strInput & " ,you have : " & bytBull & " bulls," & bytCow & " cows."
            MsgBox strTemp
        End If
    Loop While Not boolEnd
    MsgBox strMsg
End Sub

Function Create_Number(NbDigits As Byte) As String
Dim myColl As New Collection
Dim strTemp As String
Dim bytAlea As Byte

    Randomize
    Do
        bytAlea = Int((Rnd * 9) + 1)
        On Error Resume Next
        myColl.Add CStr(bytAlea), CStr(bytAlea)
        If Err <> 0 Then
            On Error GoTo 0
        Else
            strTemp = strTemp & CStr(bytAlea)
        End If
    Loop While Len(strTemp) < NbDigits
    Create_Number = strTemp
End Function

Function AskToUser(NbDigits As Byte) As String
Dim boolGood As Boolean, strIn As String, i As Byte, NbDiff As Byte

    Do While Not boolGood
        strIn = InputBox("Enter your number (" & NbDigits & " digits)", "Number")
        If StrPtr(strIn) = 0 Then strIn = "Exit Game": Exit Do
        If strIn <> "" Then
            If Len(strIn) = NbDigits Then
                NbDiff = 0
                For i = 1 To Len(strIn)
                    If Len(Replace(strIn, Mid(strIn, i, 1), "")) < NbDigits - 1 Then
                        NbDiff = 1
                        Exit For
                    End If
                Next i
                If NbDiff = 0 Then boolGood = True
            End If
        End If
    Loop
    AskToUser = strIn
End Function



Fortran: module bac
  implicit none

contains

  subroutine Gennum(n)
    integer, intent(out) :: n(4)
    integer :: i, j
    real :: r
      
    call random_number(r)
    n(1) = int(r * 9.0) + 1
    i = 2
    
outer: do while (i <= 4)
         call random_number(r)
         n(i) = int(r * 9.0) + 1
inner:   do j = i-1 , 1, -1
           if (n(j) == n(i)) cycle outer
         end do inner
         i = i + 1
       end do outer
 
  end subroutine Gennum

  subroutine Score(n, guess, b, c) 
    character(*), intent(in) :: guess
    integer, intent(in) :: n(0:3)
    integer, intent(out) :: b, c
    integer :: digit, i, j, ind
   
    b = 0; c = 0
    do i = 1, 4
      read(guess(i:i), "(i1)") digit
      if (digit == n(i-1)) then
        b = b + 1
      else
        do j = i, i+2
          ind = mod(j, 4)
          if (digit == n(ind)) then
            c = c + 1
            exit
          end if
        end do    
      end if
    end do  

 end subroutine Score  

end module bac

program Bulls_and_Cows
   use bac
   implicit none
   
   integer :: n(4)
   integer :: bulls=0, cows=0, tries=0
   character(4) :: guess

   call random_seed
   call Gennum(n)
   
   write(*,*) "I have selected a number made up of 4 digits (1-9) without repetitions."
   write(*,*) "You attempt to guess this number."
   write(*,*) "Every digit in your guess that is in the correct position scores 1 Bull"
   write(*,*) "Every digit in your guess that is in an incorrect position scores 1 Cow"
   write(*,*)

   do while (bulls /= 4)
     write(*,*) "Enter a 4 digit number"
     read*, guess
     if (verify(guess, "123456789") /= 0) then
       write(*,*) "That is an invalid entry. Please try again."
       cycle
     end if
     tries = tries + 1
     call Score (n, guess, bulls, cows)
     write(*, "(a, i1, a, i1, a)") "You scored ", bulls, " bulls and ", cows, " cows"
     write(*,*)
   end do

   write(*,"(a,i0,a)") "Congratulations

end program Bulls_and_Cows