Програмиране на Tic Tac Toe Game във Visual Basic

Програмиране компютърни игри може да е най-трудната техническа (и вероятно най-добре платената) работа, която а програмист мога да имам. Игрите от най-високо ниво изискват най-доброто както от програмистите, така и от компютрите.

Visual Basic 6 вече е напълно заобиколен като платформа за програмиране на игри. (Никога всъщност не е било такова. Дори в "добрите дни", сериозните програмисти за игри никога не биха използвали език на високо ниво като VB 6, защото просто не можете да получите рязането производителност на ръба, която изискват повечето игри.) Но простата игра "Tic Tac Toe" е чудесно въведение в програмирането, което е малко по-напреднало от "Здравей свят!"

Това е чудесно въведение към много от основните концепции на програмирането, тъй като съчетава техники, включително:

  • Използването на масиви. Маркерите X и O се съхраняват в отделни масиви, а целият масив се предава между функции, за да следи напредъка на играта.
  • Използване на графика на ниво VB 6: VB 6 не предлага големи графични възможности, но играта е добро запознаване с това, което е на разположение. Голяма част от останалата част от тази серия е проучване на това как GDI +, следващото поколение графики на Microsoft, заменя графиките на ниво VB 6.
    instagram viewer
  • Използване на математически изчисления за контрол на програмата: Програмата използва умен модул (Mod) и цяло число изчисления на разделението, използвайки маркерите за двуименни маркери, за да определите кога има триелементна "победа" настъпили.

Класът на програмиране в тази статия е може би просто малко над началното ниво, но би трябвало да е добър за „междинните“ програмисти. Но нека започнем на елементарно ниво, за да илюстрираме някои от концепциите и да започнем с вашето Visual Basic кариера за програмиране на игри. Дори студентите, по-напреднали от това, може да открият, че е леко предизвикателство да се получат предметите във формата точно.

Как се играе Tic Tac Toe

Ако никога не сте играли Морски шах, ето правилата. Двама играчи се редуват при поставянето на Xs и Os в 3 x 3 игрално поле.

Преди началото на играта и двамата играчи трябва да се споразумеят кой ще отиде пръв и кой ще маркира ходовете си с кой символ. След първия ход играчите последователно поставят своите знаци във всяка празна клетка. Целта на играта е да бъде първият играч с три марки в хоризонтална, диагонална или вертикална линия. Ако няма празни клетки и нито един от играчите няма печеливша комбинация, играта е равенство.

Преди да започнете действителното кодиране, винаги е добра идея да промените имената на всички компоненти, които използвате. След като започнете кодиране, името ще бъде използвано автоматично от Visual Basic, така че искате да е правилното име. Ще използваме името на формата frmTicTacToe и също така ще променим надписа на „За Tic Tac Toe“.

Със създадения формуляр използвайте линията за управление на линията с инструменти, за да нарисувате 3 x 3 решетка. Щракнете върху инструмента за линия, след което нарисувайте линия, където искате. По този начин ще трябва да създадете четири реда и да коригирате дължината и позицията им, за да изглеждат правилно. Visual Basic също има някои удобни инструменти в менюто Формат, които ще ви помогнат. Това е голям шанс да практикувате с тях.

В допълнение към игралната мрежа ще ни трябват някои обекти за символите X и O, които ще бъдат поставени в мрежата. Тъй като в мрежата има девет пространства, ще създадем обект от масив с девет интервала, наречени елементи във Visual Basic.

Има няколко начина да направите почти всичко в средата за разработка на Visual Basic и създаването на контролни масиви не е изключение. Вероятно най-лесният начин е да създадете първия етикет (щракнете и нарисувайте точно като инструмента за линия), дайте го име, задайте всички атрибути (като Font и ForeColor) и след това направете копия от него. VB 6 ще ви попита дали искате да създадете контролен масив. Използвайте името lblPlayGround за първия етикет.

