Snelcursus programmeren voor jongeren/beginners (Dutch)


Introductie
Als je wilt leren programmeren kun je het beste beginnen met Small Basic van Microsoft. Dit is een vrij simpele taal waarmee je veel dingen kunt maken. Hier kun je hem downloaden, gratis:
http://msdn.microsoft.com/en-us/beginner/ff384126.aspx

Wat is programmeren?
Programmeren is een computer opdrachten geven, maar het is belangrijk dat je eerst een beetje weet hoe een computer van binnen werkt.

'To compute' betekent rekenen, een computer is dus een 'rekenaar', oftewel een rekenmachine. Een rekenmachine werkt met kleine schakelaartjes. Een schakelaar kan aan of uit staan. 1 of 0. Door schakelaartjes op een slimme manier te ordenen kun je een cijfer uitdrukken in enen en nullen.

Mensen werken met het tientallig stelsel, een computer werkt van binnen met het tweetallig stelsel. Binair. Voor ons onoverzichtelijk, maar voor de computer juist heel simpel.
0=0
1=1
10=2
11=3
100=4
101=5
110=6
111=7
1000=8
enzovoorts.

0000 0001 is 1
0000 0010 is 2
0000 0011 is 3
0000 0100 is 4
0001 0000 is 16
0001 0010 is 18
1111 1111 is 255

Hoe dit werkt? Denk aan een tabel:
128 | 64 | 32 | 16 | 8 | 4 | 2 | 1
Je telt de macht van 2 op als je een 1 ziet. Binair getal 1111 1111 is dus al die getallen opgeteld: 255.

Een 1 of 0 is een bit. 8 bits op een rij zoals hierboven is een byte (8 bit). Twee bytes gekoppeld is een 'word' (16 bit). Twee words gekoppeld is een 'long word' (32 bit). Hoe meer bytes gekoppeld, hoe groter het mogelijke getal, maar let op: dit zijn afspraken. De computer kent alleen enen en nullen. Een fabrikant kan best bepalen dat ie een nieuwe, betere definitie gebruikt, een oorzaak van problemen met 32 bit programma's op 64 bit computers vroeger.

Rekenvoorbeelden:
1 + 2 = 3
0000 0001  (1)
0000 0010  (2)
------------------- +
0000 0011   (3)

18 x 2 = 36  (x2 = alle bits 1 plaats naar links opschuiven)
0001 0010  (18)
0010 0100  (36)

18 / 2 = 9 (alle bits 1 plaats naar rechts opschuiven)
0001 0010  (18)
0000 1001  (9)

18 x 3 = 54 ( (18 x 2) + (18 x 1))
0001 0010 (18)
0010 0100 (x2 = 36)
>>>
0010 0100 (36)
0001 0010 (18)
------------------- +
0011 0110  (54)

Negatieve getallen? Er wordt ergens een vinkje gezet zodat de meest linker bit het + of - teken moet voorstellen. 1000 0001 is dan niet 129 maar -1. Gebroken getallen, zoals 1,5? Een extra byte voor 'na de komma' wordt ingesteld. 1,5 is 0000 0001 1000 000. Het getal 1,25 wordt dan 000 0001 0100 000.

Door groepen van schakelaartjes op een slimme manier te ordenen kun je bewerkingen uitvoeren op cijfers, zoals hierboven. Of je verplaatst cijfers, in enen en nullen. Of hele groepen van cijfers. Dat is wat een computer doet. Cijfers bewerken, cijfers verplaatsen. Alles in enen en nullen. Cijfers kunnen naar een beeldscherm worden gestuurd, waarbij drie cijfers de kleur van een pixel bepalen. RGB (red green blue). 0 0 0 is zwart, 255 0 0 is rood, 255 128 0 oranje, 255 255 255 wit, 128 128 128 middelgrijs. Of naar een speaker, zodat ie trilt in een bepaalde frequentie. Of via de kabel naar een webbrowser, waarbij de enen en nullen worden vertaald naar pixels die wij in het geheel als een leesbare tekst zien.

