Programmering computer spil kan være det mest teknisk udfordrende (og muligvis det bedst betalte) job som a programmør kan få. Spil på topniveau kræver det bedste fra både programmerere og computere.
Visual Basic 6 er nu blevet omgået grundigt som en platform til spilprogrammering. (Det var aldrig rigtig en. Selv i de "gode ol 'dage" ville seriøse spilprogrammører aldrig bruge et højt niveau sprog som VB 6, fordi du bare ikke kunne få klippet edge performance, som de fleste spil kræver.) Men det enkle "Tic Tac Toe" -spil er en fantastisk introduktion til programmering, der er lidt mere avanceret end "Hej Verden!"
Dette er en god introduktion til mange af de grundlæggende begreber i programmering, da det kombinerer teknikker, herunder:
- Brugen af arrays. X- og O-markørerne opbevares i separate arrays, og hele matriserne sendes mellem funktioner for at holde styr på udviklingen i spillet.
- Brug af VB 6-niveau grafik: VB 6 tilbyder ikke stor grafisk kapacitet, men spillet er en god introduktion til hvad der er tilgængeligt. Meget af resten af denne serie er en udforskning af, hvordan GDI +, den næste generation af Microsoft-grafik, erstatter VB 6-grafikniveauet.
- Brug af matematikberegninger til programstyring: Programmet bruger smart modulo (Mod) og heltal opdelingsberegninger ved hjælp af to-spil markørarrays til at bestemme, hvornår en tre-element "win" har fandt sted.
Klassen for programmering i denne artikel er måske bare lidt forbi begyndelsesniveauet, men det skal være godt for "mellemliggende" programmerere. Men lad os starte på et elementært niveau for at illustrere nogle af koncepterne og komme i gang med dit Visual Basic spilprogrammeringskarriere. Selv studerende mere avancerede end det kan måske opleve, at det er lidt udfordrende at få objekterne i form nøjagtigt.
Sådan spiller du Tic Tac Toe
Hvis du aldrig har spillet Trip Trap Træsko, her er reglerne. To spillere skifter ved at placere Xs og Os i 3 x 3 spilleregler.
Før spillet starter, skal begge spillere blive enige om, hvem der går først, og hvem der markerer hans træk med hvilket symbol. Efter det første træk placerer spillerne skiftevis deres mærker i enhver tom celle. Målet med spillet er at være den første spiller med tre markeringer i en vandret, diagonal eller lodret linje. Hvis der ikke er tomme celler, og ingen af spillerne har en vindende kombination, er spillet uafgjort.
Før du starter en egentlig kodning, er det altid en god ide at ændre navnene på de komponenter, du bruger. Når du starter kodning, bruges navnet automatisk af Visual Basic, så du ønsker, at det skal være det rigtige navn. Vi bruger formularnavnet frmTicTacToe og vi ændrer også overskriften til "Om Tic Tac Toe."
Brug formularen til at bruge linjen værktøjskassestyring til at tegne et 3 x 3 gitter. Klik på linieværktøjet, og tegn derefter en linje, hvor du vil have det. Du bliver nødt til at oprette fire linjer på denne måde og justere deres længde og position for at få dem til at se rigtige ud. Visual Basic har også nogle praktiske værktøjer i menuen Format, som kan hjælpe. Dette er en stor chance for at øve med dem.
Ud over det spillende gitter, har vi brug for nogle objekter til X- og O-symbolerne, der vil blive placeret på gitteret. Da der er ni mellemrum i gitteret, opretter vi en objektgruppe med ni mellemrum, kaldet elementer i Visual Basic.
Der er flere måder at gøre næsten alt i Visual Basic-udviklingsmiljøet, og det er ingen undtagelse at oprette kontrolpaneler. Det er sandsynligvis den nemmeste måde at oprette den første etiket (klik og tegne ligesom linjeværktøjet), navngive den, indstille alle attributterne (f.eks. Font og ForeColor) og derefter kopiere den. VB 6 spørger, om du vil oprette et kontrolarray. Brug navnet lblPlayGround til den første etiket.
For at oprette de otte andre elementer i gitteret, skal du vælge det første labelobjekt, indstille indeksegenskabet til nul og trykke på CTRL + C (kopi). Nu kan du trykke på CTRL + V (indsætte) for at oprette et andet labelobjekt. Når du kopierer objekter som dette, arver hver kopi alle egenskaber undtagen Indeks fra den første. Indeks stiger med en for hver kopi. Dette er en kontrolgruppe, fordi de alle har det samme navn, men forskellige indeksværdier.
Hvis du opretter arrayet på denne måde, stables alle kopierne oven på hinanden i det øverste venstre hjørne af formularen. Træk hver etiket til en af de spillende gitterpositioner. Sørg for, at indeksværdier er rækkefølge i gitteret. Programmets logik afhænger af det. Etiketobjektet med indeksværdi 0 skal være i øverste venstre hjørne, og den nederste højre etiket skal have indeks 8. Hvis etiketterne dækker det spillede gitter, skal du vælge hver etiket, højreklikke og vælge Send til tilbage.
Da der er otte mulige måder at vinde spillet, har vi brug for otte forskellige linjer for at vise gevinsten på det spillende net. Du vil bruge den samme teknik til at oprette en anden kontrolgruppe. Tegn først linjen, navngiv den linWin, og indstil egenskaben Indeks til nul. Brug derefter kopipasta-teknik til at producere syv flere linjer. Følgende illustration viser, hvordan man indstiller indeksnumrene korrekt.
Ud over etiketten og linieobjekter har du brug for nogle kommandoknapper for at spille spillet og flere etiketter for at holde score. Trinene til at oprette disse er ikke detaljeret her, men det er de objekter, du har brug for.
To knap objekter:
- cmdNewGame
- cmdResetScore
Rammeobjekt fraPlayFirst indeholdende to valgknapper:
- optXPlayer
- optOPlayer
Rammeobjekt fraScoreBoard indeholdende seks etiketter. Kun lblXScore og lblOScore ændres i programkoden.
- lblX
- lblXScore
- lblO
- lblOScore
- lblMinus
- lblColon
Endelig har du også brug for etiketobjektet lblStartMsg for at 'maskere' cmdNewGame-knappen, når det ikke skal klikkes. Dette er ikke synligt på illustrationen nedenfor, fordi det optager den samme plads i formen som kommandoknappen. Du skal muligvis flytte kommandoknappen midlertidigt for at tegne denne etiket på formularen.
Indtil videre er der ikke udført nogen VB-kodning, men vi er endelig klar til at gøre det.
Initialisering
Nu får du endelig begynde at kode programmet. Hvis du ikke allerede har gjort det, kan du muligvis downloade kildekoden, der skal følges, da programmets drift forklares.
En af de første designbeslutninger, der skal træffes, er, hvordan man holder styr på den aktuelle 'tilstand' i spillet. Med andre ord, hvad er de nuværende Xs og Os på spillegridnet, og hvem flytter næste. Begrebet 'tilstand' er kritisk i en masse programmering, og især er det vigtigt i programmering af ASP og ASP.NET til internettet
Der er flere måder, dette kan gøres, så det er et kritisk trin i analysen. Hvis du løste dette problem på egen hånd, kan du måske tegne et flowchart og prøve forskellige indstillinger med 'ridsepapir', inden du starter en kodning.
Vores løsning bruger to "to-dimensionelle arrays", fordi det hjælper med at holde styr på 'tilstand' ved blot at ændre arrayindekserne i programsløjfer. Tilstanden for det øverste venstre hjørne vil være i matrixelementet med indeks (1, 1), det øverste højre hjørne vil være i (1, 3), nederst til højre i (3,3) osv.. De to matriser, der gør dette, er:
iXPos (x, y)
og
iOPos (x, y)
Der er mange forskellige måder, dette kan gøres, og den endelige VB.NET-løsning i denne serie viser dig, hvordan du gør det med bare en enkelt en-dimensionel matrix.
Programmeringen til at oversætte disse arrays til spiller-win-beslutninger og synlige skærme i formen er på næste side.
Du har også brug for et par globale variabler som følger. Bemærk, at disse er i koden Generelle og erklæringer til formularen. Dette gør dem "modulniveau" variabler, der kan henvises til overalt i koden for denne form. For mere om dette, se Forstå omfanget af variabler i Visual Basic Hjælp.
Der er to områder, hvor variabler er initialiseret i vores program. Først initialiseres et par variabler, mens formen frmTicTacToe indlæses.
Privat subformularindlæsning ()
For det andet, før hvert nyt spil, tildeles alle variabler, der skal nulstilles til startværdier, i en initialiseringssubutine.
Sub InitPlayGround ()
Bemærk, at initialisering af formbelastning også kalder legepladsinitialisering.
En af en programmørs kritiske færdigheder er evnen til at bruge fejlfindingsfaciliteterne til at forstå, hvad koden gør. Du kan bruge dette program til at prøve:
- Gå igennem koden med F8-tasten
- Indstilling af et ur på nøglevariabler, f.eks. SPlaySign eller iMove
Indstilling af et breakpoint og forespørgsel om værdien af variabler. For eksempel i den indvendige sløjfe af initialiseringen:
lblPlayGround ((i - 1) * 3 + j - 1). Billedtekst = ""
Bemærk, at dette program tydeligt viser, hvorfor det er en god programmeringspraksis at opbevare data i arrays, når det er muligt. Hvis du ikke havde arrays i dette program, skulle du skrive kode lignende:
Line0. Visible = Falsk
Line1.Visible = Falsk
Line2.Visible = Falsk
Line3.Visible = Falsk
Line4.Visible = Falsk
Line5.Visible = Falsk
Line6.Visible = Falsk
Line7.Visible = Falsk
i stedet for dette:
For i = 0 til 7
linWin (i). Visible = Falsk
Næste i
Gør et træk
Hvis en del af systemet kan betragtes som 'hjertet', er det subroutine lblPlayGround_Click. Denne subroutine kaldes hver gang en spiller klikker på spillegridet. (Klik skal være inde i et af de ni lblPlayGround-elementer.) Bemærk, at denne subroutine har et argument: (Indeks som heltal). De fleste af de andre 'hændelsesunderprogrammer', som cmdNewGame_Click (), gør det ikke. Indeks angiver, hvilket labelobjekt der er klikket på. For eksempel vil indekset indeholde værdien nul for det øverste venstre hjørne af gitteret og værdien otte for det nederste højre hjørne.
Når en spiller har klikket på en firkant i spilgitteret, bliver kommandoknappen for at starte et andet spil, cmdNewGame, "tændt" ved at gøre det synligt. Tilstanden for denne kommandoknap udfører dobbeltbetjening, fordi den også bruges som en boolesk beslutningsvariabel senere i programmet. Brug af en egenskabsværdi som en beslutningsvariabel afskrækkes normalt, fordi hvis det nogensinde bliver nødvendigt at ændre programmet (sig for eksempel at lave cmdNewGame kommandoknap, der er synlig hele tiden), så vil programmet uventet mislykkes, fordi du muligvis ikke kan huske, at det også bruges som en del af programmet logik. Af denne grund er det altid en god ide at søge gennem programkode og kontrollere brugen af alt, hvad du ændrer, når du udfører programvedligeholdelse, også ejendomsværdier. Dette program overtræder reglen dels for at gøre dette, dels fordi dette er et relativt simpelt stykke kode, hvor det er lettere at se, hvad der gøres, og undgå problemer senere.
Et spillervalg af et spilfelt behandles ved at kalde GamePlay-underprogrammet med indeks som argument.
Behandler flytningen
Først tjekker du for at se, om der blev klikket på et ledigt firkant.
Hvis lblPlayGround (xo_Move) .Caption = "" Derefter
Når vi er sikre på, at dette er et legitimt træk, øges bevægelsestælleren (iMove). De næste to linjer er meget interessante, da de oversætter koordinaterne fra det en-dimensionelle Hvis lblPlayGround-komponent array til to-dimensionelle indekser, som du kan bruge i iXPos eller iOPos. Mod- og heltalinddeling ('backslash') er matematiske operationer, som du ikke bruger hver dag, men her er et godt eksempel, der viser, hvordan de kan være meget nyttige.
Hvis lblPlayGround (xo_Move) .Caption = "" Derefter
iMove = iMove + 1
x = Int (xo_Move / 3) + 1
y = (xo_Move Mod 3) + 1
Værdien xo_Move 0 oversættes til (1, 1), 1 til (1, 2)... 3 til (2, 1)... 8 til (3, 3).
Værdien i sPlaySign, en variabel med modulomfang, holder styr på, hvilken spiller der har gjort det. Når bevægelsesmatriserne er opdateret, kan etiketkomponenterne i det spillede gitter opdateres med det passende tegn.
Hvis sPlaySign = "O" Derefter
iOPos (x, y) = 1
iWin = CheckWin (iOPos ())
Andet
iXPos (x, y) = 1
iWin = CheckWin (iXPos ())
Afslut Hvis
lblPlayGround (xo_Move) .Caption = sPlaySign
For eksempel, når X-afspilleren klikker på det øverste venstre hjørne af gitteret, vil variabler have følgende værdier:
Brugerskærmen viser kun et X i det øverste venstre felt, mens iXPos har en 1 i det øverste venstre felt og 0 i alle de andre. IOPos har 0 i hver boks.
Værdierne ændres, når O-afspilleren klikker på midterste firkant af gitteret. Nu viser iOPos en 1 i midterboksen, mens brugerskærmen viser et X i øverste venstre hjørne og en O i centerboksen. IXPos viser kun 1 i øverste venstre hjørne, med 0 i alle de andre bokse.
Nu hvor du ved, hvor en spiller klikkede, og hvilken spiller der klikkede (ved hjælp af værdien i sPlaySign), alt hvad du skal gøre er at finde ud af, om nogen vandt et spil og finde ud af, hvordan man viser det i Skærm.
At finde en vinder
Efter hver flytning tjekker CheckWin-funktionen for den vindende kombination. CheckWin fungerer ved at tilføje hver række, på tværs af hver søjle og gennem hver diagonal. Det kan være meget lærerigt at spore trinene gennem CheckWin ved hjælp af Visual Basic's Debug-funktion. At finde en gevinst er et spørgsmål om først, kontrollere, om der blev fundet tre 1'er i hver af de individuelle kontroller i variablen iScore, og derefter returnerer en unik "signatur" -værdi i Checkwin, der bruges som array-indeks til at ændre den synlige egenskab for et element i linWin komponent array. Hvis der ikke er nogen vinder, vil CheckWin indeholde værdien -1. Hvis der er en vinder, opdateres displayet, resultattavlen ændres, en lykønskningsmeddelelse vises, og spillet genstartes.
Lad os gennemgå en af kontrollerne i detaljer for at se, hvordan det fungerer. De andre er ens.
'Kontroller rækkerne for 3
For i = 1 til 3
iScore = 0
CheckWin = CheckWin + 1
For j = 1 til 3
iScore = iScore + iPos (i, j)
Næste j
Hvis iScore = 3 Derefter
Afslut funktion
Afslut Hvis
Næste i
Den første ting at bemærke er, at den første indekstæller i tæller rækkerne, mens den anden j tæller på tværs af kolonnerne. Den ydre sløjfe bevæger sig derefter blot fra den ene række til den næste. Den inderste sløjfe tæller 1'erne i den aktuelle række. Hvis der er tre, har du en vinder.
Bemærk, at du også holder styr på det samlede antal firkanter, der er testet i variablen CheckWin, som er den værdi, der er returneret, når denne funktion afsluttes. Hver vindende kombination ender med en unik værdi i CheckWin fra 0 til 7, som bruges til at vælge et af elementerne i linWin () -komponentgruppen. Dette gør rækkefølgen af koden i funktionen CheckWin også vigtig! Hvis du flyttede en af blokke af loop kode (som ovenstående), ville den forkerte linje blive trukket på det spillende gitter, når nogen vinder. Prøv det og se!
Efterbehandlingsdetaljer
Den eneste kode, der endnu ikke er diskuteret, er subroutinen til et nyt spil og subroutine, der nulstiller scoringen. Resten af logikken i systemet gør det nemt at oprette disse. For at starte et nyt spil skal du kun kalde InitPlayGround-underprogrammet. Som en bekvemmelighed for spillere, da der kan klikkes på knappen midt i et spil, beder du om bekræftelse, før du går videre. Du beder også om bekræftelse, før du genstarter resultattavlen.