За да създадете останалите осем елемента на мрежата, изберете първия обект на етикета, задайте свойството Index на нула и натиснете CTRL + C (копиране). Сега можете да натиснете CTRL + V (паста), за да създадете друг обект на етикет. Когато копирате обекти като този, всяко копие ще наследи всички свойства, с изключение на Index от първото. Индексът ще се увеличи с по един за всяко копие. Това е контролен масив, защото всички те имат едно и също име, но различни стойности на индекса.

Ако създадете масива по този начин, всички копия ще бъдат подредени един върху друг в горния ляв ъгъл на формуляра. Плъзнете всеки етикет до една от позициите на мрежата за игра. Уверете се, че стойностите на индекса са последователни в мрежата. Логиката на програмата зависи от нея. Обектът на етикета със стойност на индекса 0 трябва да бъде в горния ляв ъгъл, а долният десен етикет трябва да има индекс 8. Ако етикетите покриват мрежата за игра, изберете всеки етикет, щракнете с десния бутон на мишката и изберете Изпращане на гръб.

Тъй като има осем възможни начина да спечелите играта, ще ни трябват осем различни линии, за да покажем печалбата в игралната мрежа. Ще използвате същата техника, за да създадете друг контролен масив. Първо, начертайте линията, наречете я linWin и задайте свойството Index на нула. След това използвайте техниката copy-paste, за да създадете още седем реда. Следващата илюстрация показва как да настроите правилно числата на индекса.

В допълнение към обектите на етикета и линията се нуждаете от някои командни бутони за игра и още етикети, за да запазите резултата. Стъпките за създаването им не са подробно описани тук, но това са обектите, от които се нуждаете.

Два бутона обекти:

  • cmdNewGame
  • cmdResetScore

Обект на кадър fraPlayFirst, съдържащ два бутона за опция:

  • optXPlayer
  • optOPlayer

Frame object fraScoreBoard, съдържащ шест етикета. В кода на програмата се променят само lblXScore и lblOScore.

  • lblX
  • lblXScore
  • lblO
  • lblOScore
  • lblMinus
  • lblColon

И накрая, вие също се нуждаете от обекта на етикет lblStartMsg, за да "маскирате" бутона cmdNewGame, когато не трябва да щракнете. Това не се вижда на илюстрацията по-долу, тъй като заема същото място във формата като командния бутон. Може да се наложи временно да преместите командния бутон, за да нарисувате този етикет върху формата.

Засега не е извършено кодиране на VB, но най-накрая сме готови да направим това.

Инициализация

Сега най-накрая можете да започнете да кодирате програмата. Ако все още не сте, може да искате да изтеглите изходния код, който да следвате, след като е обяснена работата на програмата.

Едно от първите дизайнерски решения е как да следим текущото „състояние“ на играта. С други думи, какви са текущите Xs и Os в игралната мрежа и кой се движи следващия. Понятието „състояние“ е от решаващо значение при много програмиране и по-специално е важно при програмирането на ASP и ASP.NET за мрежата

Има няколко начина, по които това може да се направи, така че това е критична стъпка в анализа. Ако решавате този проблем самостоятелно, може да искате да начертаете блок-схема и да изпробвате различни опции с "скреч хартия", преди да започнете кодиране.

Нашето решение използва два "двуизмерни масива", защото това помага да се следи "състоянието", като просто се променят индексите на масива в програмните контури. Състоянието на горния ляв ъгъл ще бъде в елемента на масива с индекс (1, 1), горният десен ъгъл ще бъде в (1, 3), долният десен в (3,3) и т.н., Двата масива, които правят това, са:

iXPos (x, y)

и

iOPos (x, y)

Има много различни начини това може да се направи и окончателното решение на VB.NET в тази серия ви показва как да го направите само с един едномерен масив.

Програмирането за превеждане на тези масиви в решения за спечелване на играчи и видими дисплеи във формата са на следващата страница.

Имате нужда и от няколко глобални променливи, както следва. Забележете, че те са в общия и декларационния код за формуляра. Това ги прави "ниво на модул" променливи, на които може да се посочи навсякъде в кода за тази форма. За повече информация относно това, проверете Разбиране на обхвата на променливите в Visual Basic Help.