Een simpele binaire rekenmachine is redelijk eenvoudig te maken. Die rekenmachine programmeren (enen en nullen in hokjes plaatsen) zodat ie 18x2 moet uitvoeren ook. De eerste computers werden op deze manier gebouwd en geprogrammeerd, maar dat werd snel te ingewikkeld. Er werden constructies bedacht zodat je op toetsen met leesbare cijfers kon drukken, en de = - toets gaf dan het antwoord, in een raster met lampjes, voor ons leesbare cijfers. De (ouderwetse) rekenmachine zoals we die kennen: cijfertoetsen, twee geheugenplaatsen, berekencircuits, = - toets, raster met leesbare uitkomst.

Maar wat als je hele reeksen berekeningen wil uitvoeren, met duizenden geheugenplaatsen? De hele tijd op een = - toets drukken is geen oplossing. Daar werd iets op bedacht: de = - knop werd geautomatiseerd. Telkens doorliep de rekenmachine een rijtje instructies, en dan =. Een programma. De geboorte van de CPU (central processing unit), en daarmee de computer zoals we die nu kennen.

1. Even wachten tot alles klaar is voor de volgende ronde
2. Controleer X (zo ja: ..., zo nee: ...)
3. Controleer Y (zo ja: ..., zo nee: ...)
...
998. Doe er iets mee
999. Ga naar 1.

Ook werden veel voorkomende bewerkingen vastgelegd, in codetaal. Machinetaal. ROL (rotate left, voor delen door 2). LDX (stop (cijfer)) in X. JMP om naar een ander stuk machinetaal te springen, JSR om naar 'sub return' te gaan. Getallen die gebruikt worden zijn niet binair, maar wel snel begrijpelijk voor de computer. Hexadecimaal. 16-tallig stelsel.

00 = 0
10 = 16
FF = 255

Hier werden programma's mee geschreven, maar gebruiksvriendelijk was het niet. Je had een soort tekstverwerker waarmee je machinetaal met 'leesbare' getallen bewerkte. Er werd iets anders bedacht, geschreven in machinetaal: BASIC. Er waren meer van dat soort talen



Waarom Small Basic?

Programmeren is iets anders dan scripten, hoewel je in beide gevallen een reeks commando's maakt die de computer moet uitvoeren. Bij programmeren maak je programmablokken. Je zet in grote lijnen uiteen wat je programma moet doen en gaat de hoofdlijnen vervolgens steeds verder in detail uitwerken. Stepwise Refinement heet dat.

Veel programmeertalen zoals C++, C#, Java, Action Script, enz. zijn OOP talen, Object Oriented Programming. Je bouwt objecten waarmee je iets doet en je kunt objecten van anderen gebruiken. Objecten zitten in bibliotheken die je moet koppelen. Small Basic is een handige manier om OOP onder de knie te krijgen omdat hij standaard is uitgerust met tal van bibliotheken. Wanneer je met een andere taal aan de slag gaat zul je eerst zelf bibliotheken moeten toevoegen omdat de meeste talen op zich maar heel weinig kunnen. Als je in C++ bijvoorbeeld iets op het scherm wilt schrijven zul je eerst een bibliotheek moeten koppelen en het juiste object 'configureren' voordat je het kunt gebruiken. Bij complexere programma's wordt het snel heel lastig als je OOP niet begrijpt.

Wanneer je Small Basic snapt wordt het leren van andere talen een stuk eenvoudiger. Verder is Small Basic al heel geschikt om leuke dingen te programmeren zoals simpele games, online data ophalen en verwerken, tekenen, grafieken maken enzovoorts.

De beste manier om te leren programmeren is door programma's te bekijken, dingen te proberen en antwoorden te zoeken als je iets niet begrijpt. Het is wel belangrijk dat je de basisprincipes van programmeren begrijpt. Op deze pagina kun je zien hoe je een simpele videogame kunt maken waarbij een aantal aspecten worden uitgelicht.


Pong
Op de eerste gameconsoles in de jaren 70 kon je alleen 'Pong' spelen. Je had een streep en moest proberen een stuiterende stip op het scherm te houden.



Stel dat je een moderne 'Pong' wil maken met Small Basic. Het eerste wat je doet is bedenken wat je wilt in grote lijnen. Dan ga je de details invullen. Step-wise refinement.

