BBC BASIC for Windows
General >> General Board >> Please help me :/
http://bb4w.conforums.com/index.cgi?board=general&action=display&num=1368642381

Please help me :/
Post by Sam on May 15th, 2013, 6:26pm

Hi guys, I'm trying to create a program which (very basically) draws 52 cards. However, I can't get them to not repeat. Also, the last bit doesn't work either because if I input something other than Y or N it still restarts the program. Please help, and thank you SO much in advance! :S


Here's the code:

*ESC OFF
OFF


10 DIM Cards(13,4)
REPEAT
FORI% = 1 TO 52
PRINT ""


20 SuitR% = RND(4)
ValueR% = RND(13)
IF Cards(ValueR%,SuitR%) = 1 GOTO 20


CASE SuitR% OF


WHEN 1:
CASE ValueR% OF
WHEN 1: PRINT " Ace of Spades"
WHEN 11: PRINT " Jack of Spades"
WHEN 12: PRINT " Queen of Spades"
WHEN 13: PRINT " King of Spades"
OTHERWISE: PRINT ValueR% ; " of Spades"
ENDCASE


WHEN 2:
CASE ValueR% OF
WHEN 1: COLOUR 9
PRINT " Ace of Hearts"
COLOUR 0
WHEN 11: COLOUR 9
PRINT " Jack of Hearts"
COLOUR 0
WHEN 12: COLOUR 9
PRINT " Queen of Hearts"
COLOUR 0
WHEN 13: COLOUR 9
PRINT " King of Hearts"
COLOUR 0
OTHERWISE: COLOUR 9
PRINT ValueR% ; " of Hearts"
COLOUR 0
ENDCASE


WHEN 3:
CASE ValueR% OF
WHEN 1: COLOUR 9
PRINT " Ace of Diamonds"
COLOUR 0
WHEN 11: COLOUR 9
PRINT " Jack of Diamonds"
COLOUR 0
WHEN 12: COLOUR 9
PRINT " Queen of Diamonds"
COLOUR 0
WHEN 13: COLOUR 9
PRINT " King of Diamonds"
COLOUR 0
OTHERWISE: COLOUR 9
PRINT ValueR% ; " of Diamonds"
COLOUR 0
ENDCASE


WHEN 4:
CASE ValueR% OF
WHEN 1: PRINT " Ace of Clubs"
WHEN 11: PRINT " Jack of Clubs"
WHEN 12: PRINT " Queen of Clubs"
WHEN 13: PRINT " King of Clubs"
OTHERWISE: PRINT ValueR% ; " of Clubs"
ENDCASE


Cards(ValueR%,SuitR%) = 1
ENDCASE


PRINT ""
PRINT ""
PRINT ""
COLOUR 2
INPUT "Deal next card with 'Enter'" card$
COLOUR 0
CLS


30 NEXT I%
INPUT " Go again? (y/n) " choice$
IF choice$ = "n" OR choice$ = "N" THEN : QUIT
IF choice$ = "y" OR choice$ = "Y" THEN : CLS GOTO 10
ELSE GOTO 30
ENDIF
UNTIL FALSE

Re: Please help me :/
Post by Star Trek Tshirt Steve on May 15th, 2013, 7:07pm

Hi Sam, I can't see any problems with your coding :/ sorry. I think that you should ask you teacher about this in an upcoming lesson.
Re: Please help me :/
Post by The real Star Trek TShirt on May 15th, 2013, 7:10pm

Who's this imposter! I am the true STAR TREK T-SHIRT STEVE!

Re: Please help me :/
Post by Michael Hutton on May 15th, 2013, 7:18pm

I'll give you a clue but not the answer.

Look at the line:

Cards(ValueR%,SuitR%) = 1

and then try to figure out when it is actually being run (for instance, put a PRINT"Hello":G=GET just before it.)

It is all to do with the prgram flow and how the CASE..ENDCASE is being used.

Also, you might want to check out the Wiki here:
http://bb4w.wikispaces.com/Notes+on+the+use+of+RND
which will give you some clues. Also, search the yahoo groups for 'shuffle' and you'll find some talk of this in the past.


Michael

Re: Please help me :/
Post by Sam on May 15th, 2013, 7:42pm

Thanks, Michael. Unfortunately I'm not too up to date with my BASIC knowledge. Could you give me any other tips? This has to be done urgently and my friend and I are starting to panic as we can't work this out. Also, can you see a problem with our closing few lines? They don't seem to work and I can think of no logical reason why :/ Thank you very, very much!
Re: Please help me :/
Post by Michael Hutton on May 15th, 2013, 8:52pm

I haven't done homework for anyone for ages. C'mon, you can work it out.
Re: Please help me :/
Post by admin on May 15th, 2013, 9:21pm

on May 15th, 2013, 6:26pm, Guest-Sam wrote:
Hi guys, I'm trying to create a program which (very basically) draws 52 cards. However, I can't get them to not repeat.

If you are trying to shuffle a pack of cards there is a standard algorithm for that - it's called the Fisher-Yates or Knuth shuffle:

http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle

There is a BBC BASIC implementation at the bottom of this Wiki article:

http://bb4w.wikispaces.com/Notes+on+the+use+of+RND

However please note that BBC BASIC's RND function is entirely unsuited to shuffling cards, in a 'serious' application, because it simply doesn't have enough 'randomness' to create anything more than a tiny proportion of the total number of possible shuffles. See the paragraph How to do better than RND.

