Crearea unui minesweeper hexagonal

Ce veți crea

În acest tutorial, voi încerca să introduc lumea interesantă a jocurilor pe bază de țiglă hexagonală utilizând cele mai ușoare abordări. Veți învăța cum să convertiți datele matriceale bidimensionale la un nivel de nivel hexagonal corespunzător pe ecran și invers. Folosind informațiile obținute, vom crea un joc hexagonal de minesweeper în două scheme diferite hexagonale.

Acest lucru vă va face să începeți cu explorarea jocurilor de bord hexagonale simple și a jocurilor puzzle și va fi un bun punct de plecare pentru a afla abordări mai complexe, cum ar fi sistemele de coordonate hexagonale axiale sau cubice.

1. Placi hexagonale și planșe

În generația curentă de jocuri casual, nu vedem multe jocuri care utilizează o abordare pe bază de țiglă hexagonală. Ceea ce întâlnim noi sunt, de obicei, jocuri de puzzle, jocuri de bord sau jocuri de strategie. De asemenea, majoritatea cerințelor noastre sunt îndeplinite de abordarea pătratică sau de abordarea izometrică. Aceasta duce la întrebarea firească: "De ce avem nevoie de o abordare hexagonală diferită și evident complicată?" Să aflăm.

Avantajele abordării hexagonale

Deci, ceea ce face ca abordarea pe bază de țiglă hexagonală să fie relevantă, deoarece deja avem alte abordări învățate și perfecționate? Permiteți-mi să enumăr câteva motive.

  • Numărul mai mic de țigle vecine: în comparație cu o rețea pătrată, care va avea opt plăci vecine, o țiglă hexagonală va avea doar șase vecini. Aceasta reduce calculele pentru algoritmi complicați.
  • Toate plăcile vecine sunt la aceeași distanță: pentru o rețea pătrată, cei patru vecini diagonali sunt departe în comparație cu vecinii orizontali sau verticali. Vecinii care se află la distanțe egale este o mare ușurare atunci când calculăm euristica și reducem cheltuielile de utilizare a două metode diferite pentru a calcula ceva în funcție de vecin.
  • Unicitatea: în zilele noastre, milioane de jocuri casual ies și concurează pentru timpul jucătorului. Jocurile mari nu reușesc să obțină o audiență și un lucru care poate fi garantat pentru a atrage atenția unui jucător este unicitatea. Un joc care utilizează o abordare hexagonală se va deosebi vizual de restul jocului și jocul va părea mai interesant pentru o mulțime de oameni care se plictisesc de toată mecanica de joc convențională. 

Aș spune că ultimul motiv ar trebui să fie suficient pentru a vă stăpâni această nouă abordare. Adăugarea acestui element unic de joc peste logica jocului ar putea face diferența și vă va permite să faceți un joc minunat. 

Celelalte motive sunt pur tehnice și ar intra în vigoare numai după ce v-ați confruntat cu algoritmi complicați sau seturi de plăci mai mari. Există și multe alte aspecte care pot fi enumerate ca avantaje ale abordării hexagonale, dar majoritatea vor depinde de interesul personal al jucătorului.

aspecte

Un hexagon este un poligon cu șase laturi, iar un hexagon cu toate laturile având aceeași lungime se numește hexagon normal. Din punct de vedere teoretic, vom considera că plăcile hexagonale sunt hexagoane regulate, dar ele pot fi îndoite sau alungite în practică. 

Lucrul interesant este acela că un hexagon poate fi plasat în două moduri diferite: colțurile cu vârfuri ar putea fi aliniate vertical sau orizontal. Când vârfurile vârfurilor sunt aliniate vertical, se numește a orizontală aspect, și atunci când acestea sunt aliniate orizontal, se numește a vertical aspect. S-ar putea să credeți că numele sunt improprii în ceea ce privește explicația furnizată. Nu este cazul, deoarece denumirea nu se face pe baza colțurilor ascuțite, ci a modului în care se întinde o rețea de plăci. Imaginea de mai jos prezintă diferitele aliniamente ale plăcilor și dispunerea corespunzătoare.

Alegerea aspectului depinde în întregime de viziunile și jocul jocului. Cu toate acestea, alegerea dvs. nu se termină aici, deoarece fiecare dintre aceste planuri ar putea fi implementat în două moduri diferite.