Има две области, където променливите се инициализират в нашата програма. Първо, няколко променливи се инициализират, докато формата frmTicTacToe се зарежда.

Private Sub Form_Load ()

Второ, преди всяка нова игра всички променливи, които трябва да бъдат нулирани към началните стойности, се задават в подпрограма за инициализация.

Sub InitPlayGround ()

Обърнете внимание, че инициализацията на зареждане на формуляр също извиква инициализацията на детската площадка.

Едно от критичните умения на програмиста е възможността да използва средствата за отстраняване на грешки, за да разбере какво прави кодът. Можете да използвате тази програма, за да опитате:

  • Преминаване през кода с клавиша F8
  • Задаване на часовник на ключови променливи, като sPlaySign или iMove
    Задаване на точка на прекъсване и запитване на стойността на променливите. Например във вътрешния цикъл на инициализацията:
lblPlayGround ((i - 1) * 3 + j - 1) .Caption = ""

Имайте предвид, че тази програма ясно показва защо е добра практика на програмиране да се съхраняват данни в масиви, когато е възможно. Ако нямате масиви в тази програма, ще трябва да напишете код нещо подобно:

Line0.Visible = Грешно
Line1.Visible = Грешно
Line2.Visible = Грешно
Line3.Visible = Грешно
Line4.Visible = Грешно
Line5.Visible = Грешно
Line6.Visible = Грешно
Line7.Visible = Грешно

вместо това:

За i = 0 до 7
linWin (i) .Visible = Грешно
Следващ i

Да направим ход

Ако някоя част от системата може да се мисли като „сърцето“, това е подпрограма lblPlayGround_Click. Тази подпрограма се извиква всеки път, когато играч кликне върху игралната мрежа. (Кликванията трябва да са вътре в един от деветте елемента lblPlayGround.) Забележете, че тази подпрограма има аргумент: (Индекс като цяло число). Повечето от другите подпрограми на събитията, като cmdNewGame_Click (), не го правят. Индексът показва кой обект на етикет е щракнат. Например, индексът ще съдържа стойността нула за горния ляв ъгъл на мрежата и стойността осем за долния десен ъгъл.

След като играч кликне върху квадрат в игровата мрежа, командният бутон за стартиране на друга игра, cmdNewGame, се „включва“, като го прави видим. Състоянието на този команден бутон изпълнява двойно задължение, тъй като се използва и като булева променлива за решение по-късно в програмата. Използването на стойност на свойството като променлива за решение обикновено се обезкуражава, защото ако някога се наложи да промените програмата (да речем например, за да направите командният бутон cmdNewGame видим през цялото време), тогава програмата неочаквано ще се провали, защото може да не си спомняте, че се използва и като част от програмата логика. Поради тази причина винаги е добра идея да търсите програмния код и да проверите използването на всичко, което промените, когато правите поддръжка на програмата, дори стойности на свойствата. Тази програма нарушава правилото отчасти да се направи тази точка и отчасти защото това е сравнително прост код, където е по-лесно да се види какво се прави и да се избегнат проблеми по-късно.

Избор на играч на игровия квадрат се обработва чрез извикване на подпрограмата GamePlay с аргумент Index.

Обработка на движение

Първо проверявате дали е щракнат незает квадрат.

Ако lblPlayGround (xo_Move) .Caption = "" Тогава

След като сме сигурни, че това е легитимен ход, броячът на ход (iMove) се увеличава. Следващите два реда са много интересни, тъй като превеждат координатите от едноизмерните Ако lblPlayGround компонент масив до двуизмерни индекси, които можете да използвате в iXPos или iOPos. Модно и цяло число разделение ("обратната черта") са математически операции, които не използвате всеки ден, но ето чудесен пример, показващ как те могат да бъдат много полезни.