Een omschrijving kan zijn:
- Ik wil een Pong game maken. 
- Ik wil een scherm met een paddle en een bal. 
- De bal moet bewegen en stuiteren. 
- De paddle moet meebewegen met de muis. 
- Als de bal gemist wordt moet er een popup komen dat je verloren hebt. 
(Later komt er misschien een startscherm waar je ook naar terug gaat als je verloren hebt, een puntentelling, 3 lives, special effects, interactieve dingen op het speelveld enzovoorts)

Het eerste deel is concreet en ook heb je al een idee hoe je je game later zou kunnen uitbouwen. Hoe zou je het eerste deel nu kunnen programmeren?


Programmaschema
Een computerprogramma bestaat uit de onderdelen:
1. initialisatie  - hier worden dingen klaargezet
2. programmablok - dit is de hoofdloop met instructies
3. subroutines - dit zijn miniprogramma's die aangeroepen kunnen worden vanuit '2'

Voor Pong zou het er zo uit kunnen zien:
1.  We maken een window met een balletje en paddle. 
We vertellen de computer dat ie altijd moet 'luisteren' of de muis wordt bewogen. 
We bepalen waar het balletje de eerste keer is en welke richting dat ie opgaat.

2. We maken een label om het begin van de hoofdrun te markeren
  We berekenen de x en y van het balletje
Is het balletje aan de rand (links, rechts, boven)? We keren een richting om.
Is het balletje bij de paddle? We keren de y-richting om
  We plaatsen het balletje op z'n nieuwe plek
Als het balletje nog op het scherm is sturen we de computer terug naar het begin
... en anders laten we een pop-up zien dat je verloren hebt. 

3. Subroutine voor het geval dat de muis beweegt:
het x-coordinaat van de paddle moet meebewegen met de muis
plaats de paddle op het scherm
Einde subroutine.


Stukje programma
Hieronder is het eerste deel van Pong voor Small Basic. Het hele programma komt zodadelijk, maar kijk er eens naar.

------------------------------------------------------------------------------------------------------

' ---- initialisatie
' maak een scherm met donkerblauwe achtergrond
' maak een rechthoek en noem hem "paddle"
' maak een bal en noem hem "ball"
' ga naar onze subroutine "OnMouseMove" als de muis wordt bewogen
GraphicsWindow.BackgroundColor = "DarkBlue"
paddle = Shapes.AddRectangle(120, 12)
ball = Shapes.AddEllipse(16, 16)
GraphicsWindow.MouseMove = OnMouseMove

' variabelen voor eerste positie, snelheid en richting van het balletje
x = 0
y = 0
deltaX = 1
deltaY = 1

------------------------------------------------------------------------------------------------------


Tekst in groen achter een '-teken is een comment. Dat wordt overgeslagen door de computer. Het is verstandig om comments te schrijven. Als je een wat groter programma hebt geschreven weet je na een tijdje vaak niet meer zo goed wat je precies gedaan hebt en waarom. Met comments kun je aanwijzingen geven voor het geval je later bugs moet opsporen of je programma wil uitbreiden. Ook in teamverband zijn comments heel belangrijk. In de comments hier zie je wat de verschillende commando's doen.

In Small Basic krijgen alle bijzondere keywords eigen kleuren waardoor het makkelijk is dingen op te sporen.



Wat is "=" ?
Het =-teken heeft verschillende betekenissen.
x = 0 betekent: maak een variabele x met waarde 0
if (x = 0).. betekent als/indien/wanneer (vergelijk variabele x met 0)
ball = Shapes.AddEllipse(..) betekent: maak een AddEllipse object aan van de klasse Shapes
GraphicsWindow.MouseMove = Pietje betekent: wanneer object MouseMove van klasse GraphicsWindow een seintje geeft, ga dan naar subroutine Pietje.

Een variabele x maken of vergelijken zul je begrijpen, maar wat is nou een object en een klasse? Heel belangrijk om dit te begrijpen omdat dit een belangrijke essentie van programmeren is. Je komt dit overal tegen. OOP!


Objecten, klassen, subroutines
Een klasse is een ander programma dat je kunt aanroepen vanuit jouw programma. Je roept een subroutine (mini-programma) aan. Een object is een kopie van zo'n subroutine, met de waarden die jij hebt meegegeven bij het aanmaken. Een ding zoals Shapes.AddEllipse (let op de punt) is een verwijzing naar subroutine AddEllipse in het programma Shapes.