Să luăm în considerare o dispunere orizontală a grilei hexagonale. Rândurile alternative ale grila ar trebui să fie compensate orizontal de către hexTileWidth / 2. Aceasta înseamnă că am putea alege să compenseze fie rândurile ciudate, fie rândurile uniforme. Dacă afișăm și mesajul corespunzător rând, coloană valori, aceste variante ar arăta ca imaginea de mai jos.

În mod similar, structura verticală ar putea fi implementată în două variante în timp ce se compensează coloanele alternative prin hexTileHeight / 2 așa cum se arată mai jos.

2. Implementarea planșelor hexagonale

De aici încolo, vă rugăm să începeți să vă referiți la codul sursă furnizat împreună cu acest tutorial pentru o mai bună înțelegere

Imaginile de mai sus, cu rândurile și coloanele afișate, facilitează vizualizarea unei corelații directe cu o matrice bidimensională care stochează datele de nivel. Să presupunem că avem o simplă matrice bidimensională levelData ca mai jos.

var nivelData = [[0,0,0,0,0], [0,0,0,0,0], [0,0,0,0,0], [0,0,0,0,0] ], [0,0,0,0,0]]

Pentru a facilita vizualizarea, voi arăta rezultatul dorit aici, atât în ​​variante verticale cât și orizontale.

Să începem cu aspectul orizontal, care este imaginea din partea stângă. În fiecare rând, dacă sunt luate individual, plăcile vecine sunt deplasate orizontal prin hexTileWidth. Rândurile alternative sunt compensate orizontal cu o valoare de hexTileWidth / 2. Diferența verticală înălțime dintre fiecare rând este hexTileHeight * 3/4

Pentru a înțelege modul în care am ajuns la o astfel de valoare pentru compensarea înălțimii, trebuie să luăm în considerare faptul că porțiunile triunghiulare superioare și inferioare ale unui hexagon așezat orizontal sunt exact hexTileHeight / 4

Aceasta înseamnă că hexagonul are dreptunghiular hexTileHeight / 2 porțiune în mijloc, un triunghiular hexTileHeight / 4 partea de sus și un triunghiular inversat hexTileHeight / 4 porțiune pe partea de jos. Această informație este suficientă pentru a crea codul necesar pentru a stabili grila hexagonală pe ecran.

var verticalOffset = hexTileHeight * 3/4; var orizontalOffset = hexTileWidth; var startX; var startY; var startXInit = hexTileWidth / 2; var startYInit = hexTileHeight / 2; var hexTile; pentru (var i = 0; i < levelData.length; i++)  if(i%2!==0) startX=2*startXInit; else startX=startXInit;  startY=startYInit+(i*verticalOffset); for (var j = 0; j < levelData[0].length; j++)  if(levelData[i][j]!=-1) hexTile= new HexTile(game, startX, startY, 'hex',false,i,j,levelData[i][j]); hexGrid.add(hexTile);  startX+=horizontalOffset;  

Cu HexTile prototip, am adăugat câteva funcționalități suplimentare la Phaser.Sprite prototip care îi permite să afișeze eu și j valori. Codul introduce, în esență, o nouă placă hexagonală spiriduș la startx și starty. Acest cod poate fi modificat pentru a afișa varianta uniformă doar prin eliminarea unui operator în dacă astfel: dacă (i% 2 === 0).

Pentru un aspect vertical (imaginea din jumătatea dreaptă), plăcile de vecinătate din fiecare coloană sunt compensate vertical hexTileHeight. Fiecare coloană alternativă este compensată vertical de către hexTileHeight / 2. Aplicând logica pe care am aplicat-o pentru offset vertical pentru structura orizontală, putem vedea că decalajul orizontal pentru structura verticală dintre plăcile vecine într-un rând este hexTileWidth * 3/4. Codul corespunzător este de mai jos.

var verticalOffset = hexTileHeight; var orizontalOffset = hexTileWidth * 3/4; var startX; var startY; var startXInit = hexTileWidth / 2; var startYInit = hexTileHeight / 2; var hexTile; pentru (var i = 0; i < levelData.length; i++)  startX=startXInit; startY=2*startYInit+(i*verticalOffset); for (var j = 0; j < levelData[0].length; j++)  if(j%2!==0) startY=startY+startYInit; else startY=startY-startYInit;  if(levelData[i][j]!=-1) hexTile= new HexTile(game, startX, startY, 'hex', true,i,j,levelData[i][j]); hexGrid.add(hexTile);  startX+=horizontalOffset;  

