programmering dataspill kan være den mest teknisk utfordrende (og muligens den best betalte) jobben som a Programmerer kan ha. Spill på toppnivå krever det beste fra både programmerere og datamaskiner.
Visual Basic 6 er nå blitt omgått grundig som en plattform for programmering av spill. (Det var egentlig aldri det. Selv i de "gode ol-dagene" ville seriøse spillprogrammerere aldri bruke et høyt nivå språk som VB 6 fordi du bare ikke kunne få klippet kantprestasjoner som de fleste spill krever.) Men det enkle "Tic Tac Toe" -spillet er en flott introduksjon til programmering som er litt mer avansert enn "Hei Verden!"
Dette er en flott introduksjon til mange av de grunnleggende konseptene for programmering siden den kombinerer teknikker inkludert:
- Bruken av arrays. X- og O-markørene holdes i separate matriser, og hele matriser føres mellom funksjoner for å holde oversikt over fremdriften i spillet.
- Bruke VB 6-nivågrafikk: VB 6 tilbyr ikke stor grafisk evne, men spillet er en god introduksjon til hva som er tilgjengelig. Mye av resten av denne serien er en utforskning av hvordan GDI +, den neste generasjonen av Microsoft-grafikk, erstatter VB 6-nivågrafikken.
- Bruker matematikkberegninger for programkontroll: Programmet bruker smart modulo (Mod) og heltall divisjonsberegninger ved bruk av to-spill markør-arrayer for å bestemme når en "tre-element" seier har inntraff.
Klassen for programmering i denne artikkelen er kanskje bare litt forbi begynnelsesnivået, men det skal være bra for "mellomliggende" programmerere. Men la oss begynne på et elementært nivå for å illustrere noen av konseptene og komme i gang med dine Visual Basic spillprogrammeringskarriere. Til og med studenter som er mer avanserte enn det kan synes at det er litt utfordrende å få objektene i form akkurat passe.
Hvordan spille Tic Tac Toe
Hvis du aldri har spilt Tre på rad, her er reglene. To spillere veksler ved å plassere Xs og Os i 3 x 3 spillefelt.
Før spillet starter, må begge spillerne være enige om hvem som skal gå først og hvem som vil markere trekkene hans med hvilket symbol. Etter det første trekket, plasserer spillerne vekselvis merkene sine i en hvilken som helst tom celle. Målet med spillet er å være den første spilleren med tre merker i en horisontal, diagonal eller vertikal linje. Hvis det ikke er tomme celler og ingen av spillerne har en vinnende kombinasjon, er spillet uavgjort.
Før du starter en faktisk koding, er det alltid en god idé å endre navn på komponentene du bruker. Når du begynner koding, brukes navnet automatisk av Visual Basic slik at du vil at det skal være riktig navn. Vi bruker skjemanavnet frmTicTacToe og vi vil også endre bildeteksten til "Om Tic Tac Toe."
Med skjemaet etablert, bruk linjen verktøykasse kontroll for å tegne et 3 x 3 rutenett. Klikk på linjeverktøyet, tegne deretter en linje der du vil ha den. Du må lage fire linjer på denne måten og justere lengden og posisjonen slik at de ser riktig ut. Visual Basic har også noen praktiske verktøy under Format-menyen som vil hjelpe. Dette er en stor sjanse til å øve sammen med dem.
I tillegg til det spillende rutenettet, trenger vi noen objekter for X- og O-symbolene som vil bli plassert på rutenettet. Siden det er ni mellomrom i rutenettet, oppretter vi en objektserie med ni mellomrom, kalt elementer i Visual Basic.
Det er flere måter å gjøre omtrent alt i Visual Basic-utviklingsmiljøet, og det er intet unntak å lage kontrollmatriser. Sannsynligvis den enkleste måten er å lage den første etiketten (klikk og tegne akkurat som linjeverktøyet), navngi den, angi alle attributtene (for eksempel Font og ForeColor), og deretter kopier av den. VB 6 vil spørre om du vil lage en kontrollgruppe. Bruk navnet lblPlayGround for den første etiketten.
For å lage de andre åtte elementene i rutenettet, velg det første etikettobjektet, sett indeksegenskapen til null og trykk CTRL + C (kopi). Nå kan du trykke CTRL + V (lime) for å opprette et annet etikettobjekt. Når du kopierer objekter som dette, vil hver kopi arve alle egenskaper bortsett fra Indeks fra den første. Indeksen vil øke med en for hver kopi. Dette er en kontrollmatrise fordi de alle har samme navn, men forskjellige indeksverdier.
Hvis du oppretter matrisen på denne måten, blir alle kopiene stablet oppå hverandre i øverste venstre hjørne av skjemaet. Dra hver etikett til en av spillernettposisjonene. Forsikre deg om at indeksverdiene er sekvensielle i rutenettet. Logikken til programmet avhenger av det. Etikettobjektet med indeksverdi 0 skal være i øverste venstre hjørne, og nederste høyre etikett skal ha indeks 8. Hvis etikettene dekker det rutenettet som spilles av, velger du hver etikett, høyreklikker og velger Send til tilbake.
Siden det er åtte mulige måter å vinne spillet, trenger vi åtte forskjellige linjer for å vise seieren på det spillende rutenettet. Du vil bruke den samme teknikken for å lage en annen kontrollgruppe. Tegn først linjen, navn den linWin, og sett indeksegenskapen til null. Bruk deretter copy-paste-teknikk for å produsere syv linjer til. Illustrasjonen nedenfor viser hvordan du indikerer indeksnumrene riktig.
I tillegg til etiketten og linjeobjektene, trenger du noen kommandoknapper for å spille spillet og flere etiketter for å beholde poengsummen. Trinnene for å lage disse er ikke detaljerte her, men dette er objektene du trenger.
To-knapp objekter:
- cmdNewGame
- cmdResetScore
Rammeobjekt fraPlayFirst som inneholder to alternativsknapper:
- optXPlayer
- optOPlayer
Rammeobjekt fraScoreBoard som inneholder seks etiketter. Bare lblXScore og lblOScore blir endret i programkoden.
- lblX
- lblXScore
- lblO
- lblOScore
- lblMinus
- lblColon
Til slutt trenger du også etikettobjektet lblStartMsg for å 'maskere' cmdNewGame-knappen når det ikke skal klikkes. Dette er ikke synlig på illustrasjonen nedenfor fordi den har samme plass i formen som kommandoknappen. Du må kanskje flytte kommandoknappen midlertidig for å tegne denne etiketten på skjemaet.
Så langt har ingen VB-koding blitt gjort, men vi er endelig klare til å gjøre det.
initialisering
Nå får du endelig begynne å kode programmet. Hvis du ikke allerede har gjort det, kan det være lurt å laste ned kildekoden som skal følges, mens driften av programmet blir forklart.
En av de første designbeslutningene som tas, er hvordan du kan holde oversikt over dagens "tilstand" i spillet. Med andre ord, hva er nåværende X-er og Os på spillnettet og hvem som beveger seg neste. Konseptet "tilstand" er kritisk i mye programmering, og spesielt er det viktig i programmering av ASP og ASP.NET for nettet
Det er flere måter dette kan gjøres, så det er et kritisk trinn i analysen. Hvis du løste dette problemet på egen hånd, kan det være lurt å tegne et flytdiagram og prøve ut forskjellige alternativer med 'skrapapapir' før du starter koding.
Løsningen vår bruker to "todimensjonale matriser" fordi det hjelper med å holde oversikt over 'tilstand' ved å bare endre arrayindeksene i programløkker. Tilstanden til øverste venstre hjørne vil være i matriseelementet med indeks (1, 1), øverste høyre hjørne vil være i (1, 3), nede til høyre i (3,3), og så videre. De to matriser som gjør dette er:
iXPos (x, y)
og
iOPos (x, y)
Det er mange forskjellige måter dette kan gjøres, og den endelige VB.NET-løsningen i denne serien viser deg hvordan du gjør det med bare en enkelt dimensjonal matrise.
Programmeringen for å oversette disse matrikkene til spillerens avgjørelser og synlige skjermer i skjemaet er på neste side.
Du trenger også noen få globale variabler som følger. Legg merke til at disse er i koden Generelle og erklæringer for skjemaet. Dette gjør dem "modulenivå" variabler som kan henvises hvor som helst i koden for dette skjemaet. For mer om dette, sjekk Forstå omfanget av variabler i Visual Basic Hjelp.
Det er to områder der variabler initialiseres i vårt program. Først initialiseres noen få variabler mens formen frmTicTacToe lastes inn.
Privat subform_Load ()
For det andre, før hvert nye spill, tildeles alle variabler som må tilbakestilles til startverdiene i en initialiseringssubutine.
Sub InitPlayGround ()
Merk at initialiseringen av skjemabelastningen også kaller initialiseringen av lekeplassen.
En av de kritiske ferdighetene til en programmerer er muligheten til å bruke feilsøkingsfasilitetene for å forstå hva koden gjør. Du kan bruke dette programmet til å prøve:
- Gå gjennom koden med F8-tasten
- Innstille en klokke på viktige variabler, for eksempel sPlaySign eller iMove
Stille inn et brytepunkt og spørre verdien til variabler. For eksempel i den indre løkken av initialiseringen:
lblPlayGround ((i - 1) * 3 + j - 1). Bildetekst = ""
Merk at dette programmet tydelig viser hvorfor det er en god programmeringspraksis å oppbevare data i matriser når det er mulig. Hvis du ikke hadde matriser i dette programmet, ville du måtte skrive kode slik:
Line0.Visible = Falsk
Line1.Visible = Falsk
Line2.Visible = Falsk
Line3.Visible = Falsk
Line4.Visible = Falsk
Line5.Visible = Falsk
Line6.Visible = Falsk
Line7.Visible = Falsk
istedenfor dette:
For i = 0 til 7
linWin (i). Visible = Falsk
Neste jeg
Gjør et trekk
Hvis noen del av systemet kan tenkes som 'hjertet', er det subroutine lblPlayGround_Click. Denne subrutinen kalles hver gang en spiller klikker på spillrutenettet. (Klikk må være inne i et av de ni lblPlayGround-elementene.) Legg merke til at denne subroutinen har et argument: (Indeks som heltall). De fleste av de andre hendelsesunderrutinene, som cmdNewGame_Click (), gjør det ikke. Indeks indikerer hvilket etikettobjekt som er klikket. For eksempel vil indeksen inneholde verdien null for øverste venstre hjørne av rutenettet og verdien åtte for nederst til høyre hjørne.
Etter at en spiller klikker en firkant i spillnettet, blir kommandoknappen for å starte et nytt spill, cmdNewGame, "slått på" ved å gjøre det synlig. Tilstanden til denne kommandoknappen gjør dobbelt plikt fordi den også brukes som en boolesk beslutningsvariabel senere i programmet. Å bruke en eiendomsverdi som en beslutningsvariabel, frarådes vanligvis fordi det hvis det noen gang blir nødvendig å endre programmet (si for eksempel for å lage cmdNewGame-kommandoknappen er synlig hele tiden), da vil programmet uventet mislykkes fordi du kanskje ikke husker at det også brukes som en del av programmet logikk. Av denne grunn er det alltid en god idé å søke gjennom programkode og sjekke bruken av alt du endrer når du gjør programvedlikehold, til og med eiendomsverdier. Dette programmet bryter regelen delvis for å gjøre dette poenget, og delvis fordi dette er et relativt enkelt stykke kode der det er lettere å se hva som blir gjort og unngå problemer senere.
Et spillervalg av et spillfelt blir behandlet ved å kalle GamePlay-underrutinen med Indeks som argument.
Behandler trekk
Først sjekker du om det ble klikket på et ledig torg.
Hvis lblPlayGround (xo_Move) .Caption = "" Da
Når vi er sikre på at dette er et legitimt trekk, økes flyttelleren (iMove). De neste to linjene er veldig interessante, siden de oversetter koordinatene fra den endimensjonale Hvis lblPlayGround-komponenten blir til todimensjonale indekser som du kan bruke i iXPos eller iOPos. Mod- og heltaledivisjon ('motslettet') er matematiske operasjoner som du ikke bruker hver dag, men her er et flott eksempel som viser hvordan de kan være veldig nyttige.
Hvis lblPlayGround (xo_Move) .Caption = "" Da
iMove = iMove + 1
x = Int (xo_Move / 3) + 1
y = (xo_Move Mod 3) + 1
Verdien xo_Move 0 blir oversatt til (1, 1), 1 til (1, 2)... 3 til (2, 1)... 8 til (3, 3).
Verdien i sPlaySign, en variabel med modulomfang, holder oversikt over hvilken spiller som gjorde farten. Når flyttearrangene er oppdatert, kan etikettkomponentene i det spillende rutenettet oppdateres med riktig tegn.
Hvis sPlaySign = "O" Da
iOPos (x, y) = 1
iWin = CheckWin (iOPos ())
Ellers
iXPos (x, y) = 1
iWin = CheckWin (iXPos ())
Slutt om
lblPlayGround (xo_Move) .Caption = sPlaySign
Når for eksempel X-spilleren klikker øvre venstre hjørne av rutenettet, vil variablene ha følgende verdier:
Brukerskjermen viser bare et X i øvre venstre boks, mens iXPos har en 1 i øvre venstre boks og 0 i alle de andre. IOPos har 0 i hver boks.
Verdiene endres når O-spilleren klikker på midtre firkant av rutenettet. Nå viser iOPos en 1 i midtboksen mens brukerskjermen viser et X øverst til venstre og en O i midtboksen. IXPos viser bare 1 i øvre venstre hjørne, med 0 i alle de andre boksene.
Nå som du vet hvor en spiller klikket, og hvilken spiller som klikket (ved å bruke verdien i sPlaySign), alt du trenger å gjøre er å finne ut om noen vant et spill og finne ut hvordan du kan vise det i vise.
Finne en vinner
Etter hvert trekk, sjekker CheckWin-funksjonen for den vinnende kombinasjonen. CheckWin fungerer ved å legge ned hver rad, på tvers av hver kolonne og gjennom hver diagonal. Det kan være veldig lærerikt å spore trinnene gjennom CheckWin ved hjelp av Visual Basys avlusingsfunksjon. Å finne en gevinst er et spørsmål om først, sjekke om tre 1-er ble funnet i hver av de individuelle sjekkene i variabelen iScore, og deretter returnerer en unik "signatur" -verdi i Checkwin som brukes som matrixindeks for å endre synlig egenskap for ett element i linWin komponentgruppe. Hvis det ikke er noen vinner, vil CheckWin inneholde verdien -1. Hvis det er en vinner, blir skjermen oppdatert, resultattavlen endres, en gratulasjonsmelding vises, og spillet startes på nytt.
La oss gå gjennom en av sjekkene i detalj for å se hvordan det fungerer. De andre er like.
'Kontroller radene for 3
For i = 1 til 3
iScore = 0
CheckWin = CheckWin + 1
For j = 1 til 3
iScore = iScore + iPos (i, j)
Neste j
Hvis iScore = 3 Da
Avslutt funksjon
Slutt om
Neste jeg
Den første tingen å merke seg er at den første indekstelleren i teller ned radene, mens den andre j teller over kolonnene. Den ytre løkken beveger seg ganske enkelt fra den ene raden til den neste. Den indre løkken teller 1-ene i den gjeldende raden. Hvis det er tre, har du en vinner.
Legg merke til at du også holder oversikt over det totale antall rutene som er testet i variabelen CheckWin, som er verdien som blir returnert når denne funksjonen avsluttes. Hver vinnende kombinasjon vil ende opp med en unik verdi i CheckWin fra 0 til 7 som brukes til å velge et av elementene i linWin () -komponentgruppen. Dette gjør rekkefølgen på koden i funksjonen CheckWin også viktig! Hvis du flyttet en av blokkene med sløyfekode (som den ovenfor), vil feil linje bli trukket på det spillende rutenettet når noen vinner. Prøv det og se!
Etterbehandlingsdetaljer
Den eneste koden som ikke er diskutert ennå er subroutine for et nytt spill og subroutine som vil tilbakestille poengsummen. Resten av logikken i systemet gjør det enkelt å lage disse. For å starte et nytt spill, trenger du bare å ringe InitPlayGround-underrutinen. Som en bekvemmelighet for spillere siden knappen kan klikkes midt i et spill, ber du om bekreftelse før du går videre. Du ber også om bekreftelse før du starter på nytt resultattavlen.