April 16, 2024, 05:05:53 AM

News:

Own IWBasic 2.x ? -----> Get your free upgrade to 3.x now.........


Magic Squares

Started by GWS, November 04, 2008, 03:38:10 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

GWS

Hi folks,

Here's a little puzzle to test your mental arithmetic .. resurrected from the old Pyxia forum .. :)

The code tries out a pseudo-Edit box which accepts a Return key to complete the data entry - something a normal edit box can't do without a lot of fiddling. It works by using an off-screen edit box to keep track of the data entry, and uses GetKey to detect the Return keypress.

Here's the code:


'
' EBasic Magic Square - GWS - June 2004
'
int i,j,k,n,r,g,b,mx,my,x,y,z
int test1,test2,test3,stopit,another
int groupx,groupy,sdev,col,c,d,e
int xpos,ypos,querymouse,xp,yp
int sl,st,marked,userreply,tW,tH
float pi,x1,x2,ret
pointer sprite1,spriten,spritex,sback
string aclue,a$,e$,r$
int a[10],q[10],sq[10,3]
autodefine "OFF"
pi = 4 * atan(1)
querymouse = true: ' mouse enabled
marked = 0: ' no square is marked
userreply = true: ' no reply to be displayed
if CREATESCREEN(800,600,32,&screenhandler) < 0
  MESSAGEBOX 0,"Error creating screen","Error"
  END
endif
Fillscreen RGB(0,0,50), FrontBuffer
FRONTPEN BackBuffer,RGB(100,100,240)
BACKPEN BackBuffer, RGB(50,50,100)
sback = CREATESPRITE(750,520,1,1)
gosub NextPuzzle
sprite1 = CREATESPRITE(80,80,1,1)
spritetobuffer sprite1
DRAWFILLEDRECT 5,5, 70, 70, RGB(50,50,100),SpriteBuffer
spriten = CREATESPRITE(100,25,1,1)
spritetobuffer spriten
Fillscreen RGB(0,0,0), SpriteBuffer
DRAWFILLEDRECT 0,0, 100, 25, RGB(50,50,100),SpriteBuffer

spritex = CREATESPRITE(100,25,1,1)
spritetobuffer spritex
Fillscreen RGB(0,0,0), SpriteBuffer
DRAWFILLEDRECT 0,0, 100, 25, RGB(50,50,100),SpriteBuffer

' create an off-screen edit control ..
CONTROL backbuffer,@edit,"",-50,-20,50,20,0,1
'----------------------------------------------------------------------
do
   FILLSCREEN RGB(0,0,50)
' draw background sprite ..
   DrawSpriteXY sback,25,25
' (note: set the data pointer to the beginning or this doesn't work ..)
   restore squares
   for i = 1 to 7 step 3
      getdata squares,xp
      for j = 0 to 2
         getdata squares,yp
         DrawSpriteXY sprite1,xp,yp
' remember the square locations ..
         sq[i+j,1] = xp
         sq[i+j,2] = yp
      next j
   next i
' place the numbers on the screen ..
   k = -1
   setfont BackBuffer,"Times Roman",20,600
   for y = 1 to 7 step 3
      k = k + 1
      for z = 0 to 2
         xpos = 300 + k * 82
         ypos = 155 + z * 82
         if q[y+z] = 30
            WRITETEXT xpos, ypos, "??"
         else
            a$ = USING("##", q[y+z])
            WRITETEXT xpos, ypos, a$   
         endif
      next z
   next y
   
   setfont BackBuffer,"Times Roman",16,400
   WRITETEXT 285, 0, "  EBasic Magic Square  "
   setfont BackBuffer,"Times Roman",12,300
   aclue = "Clue:  All Rows and Columns add to the same number."
   WRITETEXT 200, 480, aclue
   SpriteDrawMode spriten, @TRANS
   DrawSpriteXY spriten,146,560
   setfont BackBuffer,"Times Roman",14,400
   WRITETEXT 180, 561, "Next"
   SpriteDrawMode spritex, @TRANS
   DrawSpriteXY spritex,550,560
   setfont BackBuffer,"Times Roman",14,400
   WRITETEXT 584, 561, "Exit"
' current mouse co-ordinates and left button status ..
   mx = MOUSEX()
   my = MOUSEY()
   test3 = mousedown(1)
' only do the next tests if the left mouse button is pressed
' and Querymouse is true ..
   if querymouse and test3
' test for Next button clicked ..
      test1 = mx > 146 and mx < 246
      test2 = my > 560 and my < 585
      if (test1 and test2) then another = 1
      if another
       starttimer backbuffer,500,1
         another = 0
         querymouse = false
         gosub NextPuzzle
      endif
' test for Exit button clicked ..
      test1 = mx > 546 and mx < 646
      test2 = my > 560 and my < 585
      if (test1 and test2) then stopit = 1
' check if clicked within the squares region ..
      test1 = mx > sq[1,1] and mx < sq[7,1] + 80
      test2 = my > sq[1,2] and my < sq[3,2] + 80
      if (test1 and test2)
' test for a '??' box clicked ..
         for i = 1 to 9
            if q[i] = 30 :' is it a ?? square ..