În același mod ca și în cazul planșelor orizontale, putem trece la varianta uniformă doar prin eliminarea ! operator în partea de sus dacă condiție. Eu folosesc un Phaser grup pentru a colecta toate hexTiles numit hexGrid. Pentru simplitate, folosesc punctul central al imaginii hexagonale ca o ancoră, altfel ar trebui să luăm în considerare și compensările imaginii. 

Un lucru de observat este că valorile lățimii plăcilor și ale înălțimii plăcilor în aspectul orizontal nu sunt egale cu lățimea plăcilor și valorile înălțimii plăcilor în aspectul vertical. Dar când folosim aceeași imagine pentru ambele planuri, am putea doar să rotim imaginea țiglelor la 90 de grade și să schimbăm valorile lățimii plăcilor și înălțimea plăcilor.

3. Găsirea indexului matricei unei plăci hexagonale

Matricea de afișare a logicii plasamentului a fost interesantă, dar inversul nu este atât de ușor. Considerăm că trebuie să găsim indicele matrice al plăcii hexagonale pe care am reușit să-l atingem. Codul pentru a realiza acest lucru nu este destul de frumos și, de obicei, este atins de unele încercări și erori. 

Dacă luăm în considerare aspectul orizontal, ar putea părea că porțiunea dreptunghiulară mijlocie a plăcii hexagonale poate ajuta cu ușurință să ne dăm seama j valoare, deoarece este doar o chestiune de împărțire X valoare prin hexTileWidth și luând valoarea întregului. Dar dacă nu știm eu valoare, nu știm dacă suntem pe un rând impar sau par. O valoare aproximativă de eu poate fi găsită prin împărțirea valorii y prin hexTileHeight * 3/4

Acum vin părțile complicate ale plăcilor hexagonale: porțiunile triunghiulare de sus și de jos. Imaginea de mai jos ne va ajuta să înțelegem problema la îndemână.

Regiunile 2, 3, 5, 6, 8 și 9 formează împreună o singură țiglă. Partea cea mai complicată este să găsești dacă poziția cu filet este de 1/2 sau 3/4 sau 7/8 sau 9/10. Pentru aceasta, trebuie să luăm în considerare toate regiunile triunghiulare individuale și să le verificăm folosind panta marginii înclinate. 

Această pantă poate fi găsită din înălțimea și lățimea fiecărei regiuni triunghiulare, care sunt, respectiv hexTileHeight / 4 și hexTileWidth / 2. Permiteți-mi să vă arăt funcția care face acest lucru.

funcția findHexTile () var pos = game.input.activePointer.position; pos.x- = hexGrid.x; pos.y- = hexGrid.y; var xVal = Math.floor ((poz.x) / hexTileWidth); var yVal = Math.floor ((poz.y) / (hexTileHeight * 3/4)); var dX = (poz.x)% hexTileWidth; var dY = (poziția)% (hexTileHeight * 3/4); varianta var = (hexTileHeight / 4) / (hexTileWidth / 2); var caldY = dX * panta; var delta = HexTileHeight / 4-caldY; dacă yVal% 2 === 0) // corecția trebuie să se întâmple în porțiuni triunghiulare și rândurile offset dacă (Math.abs (delta)> dY) if (delta> 0) // xVal--; yVal--;  altceva // separat rândul din stânga jos jumătate yVal--;  altceva if (dX> hexTileWidth / 2) // valorile disponibile nu funcționează pentru jumătatea dreaptă de jos a rândului, dacă (dY<((hexTileHeight/2)-caldY))//even row bottom right half yVal--;  else if(dY>caldY) // un rând de rând dreapta sus și jumătate dreaptă xVal--;  altceva // chiar rândul din stânga jos stânga jumătate yVal--;  pos.x = yVal; pos.y = xVal; retur; 

Mai întâi, găsim xVal și yVal la fel cum am face pentru o rețea pătrată. Apoi găsim restul orizontal (dX) și verticală (dY) după îndepărtarea offsetului multiplicatorului plăcilor. Folosind aceste valori, încercăm să aflăm dacă punctul se află în oricare din regiunile triunghiulare complicate. 

Dacă se găsește, vom face modificări corespunzătoare valorilor inițiale ale xVal și yVal. După cum am spus mai devreme, codul nu este destul și nu este simplu. Cea mai ușoară modalitate de a înțelege acest lucru ar fi să sunați findHexTile pe mutarea mouse-ului, și apoi pus console.log în interiorul fiecăreia dintre aceste condiții și deplasați mouse-ul peste diferite regiuni în cadrul unei plăci hexagonale. În acest fel, puteți vedea modul în care este gestionată fiecare regiune intra-hexagonală.