Ако lblPlayGround (xo_Move) .Caption = "" Тогава
iMove = iMove + 1
x = Int (xo_Move / 3) + 1
y = (xo_Move Mod 3) + 1

Стойността xo_Move 0 ще бъде преведена в (1, 1), 1 до (1, 2)... 3 до (2, 1)... 8 до (3, 3).

Стойността в sPlaySign, променлива с обхват на модула, следи кой играч е направил ход. След като масивите за движение се актуализират, компонентите на етикетите в игралната мрежа могат да бъдат актуализирани със съответния знак.

Ако sPlaySign = "O", тогава
iOPos (x, y) = 1
iWin = CheckWin (iOPos ())
още
iXPos (x, y) = 1
iWin = CheckWin (iXPos ())
Край Ако
lblPlayGround (xo_Move) .Caption = sPlaySign

Например, когато X играчът кликне в горния ляв ъгъл на мрежата, променливите ще имат следните стойности:

Потребителският екран показва само X в горната лява кутия, докато iXPos има 1 в горната лява кутия и 0 във всички останали. IOPos има 0 във всяко поле.

Стойностите се променят, когато O плейърът кликне върху централния квадрат на мрежата. Сега iOPos показва 1 в централната кутия, докато екранът на потребителя показва X в горната лява част и O в централната кутия. IXPos показва само 1 в горния ляв ъгъл, с 0 във всички останали полета.

Сега, когато знаете къде играч е щракнал и кой играч е извършил щракването (използвайки стойността в sPlaySign), всичко, което трябва да направите, е да разберете дали някой е спечелил игра и да измислите как да покажете това в показване.

Намиране на победител

След всеки ход функцията CheckWin проверява за печелившата комбинация. CheckWin работи, като добавя всеки ред, през всяка колона и през всеки диагонал. Проследяването на стъпките през CheckWin с помощта на функцията за отстраняване на грешки на Visual Basic може да бъде много образователно. Намирането на печалба е въпрос на първо място, проверка дали са намерени три 1 във всяка от отделните проверки в променливата iScore, а след това връщане на уникална стойност "подпис" в Checkwin, която се използва като индекс на масива за промяна на свойството Visible на един елемент в linWin масив от компоненти Ако няма победител, CheckWin ще съдържа стойността -1. Ако има победител, дисплеят се актуализира, таблото се променя, показва се поздравително съобщение и играта се рестартира.

Нека да преминем подробно през една от проверките, за да видим как работи. Другите са подобни.

„Проверка на редове за 3
За i = 1 до 3
iScore = 0
CheckWin = CheckWin + 1
За j = 1 до 3
iScore = iScore + iPos (i, j)
Следващ j
Ако iScore = 3 Тогава
Излезте от функцията
Край Ако
Следващ i

Първото нещо, което трябва да забележите, е, че първият брояч на индекси i отброява редовете, докато вторият j се брои през колоните. Външният контур, след това просто се премества от един ред в следващия. Вътрешният цикъл отчита 1-те в текущия ред. Ако има три, значи имате победител.

Забележете, че следите и общия брой квадратчета, тествани в променливата CheckWin, която е стойността, предадена обратно при прекратяване на тази функция. Всяка печеливша комбинация ще завърши с уникална стойност в CheckWin от 0 до 7, която се използва за избор на един от елементите в компонентния масив linWin (). Това прави и редът на кода във функция CheckWin важен! Ако сте преместили един от блоковете на код на контура (като тази по-горе), грешната линия ще бъде очертана на игралната мрежа, когато някой спечели. Опитайте и вижте!

Детайли за довършителни работи

Единственият код, който все още не е обсъден, е подпрограмата за нова игра и подпрограмата, която ще нулира резултата. Останалата част от логиката в системата прави създаването на тези доста лесни. За да започнете нова игра, трябва само да се обадите на подпрограмата InitPlayGround. Като удобство за играчите, тъй като бутонът може да бъде кликнат в средата на играта, вие молете за потвърждение, преди да продължите напред. Можете също така да поискате потвърждение, преди да рестартирате таблицата.