' check if the mouse is within the '??' square ..
               sl = sq[i,1] : st = sq[i,2]: ' box left and top positions
               test1 = (mx > sl) and (mx < sl + 80)
               test2 = (my > st) and (my < st + 80)
               if (test1 and test2)
' mouse clicked within '??' square 'i'..
' display the marker
                  DRAWRECT sq[i,1], sq[i,2], 80, 80, RGB(255,0,0)
' note which square is marked ..
                  marked = i
               endif
            endif   
         next i
      else
' clicked outside the boxes region ..
         marked = 0
         setcontroltext backbuffer,1,""
      endif
   else
' mouse left button not down (or querymouse is false due to Next being pressed) ..
      if querymouse and marked
' a '??' square is already marked ..
         DRAWRECT sq[marked,1], sq[marked,2], 80, 80, RGB(255,0,0)
' get user input ..
         DRAWFILLEDRECT 360, 401, 70, 23, RGB(0,50,120)
         setfocus backbuffer,1
         a$ = "Type the number you think it is and press Enter."
         FRONTPEN BackBuffer,RGB(0,150,150)
         BACKPEN BackBuffer, RGB(0,0,50)
         setfont BackBuffer,"Times Roman",12,400
         WRITETEXT 250, 430, a$
         e$ = getkey
         a$ = getcontroltext(backbuffer ,1)
         setfont BackBuffer,"Times Roman",16,400
         FRONTPEN BackBuffer,RGB(200,200,240)
         BACKPEN BackBuffer, RGB(0,50,120)
         GETTEXTSIZE backbuffer, a$, tW, tH
         k = (800-tW)/2 - 5
         WRITETEXT k, 401, a$
         FRONTPEN BackBuffer,RGB(100,100,240)
         BACKPEN BackBuffer, RGB(50,50,100)
' check for Enter pressed ..
         if asc(e$) = 13
            starttimer backbuffer,50,3
' is it the right answer ..
            if val(a$) = a[marked]
' correct answer ..
               r$ = "  correct  "
            else
' wrong answer ..
               r$ = "  wrong  "
            endif
            starttimer backbuffer,1000,2
         endif
      endif
   endif
' show the result ..
   if userreply
      BACKPEN BackBuffer, RGB(0,0,50)
      select r$
         case "  correct  "
            FRONTPEN BackBuffer,RGB(0,200,40)   
         case "  wrong  "
            FRONTPEN BackBuffer,RGB(200,0,40)
      endselect
      GETTEXTSIZE backbuffer, r$, tW, tH
      k = (800-tW)/2 -5
      WRITETEXT k, 401, r$
      FRONTPEN BackBuffer,RGB(100,100,240)
      BACKPEN BackBuffer, RGB(50,50,100)
   endif
   FLIP
until stopit = 1
'----------------------------------------------------------------------
FREESPRITE sprite1
FREESPRITE spriten
FREESPRITE spritex
FREESPRITE sback
CLOSESCREEN
END
SUB screenhandler

   select @MESSAGE
      case @IDTIMER
         if (@code = 1)
            querymouse = true
            stoptimer backbuffer,1
         endif
         if (@code = 2)
            stoptimer backbuffer,2
            if r$ = "  correct  " then q[marked] = a[marked]
            marked = 0
            userreply = false
            setcontroltext backbuffer,1,""
            r$ = ""
         endif
         if (@code = 3)
            userreply = true
            stoptimer backbuffer,3
         endif
   endselect

return
ENDSUB

sub NextPuzzle
' generate the next numbers ..
spritetobuffer sback
Fillscreen RGB(0,0,50), SpriteBuffer
' create some coloured spots fot the background ...
for i = 1 to 10
   groupx = rnd(500)+100
   groupy = rnd(300)+100
   sdev = 30
   col = rgb(rnd(200),rnd(200),rnd(200))
   for j = 1 to 1000
      x = splot() * sdev + groupx
      y = splot() * sdev + groupy
      writepixel x,y,col, SpriteBuffer
   next j
next i
'generate the numbers ..
c = 1 + rand(9)
do
   d = 1 + rand(9)
until d <> c
do
   e = 1 + rand(9)
until (e <> c) & (e <> d)
a[1] = c + d
a[2] = c - (d + e)
a[3] = c + e
a[4] = c - d + e
a[5] = c
a[6] = c + d - e
a[7] = c - e
a[8] = c + d + e
a[9] = c - d
for i = 1 to 9
   q[i] = a[i]
next i
q[c] = 30
q[d] = 30
q[e] = 30
return
endsub

sub splot(),float
' routine to give a random value from the Normal distribution ..
float x1,x2,ret
x1 = rnd(1.0)
x2 = rnd(1.0)
' catch very small (near zero) values of x1 ..
if (x1 < 1.0e-5) then x1 = 1.0e-5
' the Normal curve value ..
ret = sqrt(-2.0*log(x1)) * cos(2*pi*x2)

return ret
endsub

databegin squares
data 275,130,212,294,357,130,212,294,439,130,212,294
dataend





all the best, :)

Graham
Tomorrow may be too late ..