Modificările codului pentru aspectul vertical sunt prezentate mai jos.

funcția findHexTile () var pos = game.input.activePointer.position; pos.x- = hexGrid.x; pos.y- = hexGrid.y; var xVal = Math.floor ((poz.x) / (hexTileWidth * 3/4)); var yVal = Math.floor ((poz.y) / (hexTileHeight)); var dX = (poz.x)% (hexTileWidth * 3/4); var dY = (poziția)% (hexTileHeight); varianta var = (hexTileHeight / 2) / (hexTileWidth / 4); var caldX = dY / panta; var delta = hexilungime / 4-caldX; dacă dx> Math.abs (delta)) // chiar stânga altceva // ciudat dreapta dacă (delta> 0) // partea inferioară dreaptă xVal--; yVal--;  altceva // separat dreapta sus xVal--;  altceva if (delta> 0) if (dX

4. Găsirea vecinilor

Acum, că am găsit piesa pe care am reușit să o găsim, să găsim cele șase plăci învecinate. Aceasta este o problemă foarte ușoară de rezolvat odată ce vom analiza vizual grilă. Să luăm în considerare aspectul orizontal.

Imaginea de mai sus arată impar și par rânduri a unei rețele hexagonale orizontale, atunci când o piesă mijlocie are valoarea de 0 pentru amandoi eu și j. Din imagine, devine clar că dacă rândul este ciudat, atunci pentru o țiglă la i, j vecinii sunt i, j-1, i-1, j-1, i-1, j, i, j + 1, i + 1, j, și i + 1, j-1. Atunci când rândul este echivalent, atunci pentru o țiglă la i, j vecinii sunt i, j-1i-1, ji-1, j + 1i, j + 1i + 1, j + 1, și i + 1, j. Acest lucru ar putea fi calculat manual cu ușurință.

Să analizăm o imagine asemănătoare pentru par și impar coloane al unei grile hexagonale aliniate vertical.

Când avem o coloană ciudată, o țiglă i, j vom avea i, j-1i-1, j-1, i-1, j, i-1, j + 1, i, j + 1, și i + 1, j ca vecini. În mod similar, pentru o coloană uniformă, vecinii sunt i + 1, j-1, i, j-1, i-1, j, i, j + 1, i + 1, j + 1, și i + 1, j

5. Minesweeper hexagonal

Cu ajutorul cunoștințelor de mai sus, putem încerca să realizăm un joc hexagonal de minesweeper în cele două planuri diferite. Să distrugem trăsăturile unui joc de minesweeper.

  1. În interiorul grilajului se va afla numărul de mină N.
  2. Dacă atingem o țiglă cu o mină, jocul se termină.
  3. Dacă atingem o țiglă care are o mină vecină, va afișa numărul de mine imediat în jurul ei.
  4. Dacă atingem o mină fără mine învecinate, ar duce la dezvăluirea tuturor plăcilor conectate care nu au mine.
  5. Putem atinge și țineți pentru a marca o țiglă ca pe o mină.
  6. Jocul este terminat când dezvăluim toate plăcile fără mine.

Putem stoca cu ușurință o valoare în levelData matrice pentru a indica o mină. Aceeași metodă poate fi utilizată pentru a popula valoarea minei din apropiere pe indicele matricei țiglelor învecinate. 

La începutul jocului, vom popula aleatoriu levelData matrice cu numărul N de mine. După aceasta, vom actualiza valorile pentru toate plăcile vecine. Vom folosi o metodă recursivă în lanț pentru a dezvălui toate plăcile goale conectate atunci când player-ul se fixează pe o țiglă care nu are o mină ca vecină.

Nivelul datelor

Trebuie să creați o grilă hexagonală cu aspect frumos, după cum se arată în imaginea de mai jos.

Acest lucru se poate face doar prin afișarea unei porțiuni din levelData matrice. Dacă vom folosi -1 ca valoare pentru o piesă nefolosabilă și 0 ca valoare pentru o piesă utilizabilă, apoi pentru noi levelData pentru a obține rezultatul de mai sus va arăta astfel.