Laten we kijken hoe het precies werkt.

Als de computer ball = Shapes.AddEllipse(16, 16) ziet dan springt ie naar programma 'Shapes' en start ie subroutine 'AddEllipse' met 16 en 16 als invoerwaarden. Hij maakt een kopie van de subroutine met jouw waarden erin en noemt deze 'ball'. Dit is vervolgens een object wat je kunt gebruiken! Je kunt hem naar andere subroutines sturen, je kunt eigenschappen aanpassen. Het is en blijft een uniek object. Het object is in dit geval een circel met straal 16.

De computer kan dus voortaan iets met 'ball' of 'jantje' of 'pietje', welke naam je er ook aan gaf.

Je kunt 'ball' bijvoorbeeld op deze manier gebruiken:
Shapes.Move(ball, x, y)
Als de computer dit ziet gaat ie naar dezelfde klasse (Shapes), maar een andere subroutine (Move). Hier kijkt ie wat jij bedoelt met 'ball' en dan ziet ie dat het een object is dat ie begrijpt. Hij zal je cirkel verwijderen op de oude plek door de achtergrond te herstellen en een nieuwe tekenen op de coordinaten die je hebt meegegeven. Als ie klaar is gaat het programma verder.

Zo zijn er verschillende subroutines die je kunt gebruiken in de klasse shape, bijvoorbeeld om de coordinaten van je object op te halen.


Waarom objecten maken?
Stel nu dat je geen 'ball' hebt aangemaakt en Shapes.Move(Shapes.AddEllipse(16, 16), x, y) zou gebruiken. In principe kan dat, maar bij een ingewikkelder object zul zul je zelf ergens de eigenschappen moeten gaan bijhouden. En als je 100 unieke balletjes hebt in je spel wordt het al snel heel ingewikkeld. Object georienteerd programmeren is dus heel handig!

En waar is dat "programma" 'Shapes'? In de map van Small Basic is een bestand ToolFramework.dll. De extensie dll betekent dynamic link library. In zo'n bestand zitten subroutines. Waarschijnlijk zitten alle klassen van Small Basic in dit bestand, of in een soortgelijk bestand. Small Basic weet in ieder geval waar ie moet wezen als jij de klasse Shapes aanroept.

Een klasse is dus een ander programma waarvan je subroutines kunt aanroepen vanuit je eigen programma. Je kunt kopieen oftewel instanties van een subroutine maken met jouw waarden en dit als object in andere subroutines van dezelfde klasse gebruiken.


Eventlisteners, eventhandlers
GraphicsWindow is een klasse die van alles afhandelt van/over/op je window. Je kunt dingen instellen zoals achtergrondkleuren, bekijken hoe groot ie is, en hij kan tijdens het draaien van het programma aangeven of er iets op het scherm gebeurt zoals een muisbeweging of een klik. Dit laatste wordt een eventlistener genoemd waarvoor je een eventhandler kunt schrijven. Die subroutine 'Pietje' in het voorbeeld is een eventhandler voor eventlistener GraphicsWindow.MouseMove. Bij programmeren krijg je te maken met eventlisteners. De computer kan 'luisteren' wat een muis doet, of een toets wordt aangeslagen, of het einde van een tekstbestand bereikt is, of een website nieuwe data opstuurt, enzovoorts.


Pong!
Hier is het complete programma dat je kunt knippen en plakken in Small Basic. Alles tussen de ------ lijnen.

------------------------------------------------------------------------------------------------------

' ---- initialisatie
' maak een scherm met donkerblauwe achtergrond
' maak een rechthoek en noem hem "paddle"
' maak een bal en noem hem "ball"
' ga naar onze subroutine "OnMouseMove" als de muis wordt bewogen
GraphicsWindow.BackgroundColor = "DarkBlue"
paddle = Shapes.AddRectangle(120, 12)
ball = Shapes.AddEllipse(16, 16)
GraphicsWindow.MouseMove = OnMouseMove

' variabelen voor eerste positie en snelheid bal
x = 0
y = 0
deltaX = 1
deltaY = 1


