Qbasicnews.com

Full Version: Rotating a squared matrix
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Pages: 1 2 3
Hi, I'm working on a image (Tile) editor in Qbasic and my Rotate 90 degrees function doesn't work for smaller selections within a bigger image.

So, to solve my problem I need to know how I can achieve this in QBasic:

We have this matrix and the selection I made and I wish to rotate it 90 degrees clockwise:

Before the rotation:
[Image: before.gif]

After the rotation:
[Image: after.gif]

Please help me!

Regards,
Clay Dragon
(01-12-2008, 06:21 AM)Clay Dragon link Wrote:We have this matrix and the selection I made and I wish to rotate it 90 degrees clockwise

You have A(5,5) with content such as

abcde
fghij
klmno
pqrst
uvwxy


Given you select one of the 9 interior cells
ghi
lmn
qrs

You want to rotate the adjacent cells two position clockwise. For example, if the cell chosen is r then you want the result

abcde
fghij
kvqlo
pwrmt
uxsny


Does that restate your problem correctly?

Mac
(01-23-2008, 11:26 AM)Mac link Wrote:Does that restate your problem correctly?

Assuming "yes", this will do it
Code:
' Populate demo array
DIM a(5, 5) AS STRING * 1
FOR i = 1 TO 5: FOR j = 1 TO 5
  k = k + 1
  a(i, j) = MID$("abcdefghijklmnopqrstuvwxy", k, 1)
NEXT j: NEXT i
' Show Rotations
DO: GOSUB Demo: LOOP WHILE R > 0
CLS
SYSTEM

Demo:
R = 0: C = 0
CLS : PRINT "Array Before"
GOSUB DumpA
PRINT "Enter coordinates of pivot point"
DO
  INPUT "Enter 2, 3, or 4. Row"; R
  IF R = 0 THEN RETURN
LOOP WHILE NOT ((R = 2) OR (R = 3) OR (R = 4))
DO
  INPUT "Enter 2, 3, or 4. Column"; C
  IF C = 0 THEN R = 0: RETURN
LOOP WHILE NOT ((C = 2) OR (C = 3) OR (C = 4))
GOSUB Rotate
PRINT "Array After"
GOSUB DumpA
LINE INPUT "Press Enter"; e$
RETURN

Rotate:
c1$ = a(R - 1, C - 1)
c2$ = a(R, C - 1)
a(R - 1, C - 1) = a(R + 1, C - 1)
a(R, C - 1) = a(R + 1, C)
a(R + 1, C - 1) = a(R + 1, C + 1)
a(R + 1, C) = a(R, C + 1)
a(R + 1, C + 1) = a(R - 1, C + 1)
a(R, C + 1) = a(R - 1, C)
a(R - 1, C + 1) = c1$
a(R - 1, C) = c2$
RETURN

DumpA:
FOR i = 1 TO 5
  LOCATE , 30
  FOR j = 1 TO 5
    IF i = R AND j = C THEN COLOR 13, 0 ELSE COLOR 7, 0
    PRINT a(i, j);
  NEXT j
  PRINT
NEXT i
PRINT : PRINT
RETURN
Sorry for coming in so late, mac, but I do appreciate your help very much! However my problem is not simple as that! My first post is describing only a simple example of what I want to achieve! I want to be able to rotate any selection of 2x2, 3x3, 4x4... up to the max of the main matrix ranging from 2x2 up to 56x56.

But I got to admit it is a good start and once again I want to thank you very much for your help, mac! Sadly, I must say I wasn't expecting that such a big code snipet would be necessary to realize my first wish:

Code:
Rotate:
c1$ = a(R - 1, C - 1)
c2$ = a(R, C - 1)
a(R - 1, C - 1) = a(R + 1, C - 1)
a(R, C - 1) = a(R + 1, C)
a(R + 1, C - 1) = a(R + 1, C + 1)
a(R + 1, C) = a(R, C + 1)
a(R + 1, C + 1) = a(R - 1, C + 1)
a(R, C + 1) = a(R - 1, C)
a(R - 1, C + 1) = c1$
a(R - 1, C) = c2$
RETURN

So I guess I have to forget that idea it is to much complicated for me unless, of course, you really want to sort my problem out...

Clay Dragon