// orizontală în formă de tigla var varDatele = [[-1, -1, -1,0,0,0,0,0,0,0, -1, -1, -1], [-1, -1 , 0,0,0,0,0,0,0,0, -1, -1, -1], [-1,1,0,0,0,0,0,0,0,0, 0, -1, -1], [-1,0,0,0,0,0,0,0,0,0,0, -1, -1], [-1,0,0,0, 0,0,0,0,0,0,0,0, -1], [0,0,0,0,0,0,0,0,0,0,0,0, -1], [ 0,0,0,0,0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0,0, 0, -1], [-1,0,0,0,0,0,0,0,0,0,0,0, -1], [-1,0,0,0,0,0, 0,0,0,0,0, -1, -1], [1, -1,0,0,0,0,0,0,0,0,0, -1, -1], [ -1, -1,0,0,0,0,0,0,0,0, -1, -1, -1], [-1,1 -1,0,0,0,0, 0,0,0, -1, -1, -1]];

În timp ce ne confruntăm prin matrice, am adăuga numai plăci hexagonale atunci când levelData are o valoare de 0. Pentru alinierea verticală, la fel levelData pot fi folosite, dar noi ar trebui transpune matricea. Iată o metodă minunată care poate face acest lucru pentru dvs..

levelData = transpusa (levelData); // ... function transpose (a) return Object.keys (a [0]) harta (functie (c) return a.map (function (r) return r [c]; 

Adăugarea de mine și actualizarea vecinilor

În mod prestabilit levelData are doar două valori, -1 și 0, din care vom folosi doar zona cu 0. Pentru a indica faptul că o țiglă conține o mină, putem folosi valoarea lui 10

O placă hexagonală necompletată poate avea în apropiere aproape 6 mine, deoarece are șase plăci învecinate. Putem stoca aceste informații și în levelData odată ce am adăugat toate minele. În esență, a levelData index cu o valoare de 10 are o mină și dacă conține valori 0 la 6, care indică numărul de mine învecinate. După ce populați minele și actualizați vecinii, dacă un element de matrice este în continuare 0, indică faptul că este o faianță goală fără mine învecinate. 

Putem folosi următoarele metode pentru scopurile noastre.

funcția addMines () var tileType = 0; var tempArray = []; var newPt = nou Phaser.Point (); pentru (var i = 0; i < levelData.length; i++)  for (var j = 0; j < levelData[0].length; j++)  tileType=levelData[i][j]; if(tileType===0) newPt=new Phaser.Point(); newPt.x=i; newPt.y=j; tempArray.push(newPt);    for (var i = 0; i < numMines; i++)  newPt=Phaser.ArrayUtils.removeRandomItem(tempArray); levelData[newPt.x][newPt.y]=10;//10 is mine updateNeighbors(newPt.x,newPt.y);   function updateNeighbors(i,j)//update neighbors around this mine var tileType=0; var tempArray=getNeighbors(i,j); var tmpPt; for (var k = 0; k < tempArray.length; k++)  tmpPt=tempArray[k]; tileType=levelData[tmpPt.x][tmpPt.y]; levelData[tmpPt.x][tmpPt.y]=tileType+1;  

Pentru fiecare mină adăugată în addMines, noi creștem valoarea de matrice stocată în toți vecinii săi. getNeighbors metoda nu va returna o placă care este în afara zonei noastre eficiente sau dacă conține o mină.

Apăsați Logic

Atunci când playerul funcționează pe o țiglă, trebuie să găsim elementul matriceal corespunzător folosind findHexTile metodă explicată mai devreme. Dacă indicele țiglă se află în aria noastră efectivă, atunci comparăm valoarea la indicele matricei pentru a găsi dacă este o mina sau o țiglă.

funcția onTap () var tile = findHexTile (); dacă checkforBoundary (tile.x, tile.y)) if (checkForOccuppancy (tile.x, tile.y)) if (nivelData [tile.x] [tile.y] == 10) // consolă .log ( 'Boom'); var hexTilă = hexGrid.getByName ("tile" + tile.x + "_" + tile.y); dacă (! hexTile.revealed) hexTile.reveal (); // over game altceva var hexTile = hexGrid.getByName ("tile" + tile.x + "_" + tile.y); dacă (! hexTile.revealed) if (levelData [tile.x] [tile.y] === 0) //console.log('recursive reveal '); recursiveReveal (tile.x, tile.y);  altceva //console.log('reveal '); hexTile.reveal (); revealedTiles ++;  infoTxt.text = 'găsit' + revealedTiles + 'of' + blankTiles; 