' ---- programmablok
' label RunLoop om naartoe te kunnen springen
' bereken de nieuwe x en nieuwe y
RunLoop:
  x = x + deltaX
  y = y + deltaY

  ' haal de breedte en de hoogte van het window op
  ' als de x van het balletje te ver links of rechts is, draai dan de x-richting om
  ' als de y van het balletje onder 0 is (0 is boven), draai dan de y-richting om
  gw = GraphicsWindow.Width
  gh = GraphicsWindow.Height
  If (x >= gw - 16 or x <= 0) Then
    deltaX = -deltaX
  EndIf
  If (y <= 0) Then
    deltaY = -deltaY
  EndIf

  ' haal de x-positie van de paddle op en zet hem in variabele padX
  ' als de y van het balletje bij de paddle is èn als de x in de buurt van de x van de paddle is, draai dan de y-richting van het balletje om (stuiter)
  padX = Shapes.GetLeft (paddle)
  If (y = gh - 28 and x >= padX and x <= padX + 120) Then
    deltaY = -deltaY
  EndIf

  ' verplaats "ball" naar positie x, y
  ' vertraag het programma 5 milliseconden
  Shapes.Move(ball, x, y)
  Program.Delay(5)

  ' als y van het balletje kleiner is dan de schermhoogte (en dus nog op het scherm is), ga dan terug naar label "RunLoop:"
  If (y < gh) Then
    Goto RunLoop
  EndIf

  ' ... maar als de y van het balletje gelijk of groter was dan de schermhoogte, laat dan een pop-up zien "verloren" 
GraphicsWindow.ShowMessage("You Lose", "Paddle")

' ---- Subroutines
' subroutine "onMouseMove"
' haal de x van de muis op en noem hem paddleX
' plaats "paddle" 60 pixels links van paddleX, en 12 pixels boven de onderkant van het scherm
Sub OnMouseMove
  paddleX = GraphicsWindow.MouseX
  Shapes.Move(paddle, paddleX - 60, GraphicsWindow.Height - 12)
EndSub

------------------------------------------------------------------------------------------------------

Dingen proberen
Probeer eens wat dingen te veranderen en te kijken wat het resultaat is: grotere bal, of twee manieren om de bal sneller te maken, of de bal alleen horizontaal laten gaan, enzovoorts.

Probeer ook eens te bedenken wat je zou moeten doen om de paddle bij het begin al onder te hebben i.p.v. boven. Hint: een subroutine in je eigen programma kun je aanroepen met subroutinenaam () . Je zou OnMouseMove () ergens op een extra regel kunnen plaatsen...

En als je nu drie vaste wanden wilt die resizen met het window, hoe zou je dat aanpakken? Misschien dat je een score-telling kunt inbouwen. Of twee balletjes, 3 levens, een startscherm...

Ook dit is een essentie van programmeren. Je begint met de basisdingen die je kunt uitbouwen. Je zou deze Pong hier bijvoorbeeld kunnen uitbouwen tot een ouderwetse spaceshooter. Denk aan Space Invaders. Andere graphics, iets andere bewegingen, meerdere 'balletjes' als aliens en een vuurmechanisme. Programmeren is leuk.


En verder?
Volg tutorials, bekijk bestaande programma's en probeer dingen. Als je het een beetje doorhebt kun je naar andere talen kijken zoals Java en C++. Die zijn moeilijker omdat die veel strikter en abstracter zijn dan EasyBasic. Je kunt best een Pong maken, maar dan zul je eerst zelf libraries moeten koppelen voor grafische dingen. Ook zul je specifiek variabelen moeten declareren en de computer uitleggen of het een heel getal of een stuk tekst is, en of dat die variabele in andere subroutines gebruikt mag worden of niet. Er komt dus meer bij kijken, maar het principe is hetzelfde. Wat wel mooi is in 'echte' programmeertalen is dat je gebruik kunt maken van talloze libraries zoals 3D game engines en dat je bijvoorbeeld ook apps voor smartphones kunt programmeren.


Bron
Het Pong programma komt van de MSDN site van Microsoft. Op deze pagina zijn een paar voorbeelden meer. http://msdn.microsoft.com/en-us/beginner/gg605178.aspx