Como é feito: escrevemos “Campo Minado” em 4 minutos

imagem

De um tradutor: este post é uma tradução do artigo original de Maki Chiz, um codificador experiente que não apenas escreve ótimos programas, mas também demonstra os recursos de vários idiomas para seus colegas, iniciantes e profissionais.

Campo Minado é um jogo divertido, muitos de nós jogamos. Talvez você queira fazer o caça-minas você mesmo?

A Skillbox recomenda: A profissão on - line "Profissão de desenvolvedor Web" .

Lembramos que: para todos os leitores de "Habr" - um desconto de 10.000 rublos ao se inscrever em qualquer curso Skillbox usando o código promocional "Habr".
A singularidade do jogo é que é muito simples e ao mesmo tempo muito emocionante. Não há mecânica de jogo astuta no Campo Minado, basta clicar nos quadrados, esperando que não haja minas debaixo deles.

Sugiro tentar escrever "Campo Minado" em Processamento. Essa é uma ótima ferramenta que permite criar aplicativos gráficos em Java. Link para aqui .

Antes de começar, direi que este tutorial é destinado a quem já conhece Java. A experiência com o processamento é opcional.

Então aqui vamos nós. O primeiro passo é determinar o estado do jogo. Eu decidi implementá-lo assim.

int gridW; // grid width int gridH; // grid height int numMines; // number of mines on the board int[][] mines; // entry is 1 for having a mine and 0 for not boolean[][] flags; // entry is true if you have flagged that spot boolean[][] revealed; // entry is true if that spot is revealed 

Tudo parece fazer sentido aqui, exceto nesta seção: int [] [] minas . Por que a grade da mina é um número inteiro e não um booleano? O fato é que isso facilita o cálculo de quantas minas estão próximas a uma determinada posição.

 int calcNear(int x, int y) { int i=0; for (int offsetX=-1; offsetX<=1; offsetX++) { for (int offsetY=-1; offsetY<=1; offsetY++) { i+=mines[offsetX+x][offsetY+y]; } } return i; } 

Este código determina quantas minas estão localizadas perto de um site específico. Depois de remover as exceções, obtemos algo semelhante a este:

 boolean outBounds(int x,int y){ return x<0||y<0||x>=gridW||y>=gridH; } int calcNear(int x, int y) { if(outBounds(x,y))return 0; int i=0; for (int offsetX=-1; offsetX<=1; offsetX++) { for (int offsetY=-1; offsetY<=1; offsetY++) { if (outBounds(offsetX+x, offsetY+y))continue; i+=mines[offsetX+x][offsetY+y]; } } return i; } 

A principal tarefa do jogo em si é revelar os quadrados começando no ponto x, y.

 void reveal(int x, int y){ if(outBounds(x,y))return; if(revealed[x][y])return; revealed[x][y]=true; if(calcNear(x,y)!=0)return; reveal(x-1,y-1); reveal(x-1,y+1); reveal(x+1,y-1); reveal(x+1,y+1); reveal(x-1,y); reveal(x+1,y); reveal(x,y-1); reveal(x,y+1); } 

Como resultado, temos o seguinte algoritmo:

  • Se a posição estiver fora do campo, termine;
  • Se a posição for divulgada, finalize;
  • Abrimos a posição atual;
  • Se tivermos uma bomba perto da posição atual, termine;
  • Se chegarmos a esse ponto durante a execução da função, a posição atual dentro do campo de jogo foi encontrada e não há bombas ao lado, abrindo quadrados adjacentes.

Basicamente, o resto do jogo é o mesmo. O código completo pode ser encontrado clicando neste link .

Se você quiser saber sobre visualização, continue lendo.

Visualização

Tudo deve ficar claro aqui, mas vou explicar as partes difíceis.

Portanto, temos uma variável cellSize, que determina o número de pixels em cada quadrado.

 void settings(){ size(gridW*cellSize, gridH*cellSize); } 

Assim, criamos um campo com os lados gridW x gridH, onde os tamanhos de cada quadrado serão iguais ao valor de cellSize.

Em seguida, retornamos as variáveis ​​ao seu estado original.

 void setup(){ //initialize and clear the arrays mines=new int[gridW][gridH]; flags=new boolean[gridW][gridH]; revealed=new boolean[gridW][gridH]; for(int x=0;x<gridW;x++){ for(int y=0;y<gridH;y++){ mines[x][y]=0; flags[x][y]=false; revealed[x][y]=false; } } } 

Para inicializar um campo:
 //Place numMines mines on the grid void placeMines(){ int i=0; while(i<numMines){//We don't want mines to overlap, so while loop int x=int(random(gridW)); int y=int(random(gridH)); if(mines[x][y]==1)continue; mines[x][y]=1; i++; } } //Clear the mines void clearMines() { for (int x=0; x<gridW; x++) { for (int y=0; y<gridH; y++) { mines[x][y]=0; } } } 

E, em seguida, ative a resposta aos cliques do mouse.

 //We don't want the first click to be a mine boolean firstClick=true; void mousePressed() { int x=int(mouseX/cellSize); int y=int(mouseY/cellSize); //Right-click is flagging or de-flagging a square if (mouseButton==RIGHT) { flags[x][y]=!flags[x][y]; return; } else {//left-click //Avoid making the first click a mine if (firstClick) { firstClick=false; do { clearMines(); placeMines(); } while (calcNear(x,y)!=0); } //Check for game loss if (mines[x][y]!=0) { println("Dang!"); exit(); } else {//If game not lost, reveal starting from that square reveal(x, y); } } } 

E a função de exibição, chamamos uma vez para cada quadro.

 void draw() { background(0); //For each cell for (int x=0; x<gridW; x++) { for (int y=0; y<gridH; y++) { //The colors alternate for texture color col1=color(2*255/5); color col2=color(3*255/5); color txtColor=color(0); int near=calcNear(x, y); if (flags[x][y]) { col1=color(255, 0, 0); col2=color(4*255/5, 255/5, 255/5); } else if (revealed[x][y]) { col1=color(255/2); col2=color(255/2); } if (near==1)txtColor=color(255*1/4, 255*1/4, 255*3/4); if (near==2)txtColor=color(255*1/4, 255*3/4, 155*1/4); if (near==3)txtColor=color(255, 0, 0); if (near==4)txtColor=color(0, 0, 255); if (near==5)txtColor=color(255, 0, 0); boolean alternate=(x+y)%2==0; if (alternate) { fill(col2); stroke(col2); } else { fill(col1); stroke(col1); } //if(mines[x][y]>0){ //fill(0,255,0); //stroke(0,255,0); //} rect(x*cellSize, y*cellSize, cellSize, cellSize); //If there is a mine near this spot and it is revealed if (near>0&&revealed[x][y]) { fill(txtColor); noStroke(); textAlign(LEFT, TOP); textSize(cellSize); text(""+near, x*cellSize, y*cellSize); } } } } 

E é tudo, aqui está o nosso caça-minas.

O jogo parece simples, mas no geral é totalmente funcional. E lembre-se: o Campo Minado é viciante!

A Skillbox recomenda:

Source: https://habr.com/ru/post/pt425317/


All Articles