Urmărim numărul total de plăci goale folosind variabila blankTiles și numărul de plăci descoperite utilizând revealedTiles. Odată ce sunt egali, am câștigat jocul. 

Când atingem o placă cu o valoare de matrice 0, trebuie să dezvăluim recursiv regiunea cu toate plăcile goale conectate. Aceasta se face prin funcție recursiveReveal, care primește indicii de țiglă al plăcii țipate.

funcția recursiveReveal (i, j) var newPt = nou Phaser.Point (i, j); var hexTile; Var tempArray = [newPt]; Var vecinii; în timp ce (tempArray.length) newPt = tempArray [0]; var vecinii = getNeighbors (newPt.x, newPt.y); în timp ce (vecin.length) newPt = neighbors.shift (); hexTile = hexGrid.getByName ( "țiglă" + newPt.x + "_" + newPt.y); dacă (! hexTile.revealed) hexTile.reveal (); revealedTiles ++; dacă (nivelData [newPt.x] [newPt.y] === 0) tempArray.push (newPt);  newPt = tempArray.shift (); // se părea un punct, fără ca un vecin să scape uneori de iterație fără a fi dezvăluit, să îl captureze aici hexTile = hexGrid.getByName ("tile" + newPt.x + "_" + newPt.y ); dacă (! hexTile.revealed) hexTile.reveal (); revealedTiles ++; 

În această funcție, găsim vecinii fiecărui tiglă și descoperim valoarea dală, adăugând în același timp plăci vecine unei matrice. Continuăm să repetăm ​​acest lucru cu următorul element din matrice, până când matricea este goală. Recursia se oprește când întâlnim elemente de array care conțin o mină, ceea ce este asigurat de faptul că getNeighbors nu va întoarce o țiglă cu o mină.

Marcarea și dezvăluirea dalelor

Probabil ați observat că folosesc hexTile.reveal (), care este posibil prin crearea unui HexTile prototip care păstrează majoritatea atributelor legate de țigla noastră hexagonală. Eu folosesc dezvălui pentru a afișa textul cu valori de țiglă și a seta culoarea plăcii. În mod similar, toggleMark funcția este utilizată pentru a marca țigla ca pe o mină când atingem și menținem. HexTile are, de asemenea, dezvăluit atribut care urmărește dacă este accesat sau dezvăluit sau nu.

HexTile.prototype.reveal = funcția () this.tileTag.visible = true; this.revealed = true; dacă (this.type == 10) this.tint = '0xcc0000';  altfel this.tint = '0x00cc00';  HexTile.prototype.toggleMark = funcția () if (this.marked) this.marked = false; this.tint = '0xffffff';  altceva this.marked = true; this.tint = '0x0000cc'; 

Verificați minesweeperul hexagonal cu orientare orizontală de mai jos. Atingeți pentru a dezvălui dale și mențineți apăsat pentru a marca minele. Nu există nici un joc de acum, dar dacă dezvăluiți o valoare 10, atunci este hasta la vista copil!

Modificări pentru versiunea verticală

Deoarece folosesc aceeași imagine a plăcilor hexagonale pentru ambele orientări, rotesc Sprite pentru alinierea verticală. Codul de mai jos din HexTile prototip face acest lucru.

dacă (esteVertical) this.rotation = Math.PI / 2; 

Logica minelorweeper rămâne aceeași pentru grila hexagonală aliniată vertical cu diferența pentru findHextile și getNeighbors logica care acum trebuie să găzduiască diferența de aliniere. Așa cum am menționat mai devreme, trebuie de asemenea să folosim transpunerea matricei de nivel cu bucla corespunzătoare de aspect.

Verificați versiunea verticală de mai jos.

Restul codului din sursă este simplu și simplu. Aș dori să încercați să adăugați reluarea lipsă, câștigul jocului și jocul peste funcționalitate.

Concluzie

Această abordare a unui joc pe bază de țiglă hexagonală care utilizează o matrice bidimensională este mai mult o abordare laică. Opțiunile mai interesante și funcționale implică modificarea sistemului de coordonate la diferite tipuri folosind ecuații. 

Cele mai importante sunt coordonatele axiale și coordonatele cubice. Va exista o serie de tutoriale care vor discuta aceste abordări. Între timp, aș recomanda citirea incredibil de amănunțită a articolului Amit pe grilajele hexagonale.