Richard.
Re: Please help me :/
Post by DDRM on May 16th, 2013, 09:28am

To amplify Michael's answer a little, without just re-writing it for you, I bet you don't get many repeated clubs, do you? can you work out why?

As Richard has hinted, you might be better setting up a full pack and shuffling it, then printing out the result. Your approach will spend a lot of time towards the end of the pack searching for a card it hasn't used yet - though modern computers are so fast you probably won't notice it...

If we can't persuade you to restructure the program without labels and GOTOs, at least look at where you have put the labels, and make sure it is really what you mean. That may sort out your problem at the end.

Best wishes,

David
Re: Please help me :/
Post by KenDown on Oct 22nd, 2015, 07:38am

Now that there is no danger of doing Sam's homework for him - and I agree that one learns best by doing! - I thought I would have a go at his little problem. I haven't bothered with Richard's caution about the weakness of RND as this is not a "serious" application.

PROCinit
PROCshowcards(0)
REPEAT
PROCshufflecards
PROCshowcards(20)
PRINT"Continue? Y/N"
g%=GETAND223
UNTILg%=78
END
:
DEFPROCshufflecards
FORj%=1TO4
FORi%=1TO13
a%=RND(13)
b%=RND(13)
c%=RND(4)
d%=RND(4)
SWAPcard$(a%,c%),card$(b%,d%)
NEXT
NEXT

ENDPROC
:
DEFPROCshowcards(t%)
FORi%=1TO13
FORj%=1TO4
PRINTTAB(t%+j%*4,i%)card$(i%,j%)" "
NEXT
NEXT
ENDPROC
:
DEFPROCinit
DIMcard$(13,4)
FORi%=1TO13
CASEi%OF
WHEN1,2,3,4,5,6,7,8,9,10
c$=STR$i%
WHEN11
c$="J"
WHEN12
c$="Q"
WHEN13
c$="K"
ENDCASE
FORj%=1TO4
IFj%<3card$(i%,j%)=CHR$17+CHR$9+c$ELSEcard$(i%,j%)=CHR$17+CHR$0+c$
NEXT
NEXT
ENDPROC

Incidentally, the two lines beginning with a percentage sign are really part of one long line that has been split into three.

Anyone else want to do better or more concisely?
Re: Please help me :/
Post by DDRM on Oct 22nd, 2015, 12:46pm

A Challenge! I LIKE it!
Sorry, I had children of a "Noddy" age a few years ago, and there was a character who said this...

I don't claim it's better, but it is more concise:
Code:
      c$="A23456789TJQK"
      s$="CDHS"
      DIM p&(51)
      p&(0)=0
      FOR c&=1 TO 51
        r&=RND(c&+1)-1
        p&(c&)=p&(r&)
        p&(r&)=c&
      NEXT c&
       FOR c&=0 TO 51
        PRINT TAB((c& MOD 4)*5,(c& DIV 4));MID$(c$,(p&(c&) DIV 4)+1,1)+MID$(s$,(p&(c&) MOD 4)+1,1)
      NEXT c&
      END
 

I haven't checked it rigorously, but I did test it with a routine to check it consistently (5-10 times!) uses all the cards. You can test it lays them out right by changing the shuffling routine to a direct

Code:
p&(c&)=c&
 


It uses an "inside out" Fisher-Yates shuffle to generate the pack already shuffled. Again, I've just used the standard RND function,so it's not casino grade!

I've used byte variables to use less memory - part of "concise", I guess...

Best wishes,

D
Re: Please help me :/
Post by KenDown on Oct 22nd, 2015, 2:50pm

Very nice. Lacks the pretty colours, but that wouldn't add much to its length.

In fact, change the definition of s$ to
s$=CHR$17+CHR$0+"C"+CHR$17+CHR$9+"D"+CHR$17+CHR$9+"H"+CHR$17+CHR$0+"S"

and the actual printing out to
PRINT TAB((c& MOD 4)*5,(c& DIV 4));MID$(c$,(p&(c&) DIV 4)+1,1)+MID$(s$,((p&(c&) MOD 4)*3)+1,3)

and you'll get the suites in colour.

I looked at the Fisher-Yates shuffle that Richard referenced but decided not to try and implement it as I wanted to recreate what Sam might have used. I'm sure that if I had tried, I would have been much more long-winded than you.

That was the same reason for using elements 1-52 of the array instead of 0-51, which is what any *real* programmer would have done!

Now all we need is some smarty-pants to come along and do it all in a single line of code!
Re: Please help me :/
Post by DDRM on Oct 22nd, 2015, 3:39pm

Hi Kendall,

Mine fits fine on a single line of code, if such is your fancy, but it's harder to read... Implementing a game of bridge with it would be a good trick, though! smiley

Clever trick with the colours: I like that!

I used a 0-based array because it makes the MODs and DIVs much easier, even though it's a bit less clear for the "lay reader", and needs adaptation for the string references, which are 1-based (and arguably for the RND calls, too).

Best wishes,

D
Re: Please help me :/
Post by KenDown on Oct 22nd, 2015, 4:04pm

Of course, what I had in mind was the old BBC Micro, where lines were limited to 246 bytes (or something like that), so fitting a complete program onto a line called for exquisite programming and no small amount of devious cunning.

I absolutely agree with your reasons for beginning your array with element zero and always do the same myself (well, nearly always!)