Jun 12, 2013

Cow and Bull In Salesforce - Let's Brainstorm

Hope may of you are aware of the game Cow & Bull, but those who are not here are the rules

1) Computer will generate a 4 digit number which you need to guess in less than 10 chances
2) This number will not start from 0
3) All digits of the number will be unique (no digit will repeat)

For example:

1234 - is correct
0234 - is wrong
3445 - is wrong

Now user will input a 4 digit number which doesn't starts with 0 and all digits are unique. Computer will then compare with it's generated number and tell you the count of cows and bulls.

What is Cow and Bull

1) Cow: When digits of your number matches digits of computer's generated number on same index

For example: Computer generated > 4580

Your guess > 4619
Count of cows will be one as only one digit matches on same index.

If your guess is > 4689
Then count of cows will be 2 as "4" and "8" both matches at same index

2) Bull: When digit of your number matches digits of computer's generated number but not on same index

For example: Computer generated > 4580

Your guess > 6419
Count of bulls will be one as only one digit ("4") matches (but on same index).

If your guess is > 4689
Then count of bulls will be 2 as "4" and "8" both matches (but on same index)

So if you guessed 4851, then there is ONE cow ("4") and TWO bulls ("8" and "5")



Now it's time to use the brain, here is the site link: http://bmprojects-developer-edition.ap1.force.com/CB_CowAndBull


VFP:


<apex:page controller="CB_CowAndBullController" showHeader="false" sidebar="false">
    <apex:form id="FRM">
        <apex:pageBlock id="PB" title="Cow And Bull">
            
            <apex:pageMessage severity="INFO" escape="false">
                1) Enter 4 digit number which have all digits unique and is not starting from 0 <br/><br/>
                2) Cows: Digits from your number matches computer's number at same index <br/>
                e.g: You Enter -> 1234 and Computer Number -> 1960 <br/>
                1 matches on same index so it will be counted as cow <br/><br/>
                3) Bulls: Digits from your number matches computer's number but not on same index <br/>
                e.g: You Enter -> 1234 and Computer Number -> 9120 <br/>
                1 and 2 matches but not on same index so it will be counted as bull
            </apex:pageMessage>
            <apex:pageMessages id="PM"/>
            
            <apex:pageBlockButtons rendered="{!IF(showButton , true , false)}">
                <apex:commandButton value="Check C&B" action="{!CheckCandB}"/>
            </apex:pageBlockButtons>
            
            <!-- <apex:outputText value="Computer Generated Number : {!CompNumber}"/> -->
            
            <apex:pageBlockSection id="PBS1">
                <apex:pageBlockSectionItem id="PBSI1">
                    <apex:outputLabel value="Please Enter Your Number:"/>
                    <apex:inputText size="4" value="{!userEnteredNUmber}"/>
                </apex:pageBlockSectionItem>
            </apex:pageBlockSection>
            
            <apex:pageBlockTable rendered="{!IF(toDisplayWrapperLst.size > 0 , true, false)}" value="{!toDisplayWrapperLst}" var="wrap">
                <apex:column headerValue="Your Input" value="{!wrap.userInput}"/>
                <apex:column headerValue="Cows" value="{!wrap.cow}"/>
                <apex:column headerValue="Bulls" value="{!wrap.bull}"/>
            </apex:pageBlockTable>
        
        </apex:pageBlock>
    </apex:form>
</apex:page>


Apex Code:


public class CB_CowAndBullController
{
    public Integer CompNumber {get; set;}
    public Integer userEnteredNUmber {get; set;}
    //To maintain the user inputs
    public List<userInputResults> toDisplayWrapperLst {get; set;}
    //Flag to show the button which compare the user input with computer's generated number
    public boolean showButton {get; set;}
    
    public CB_CowAndBullController()
    {
        //Number entered by user
        userEnteredNUmber = 0 ;
        
        showButton = true ;
        
        toDisplayWrapperLst = new List<userInputResults>() ;
        
        //Generating 4 digit number which doesn't start with 0 and no number is repeated
        boolean flag = false ;
        while(!flag)
        {
            Integer tempVar = Integer.valueOf(Math.Random() * 10000) ;
            if(checkNumber(tempVar))
            {
                flag = true ;
                CompNumber = tempVar ;
            }
        }
    }
    
    private Boolean checkNumber(Integer num)
    {
        //Pattern for 4 digit number which doesn't start with 0 and no number is repeated
        Pattern nonZeroPattern = Pattern.compile('([1-9])(?!.*\\1)([0-9])(?!.*\\2)([0-9])(?!.*\\3)([0-9])(?!.*\\4)');
        Matcher nonZeroMatcher = nonZeroPattern.matcher(''+num);
        if(nonZeroMatcher.matches())
             return true;
        else
            return false ;
    }
    
    public PageReference CheckCandB()
    {
        if(checknumber(userEnteredNUmber))
        {
            //Logic to compare user input and computer's generated number
            Integer cow = 0 ;
            Integer bull = 0 ;
            String UEN = string.valueOf(userEnteredNUmber) ;
            String CGN = string.valueOf(CompNumber) ;
            
            for(Integer i = 0 ; i < UEN.length() ; i++)
            {   
                for(Integer j = 0 ; j < CGN.length() ; j++)
                {
                    if(UEN.subString(i , i+1) == CGN.subString(j , j+1))
                    {
                        if(i == j)
                            cow = cow + 1 ;
                        else
                            bull = bull + 1 ;
                    }
                }
            }
            toDisplayWrapperLst.add(new userInputResults(cow, bull, userEnteredNUmber)) ;

            if(cow == 4)
            {
                showButton = false ;
                ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.INFO,'Congratulations! You guessed it right in ' + toDisplayWrapperLst.size() + ' chances.'));
            }
            else
            {
                if(toDisplayWrapperLst.size() > 9)
                {
                    showButton = false ;
                    ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR,'You failed to guess the number in 10 chances. Better luck next time.'));
                }
            }
        }
        else
        {
            ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR,'Please enter a 4 digit number which does not start with 0 and no number is repeated' ));
        }
        return null ;
    }
    
    //Wrapper to maintain number of cows, bulls and user input
    public class userInputResults
    {
        public Integer cow {get; set;}
        public Integer bull {get; set;}
        public Integer userInput {get; set;}
        
        public userInputResults(Integer c, Integer b, Integer ui)
        {
            cow = c ;
            bull = b;
            userInput = ui ;
        }
    }
}


Would love to hear the feedback.