P.S. I apologize for my bad english...
usually when you need monstrous amounts of code for certain tasks you may want to separate each task into its own section.  I would start off especially if you want to do this create a menu for each rotation so that a user can select which type of rotation he/she wants to do.  Personally I am not so great at coding but one thing I do know are standards and that was beaten to hell into my brain
Thank you for your input Tia!  Smile
(01-24-2008, 05:31 AM)Clay Dragon link Wrote:Sorry for coming in so late
Jan 12 - Asked question
Jan 23 - Got answer
Jan 24 - "Sorry for coming in so late"

That's funny. You waited for 13 days for a reply and responded within a day. Very nice person.

Anyway, yep, it is hard. I give up. Good luck.

Mac
(01-24-2008, 06:20 PM)Mac link Wrote:[quote author=Clay Dragon link=topic=13160.msg153412#msg153412 date=1201134680]
Sorry for coming in so late
Jan 12 - Asked question
Jan 23 - Got answer
Jan 24 - "Sorry for coming in so late"

That's funny. You waited for 13 days for a reply and responded within a day. Very nice person.

Anyway, yep, it is hard. I give up. Good luck.

Mac
[/quote]

I said that because you replied twice to my question in the same day! I thought I wasn't fast enough for you! That's all...

Anyway, I want to thank you again for your help!

Regards,

Clay Dragon
Just as a challenge, I dug in, trying to come up with a solution for your 5x5 matrix.  I managed to write the code to do the trick for any selection of 2x2, 3x3, 4x4 and the 5x5.  I can rotate the outermost sqare 90 degrees in a clockwise or a counterclockwise direction, as many times as wanted, one by one.

As can be seen, the code is quite repetitive, in part, and is susceptible, with a little more work, of being greatly reduced by using more FOR/NEXT, or SELECT CASE/END SELECT, or DO/LOOP.  In that manner, it could easily handle any size of square, up to the limit that I get, 127x127.  Obviously, this would meet the OP's requirement of a 56x56 square.

Here's my code:

Code:
'ArrayRot, by Ralph A. Esquivel, 24 Jan 2008, creates a 5x5 array, then
'allows selecting any 2x2, 3x3 or 4x4 submatrix, or the 5x5 matrix, then
'rotate it +/-90ø (clock- or counterclock-wise), repeatedly

OPTION BASE 1 'I like to use arrays whose first element is 1.
SCREEN 12

CLS
'size of array will be S,S
SS = 5
DIM array0(SS, SS) AS STRING * 1 'initial array
DIM array1(SS, SS) AS STRING * 1 'final array

'create array0 and array1
FOR y = 1 TO SS
  FOR x = 1 TO SS
    READ m$
    array0(x, y) = m$
    array1(x, y) = m$
  NEXT x
NEXT y

GOSUB printArray0
firstLine = y * vv 'first line of text


'draw grid
GOSUB drawGrid




'PART THAT REPEATS STARTS HERE
DO
  DO
    'clear all text below grid
   LOCATE firstLine + 1, 1
   FOR i = 1 TO 12
     PRINT STRING$(78, " ")
   NEXT i

    'enter size of block to rotate
    LOCATE firstLine + 1, 4
    PRINT "Enter horizontal dimension of block to rotate 90ø (+/-2 to +/-5): ";
    LINE INPUT k$
    d$ = k$
    d = VAL(d$)
    PRINT d
  LOOP WHILE d = 0 OR ABS(d) > 5
   



  DO
    DO
      'clear old text
      cellChosen$ = ""
      LOCATE firstLine + 2, 4
      FOR i = 1 TO 11
        PRINT STRING$(78, " ")
      NEXT i
   
     'find right-bottom-most letter allowed for top of block w/ dimension chosen
      rbmL$ = array1(SS + 1 - ABS(d), SS + 1 - ABS(d))
 
     'enter letter for left-top letter of block to rotate
     a$ = "Enter top-left cell of block (A TO " + rbmL$ + "): "
     LOCATE firstLine + 2, 4
     PRINT a$;
     GOSUB inkey
     L$ = UCASE$(k$)
     PRINT L$
   LOOP WHILE L$ = 0 OR L$ < "A" OR L$ > "Z"


    'find x and y values for L$ in array1
    FOR y = 1 TO SS
      FOR x = 1 TO SS
        '''PRINT x; y,
        IF array1(x, y) = L$ THEN
          ex$ = "Yes"
          EXIT FOR
        END IF
      NEXT x
      IF ex$ = "Yes" THEN EXIT FOR
      PRINT
    NEXT y
    'reset ex$
    ex$ = ""

    'evaluate if cell chosen is appropriate for block chosen
    maxvalue = SS + 1 - ABS(d)
    IF x > maxvalue THEN
      cellChosen$ = "Bad"
      PRINT " x ="; x; "is too large.  Choose an appopriate cell"
      GOSUB pause
    END IF

    IF y > maxvalue THEN
      cellChosen$ = "Bad"
      PRINT " y ="; y; "is too large.  Choose an appopriate cell"
      GOSUB pause
    END IF
  LOOP WHILE cellChosen$ = "Bad"

  'create a temporary array for the block to be rotated
  REDIM temp(x TO x + ABS(d) - 1, y TO y + ABS(d) - 1) AS STRING * 1

  'rotate block chosen +/-90ø

  IF d = 2 THEN
    temp(x + 0, y + 0) = array1(x + 0, y + 1)
    temp(x + 0, y + 1) = array1(x + 1, y + 1)
   
    temp(x + 1, y + 0) = array1(x + 0, y + 0)
    temp(x + 1, y + 1) = array1(x + 1, y + 0)

  ELSEIF d = -2 THEN
    temp(x + 0, y + 0) = array1(x + 1, y + 0)
    temp(x + 0, y + 1) = array1(x + 0, y + 0)
   
    temp(x + 1, y + 0) = array1(x + 1, y + 1)
    temp(x + 1, y + 1) = array1(x + 0, y + 1)
  END IF

  IF d = 3 THEN
    temp(x + 0, y + 0) = array1(x + 0, y + 2)
    temp(x + 0, y + 1) = array1(x + 1, y + 2)
    temp(x + 0, y + 2) = array1(x + 2, y + 2)

    temp(x + 1, y + 0) = array1(x + 0, y + 1)
    temp(x + 1, y + 1) = array1(x + 1, y + 1)
    temp(x + 1, y + 2) = array1(x + 2, y + 1)

    temp(x + 2, y + 0) = array1(x + 0, y + 0)
    temp(x + 2, y + 1) = array1(x + 1, y + 0)
    temp(x + 2, y + 2) = array1(x + 2, y + 0)

  ELSEIF d = -3 THEN
    temp(x + 0, y + 0) = array1(x + 2, y + 0)
    temp(x + 0, y + 1) = array1(x + 1, y + 0)
    temp(x + 0, y + 2) = array1(x + 0, y + 0)

    temp(x + 1, y + 0) = array1(x + 2, y + 1)
    temp(x + 1, y + 1) = array1(x + 1, y + 1)
    temp(x + 1, y + 2) = array1(x + 0, y + 1)

    temp(x + 2, y + 0) = array1(x + 2, y + 2)
    temp(x + 2, y + 1) = array1(x + 1, y + 2)
    temp(x + 2, y + 2) = array1(x + 0, y + 2)
  END IF

  IF d = 4 THEN
    temp(x + 0, y + 0) = array1(x + 0, y + 3)
    temp(x + 0, y + 1) = array1(x + 1, y + 3)
    temp(x + 0, y + 2) = array1(x + 2, y + 3)
    temp(x + 0, y + 3) = array1(x + 3, y + 3)

    temp(x + 1, y + 0) = array1(x + 0, y + 2)
    temp(x + 1, y + 1) = array1(x + 1, y + 2)
    temp(x + 1, y + 2) = array1(x + 2, y + 2)
    temp(x + 1, y + 3) = array1(x + 3, y + 2)

    temp(x + 2, y + 0) = array1(x + 0, y + 1)
    temp(x + 2, y + 1) = array1(x + 1, y + 1)
    temp(x + 2, y + 2) = array1(x + 2, y + 1)
    temp(x + 2, y + 3) = array1(x + 3, y + 1)

    temp(x + 3, y + 0) = array1(x + 0, y + 0)
    temp(x + 3, y + 1) = array1(x + 1, y + 0)
    temp(x + 3, y + 2) = array1(x + 2, y + 0)
    temp(x + 3, y + 3) = array1(x + 3, y + 0)

  ELSEIF d = -4 THEN
    temp(x + 0, y + 0) = array1(x + 3, y + 0)
    temp(x + 0, y + 1) = array1(x + 2, y + 0)
    temp(x + 0, y + 2) = array1(x + 1, y + 0)
    temp(x + 0, y + 3) = array1(x + 0, y + 0)

    temp(x + 1, y + 0) = array1(x + 3, y + 1)
    temp(x + 1, y + 1) = array1(x + 2, y + 1)
    temp(x + 1, y + 2) = array1(x + 1, y + 1)
    temp(x + 1, y + 3) = array1(x + 0, y + 1)

    temp(x + 2, y + 0) = array1(x + 3, y + 2)
    temp(x + 2, y + 1) = array1(x + 2, y + 2)
    temp(x + 2, y + 2) = array1(x + 1, y + 2)
    temp(x + 2, y + 3) = array1(x + 0, y + 2)

    temp(x + 3, y + 0) = array1(x + 3, y + 3)
    temp(x + 3, y + 1) = array1(x + 2, y + 3)
    temp(x + 3, y + 2) = array1(x + 1, y + 3)
    temp(x + 3, y + 3) = array1(x + 0, y + 3)
  END IF

  IF d = 5 THEN
    temp(x + 0, y + 0) = array1(x + 0, y + 4)
    temp(x + 0, y + 1) = array1(x + 1, y + 4)
    temp(x + 0, y + 2) = array1(x + 2, y + 4)
    temp(x + 0, y + 3) = array1(x + 3, y + 4)
    temp(x + 0, y + 4) = array1(x + 4, y + 4)

    temp(x + 1, y + 0) = array1(x + 0, y + 3)
    temp(x + 1, y + 1) = array1(x + 1, y + 3)
    temp(x + 1, y + 2) = array1(x + 2, y + 3)
    temp(x + 1, y + 3) = array1(x + 3, y + 3)
    temp(x + 1, y + 4) = array1(x + 4, y + 3)

    temp(x + 2, y + 0) = array1(x + 0, y + 2)
    temp(x + 2, y + 1) = array1(x + 1, y + 2)
    temp(x + 2, y + 2) = array1(x + 2, y + 2)
    temp(x + 2, y + 3) = array1(x + 3, y + 2)
    temp(x + 2, y + 4) = array1(x + 4, y + 2)

    temp(x + 3, y + 0) = array1(x + 0, y + 1)
    temp(x + 3, y + 1) = array1(x + 1, y + 1)
    temp(x + 3, y + 2) = array1(x + 2, y + 1)
    temp(x + 3, y + 3) = array1(x + 3, y + 1)
    temp(x + 3, y + 4) = array1(x + 4, y + 1)

    temp(x + 4, y + 0) = array1(x + 0, y + 0)
    temp(x + 4, y + 1) = array1(x + 1, y + 0)
    temp(x + 4, y + 2) = array1(x + 2, y + 0)
    temp(x + 4, y + 3) = array1(x + 3, y + 0)
    temp(x + 4, y + 4) = array1(x + 4, y + 0)

  ELSEIF d = -5 THEN
    temp(x + 0, y + 0) = array1(x + 4, y + 0)
    temp(x + 0, y + 1) = array1(x + 3, y + 0)
    temp(x + 0, y + 2) = array1(x + 2, y + 0)
    temp(x + 0, y + 3) = array1(x + 1, y + 0)
    temp(x + 0, y + 4) = array1(x + 0, y + 0)

    temp(x + 1, y + 0) = array1(x + 4, y + 1)
    temp(x + 1, y + 1) = array1(x + 3, y + 1)
    temp(x + 1, y + 2) = array1(x + 2, y + 1)
    temp(x + 1, y + 3) = array1(x + 1, y + 1)
    temp(x + 1, y + 4) = array1(x + 0, y + 1)

    temp(x + 2, y + 0) = array1(x + 4, y + 2)
    temp(x + 2, y + 1) = array1(x + 3, y + 2)
    temp(x + 2, y + 2) = array1(x + 2, y + 2)
    temp(x + 2, y + 3) = array1(x + 1, y + 2)
    temp(x + 2, y + 4) = array1(x + 0, y + 2)

    temp(x + 3, y + 0) = array1(x + 4, y + 3)
    temp(x + 3, y + 1) = array1(x + 3, y + 3)
    temp(x + 3, y + 2) = array1(x + 2, y + 3)
    temp(x + 3, y + 3) = array1(x + 1, y + 3)
    temp(x + 3, y + 4) = array1(x + 0, y + 3)

    temp(x + 4, y + 0) = array1(x + 4, y + 4)
    temp(x + 4, y + 1) = array1(x + 3, y + 4)
    temp(x + 4, y + 2) = array1(x + 2, y + 4)
    temp(x + 4, y + 3) = array1(x + 1, y + 4)
    temp(x + 4, y + 4) = array1(x + 0, y + 4)
  END IF


  'change elements in array1 to those in temp, the rotated block
  IF d = 2 OR d = -2 THEN
    array1(x + 0, y + 0) = temp(x + 0, y + 0)
    array1(x + 0, y + 1) = temp(x + 0, y + 1)
   
    array1(x + 1, y + 0) = temp(x + 1, y + 0)
    array1(x + 1, y + 1) = temp(x + 1, y + 1)
  END IF

  IF d = 3 OR d = -3 THEN
    array1(x + 0, y + 0) = temp(x + 0, y + 0)
    array1(x + 0, y + 1) = temp(x + 0, y + 1)
    array1(x + 0, y + 2) = temp(x + 0, y + 2)

    array1(x + 1, y + 0) = temp(x + 1, y + 0)
    array1(x + 1, y + 1) = temp(x + 1, y + 1)
    array1(x + 1, y + 2) = temp(x + 1, y + 2)

    array1(x + 2, y + 0) = temp(x + 2, y + 0)
    array1(x + 2, y + 1) = temp(x + 2, y + 1)
    array1(x + 2, y + 2) = temp(x + 2, y + 2)
  END IF

  IF d = 4 OR d = -4 THEN
    array1(x + 0, y + 0) = temp(x + 0, y + 0)
    array1(x + 0, y + 1) = temp(x + 0, y + 1)
    array1(x + 0, y + 2) = temp(x + 0, y + 2)
    array1(x + 0, y + 3) = temp(x + 0, y + 3)

    array1(x + 1, y + 0) = temp(x + 1, y + 0)
    array1(x + 1, y + 1) = temp(x + 1, y + 1)
    array1(x + 1, y + 2) = temp(x + 1, y + 2)
    array1(x + 1, y + 3) = temp(x + 1, y + 3)

    array1(x + 2, y + 0) = temp(x + 2, y + 0)
    array1(x + 2, y + 1) = temp(x + 2, y + 1)
    array1(x + 2, y + 2) = temp(x + 2, y + 2)
    array1(x + 2, y + 3) = temp(x + 2, y + 3)

    array1(x + 3, y + 0) = temp(x + 3, y + 0)
    array1(x + 3, y + 1) = temp(x + 3, y + 1)
    array1(x + 3, y + 2) = temp(x + 3, y + 2)
    array1(x + 3, y + 3) = temp(x + 3, y + 3)
  END IF

  IF d = 5 OR d = -5 THEN
    array1(x + 0, y + 0) = temp(x + 0, y + 0)
    array1(x + 0, y + 1) = temp(x + 0, y + 1)
    array1(x + 0, y + 2) = temp(x + 0, y + 2)
    array1(x + 0, y + 3) = temp(x + 0, y + 3)
    array1(x + 0, y + 4) = temp(x + 0, y + 4)

    array1(x + 1, y + 0) = temp(x + 1, y + 0)
    array1(x + 1, y + 1) = temp(x + 1, y + 1)
    array1(x + 1, y + 2) = temp(x + 1, y + 2)
    array1(x + 1, y + 3) = temp(x + 1, y + 3)
    array1(x + 1, y + 4) = temp(x + 1, y + 4)

    array1(x + 2, y + 0) = temp(x + 2, y + 0)
    array1(x + 2, y + 1) = temp(x + 2, y + 1)
    array1(x + 2, y + 2) = temp(x + 2, y + 2)
    array1(x + 2, y + 3) = temp(x + 2, y + 3)
    array1(x + 2, y + 4) = temp(x + 2, y + 4)

    array1(x + 3, y + 0) = temp(x + 3, y + 0)
    array1(x + 3, y + 1) = temp(x + 3, y + 1)
    array1(x + 3, y + 2) = temp(x + 3, y + 2)
    array1(x + 3, y + 3) = temp(x + 3, y + 3)
    array1(x + 3, y + 4) = temp(x + 3, y + 4)

    array1(x + 4, y + 0) = temp(x + 4, y + 0)
    array1(x + 4, y + 1) = temp(x + 4, y + 1)
    array1(x + 4, y + 2) = temp(x + 4, y + 2)
    array1(x + 4, y + 3) = temp(x + 4, y + 3)
    array1(x + 4, y + 4) = temp(x + 4, y + 4)
  END IF


  'print new array1
  GOSUB printArray1

  LOCATE 17, 4
  PRINT "Press <Esc> to quit exit program, any other key to continue"
  GOSUB inkey
  IF k$ = CHR$(27) THEN END
LOOP

END

'--------------
'DATA FOR ARRAY
DATA A,B,C,D,E
DATA F,G, H,I,J
DATA K,L,M,N,O
DATA P,Q,R,S,T
DATA U,V,W,X,Y


'===========================================================================
'SUBROUTINES

printArray0:
hh = 5: vv = 2
FOR y = 1 TO SS
  FOR x = 1 TO SS
    LOCATE y * vv + 1, x * hh + 4: PRINT array0(x, y)
  NEXT x
NEXT y
RETURN


printArray1:
hh = 5: vv = 2
FOR y = 1 TO SS
  FOR x = 1 TO SS
    LOCATE y * vv + 1, x * hh + 4: PRINT array1(x, y)
  NEXT x
NEXT y
RETURN


drawGrid:
'the following values were obtained by trial and error for horizontal lines
ht = 14 * 3: vt = 20
FOR x = 1 TO SS + 1
  LINE (x * ht, vt)-(x * ht, 9 * vt), 15
NEXT x

'the following values were obtained by trial and error for vertical lines
va = 20: vt = vt + 12
FOR y = -1 TO SS
  LINE (ht, y * vt + va)-(6 * ht, y * vt + va), 15
NEXT y
RETURN


inkey:
k$ = "": WHILE k$ = "": k$ = INKEY$: WEND
RETURN


pause:
WHILE INKEY$ = "": WEND
RETURN
I also made a small example. I wrote this in FB, using -lang qb, so i hope it runs ok under QBasic. I didn't add bounds checking because I thought it might be good practice for the guy who wants the code to add it himself.  Wink

Code:
declare sub rotate_array( mat() as string, px as integer, py as integer, swath as integer )

screen 13
DEFINT A-Z

dim mat(1 to 5, 1 to 5) as string
dim x, y, ch, px, py, swath


for y = 1 to ubound(mat,2)
    for x = 1 to ubound(mat,1)

        mat(x,y) = chr$(ch+65)
        ch = ch + 1

    next x
next y


for y = 1 to ubound(mat,2)
    for x = 1 to ubound(mat,1)

        locate (y*2)-1,(x*2)-1
        print mat(x,y);

        locate (y*2)-1,((x+6)*2)-1
        print mat(x,y);

    next x
next y


px = 3
py = 3
swath = 1

rotate_array( mat(), px, py, swath )

cls
color(15)

for y = 1 to ubound(mat,2)
    for x = 1 to ubound(mat,1)

        locate (y*2)-1, (x*2)-1
        print mat(x,y);

    next x
next y





sub rotate_array( mat() as string, px as integer, py as integer, swath as integer )
    'BEWARE: NO BOUNDS CHECKING!!!
    'adding it might be good practice
   
    dim x, y as integer
    dim temp( ubound(mat,1), ubound(mat,2) ) as string
   
    for y = 1 to ubound(mat,2)
        for x = 1 to ubound(mat,1)

            temp(x,y) = mat(x,y)

        next x
    next y
   
    for y = -swath to swath
        for x = -swath to swath
           
            color(4)
            locate ((py-x)*2)-1, ((px+y)*2)-1
            print temp(px+y,py-x);
           
            mat(px+x,y+py) = temp(px+y,py-x)
           
            color(14)
            locate ((py+y)*2)-1, ((px+x+6)*2)-1
            print mat(px+x,py+y);
           
            sleep 1

        next x
    next y
   
end sub
Pages: 1 2 3