Met Basic kun je niet alleen aardige plaatjes tekenen, je kunt er bovendien heel verdienstelijk mee rekenen. Dat kan ook bij tekenwerk nog wel eens van pas komen. Het diagonalenprobleem van Mark Kurvers is zo'n geval. Een plaatje is een tweedimensionale collectie van pixels. De eerste gedachte zal zijn: breng de
x- en
y-coördinaten van die pixels onder in een tweedimensionaal array. Maar wat te doen als je voor de lokatiegegevens maar één dimensie tot je beschikking hebt? Dan moet je die twee coördinaten op een of andere manier samenballen tot één waarde. Te denken valt aan een notatie waarin je drie posities voor elke coördinaat beschikbaar stelt:
0 1 2 3 4 ...
+------------------------------------------- x
0 | 000000 001000 002000 003000 004000 ......
1 | 000001 001001 002001 003001 004001 ......
2 | 000002 001002 002002 003002 004002 ......
3 | 000003 001003 002003 003003 004003 ......
... | ...... ...... ...... ...... ...... ......
y
Je hebt in feite, door de
x-coördinaat met duizend te vermenigvuldigen en de
y-coördinaat erbij op te tellen, enkelvoudige getallen verkregen die heel zichtbaar de oorspronkelijke coördinatenparen bevatten. De voorloopnullen van zo'n getal kun je uiteindelijk wel weglaten.
Nu heeft mijn laptap een scherm van 1920 bij 1080 pixels. Op regel 1000 gaat er in kolom 0 iets mis bij de toepassing van een factor duizend: daar komt
001000 te staan, wat dezelfde waarde is als in kolom 1 van regel 0. Er moet dus een grotere factor worden gekozen om unieke pixelnummers te krijgen. Tienduizend dan maar? Liever zou ik uit de tabelafmetingen de juiste factor afleiden. Zo moeilijk is dat niet. De hoogste
y-waarde is gelijk aan de hoogte van de afbeelding minus 1. Kies ik de factor één hoger dan die hoogste waarde, dan zit ik al goed. De factor moet dus gelijk zijn aan de afbeeldingshoogte. Voor een plaatje van vier keer vijf pixels leidt dit tot:
0 1 2 3 4
+--------------------- x
0 | 0 4 8 12 16
1 | 1 5 9 13 17
2 | 2 6 10 14 18
3 | 3 7 11 15 19
y
Daarmee heb ik simpelweg over de kolommen doorgenummerd. Ik had net zo goed over de regels kunnen doornummeren:
0 1 2 3 4
+--------------------- x
0 | 0 1 2 3 4
1 | 5 6 7 8 9
2 | 10 11 2 13 14
3 | 15 16 17 18 19
y
Hierbij is de afbeelding
breedte als vermenigvuldigingsfactor aangehouden. Eigenlijk maakt het weinig uit hoe je de pixels nummert, zolang er maar een systeem in zit dat het mogelijk maakt uit die nummers — in combinatie met de gegeven breedte en hoogte van de afbeelding — weer coördinaten af te leiden. Bijvoorbeeld een diagonale of een spiraalsgewijze nummering:
0 1 2 3 4 0 1 2 3 4
+--------------------- x +--------------------- x
0 | 0 2 5 9 13 0 | 0 1 2 3 4
1 | 1 4 8 12 16 1 | 13 14 15 16 5
2 | 3 7 11 15 18 2 | 12 19 18 17 6
3 | 6 10 14 17 19 3 | 11 10 9 8 7
y y
Die spiraal is natuurlijk nogal onzinnig. De diagonale nummering is echter heel interessant! Deze geeft namelijk meteen de oplossing van het probleem: gewoon itereren over de waarden
0 t/m
breedte ×
hoogte −
1 en daarbij telkens het desbetreffende pixel naar het scherm schrijven. Het enige wat je vlak voor elke schrijfhandeling hoeft te doen, is het pixelnummer even terugrekenen naar de bijbehorende
x- en
y-coördinaten. Dat is alles. In één slimme doorloop van alle pixels is de hele klus dus meteen geklaard.
Ik heb deze methode toegepast in het bijgesloten programma Synthetisch.bas (geschreven voor QB64, maar hopelijk zonder al te veel ingrepen ook in LB aan de praat te krijgen). Een aardigheidje, meer niet. Niet meteen spieken als je het zelf wilt uitvogelen. Leerzaam? Mwah... ik vind het idee interessanter dan de uitwerking. Ook maar niet kijken als je helemaal niet van dit soort puzzeltjes houdt, zonde van je tijd anders.