C贸mo se hace: escribimos "Buscaminas" en 4 minutos

imagen

De un traductor: esta publicaci贸n es una traducci贸n del art铆culo original de Maki Chiz, un codificador experimentado que no solo escribe excelentes programas, sino que tambi茅n demuestra las capacidades de varios idiomas a sus colegas, tanto principiantes como profesionales.

Buscaminas es un juego divertido, muchos de nosotros lo jugamos. 驴Tal vez quieres hacer Buscaminas t煤 mismo?

Skillbox recomienda: La profesi贸n en l铆nea "Profesi贸n de desarrollador web" .

Le recordamos: para todos los lectores de "Habr": un descuento de 10.000 rublos al registrarse en cualquier curso de Skillbox con el c贸digo de promoci贸n "Habr".
La singularidad del juego es que es muy simple y al mismo tiempo muy emocionante. No hay una mec谩nica de juego astuta en Buscaminas, solo tienes que hacer clic en los cuadrados, con la esperanza de que no haya minas debajo de ellos.

Sugiero tratar de escribir "Buscaminas" en Procesamiento. Esta es una gran herramienta que le permite crear aplicaciones gr谩ficas en Java. Enlace a esto aqu铆 .

Antes de comenzar, dir茅 que este tutorial est谩 dirigido a aquellos que ya conocen Java. La experiencia con el procesamiento es opcional.

Entonces aqu铆 vamos. El primer paso es determinar el estado del juego. Decid铆 implementarlo as铆.

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 

Aqu铆 todo parece tener sentido, excepto esta secci贸n: int [] [] mines . 驴Por qu茅 la cuadr铆cula de la mina es un n煤mero entero y no un booleano? El hecho es que esto hace que sea f谩cil calcular cu谩ntas minas hay cerca de una determinada posici贸n.

 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 cu谩ntas minas se encuentran cerca de un sitio espec铆fico. Despu茅s de eliminar las excepciones, obtenemos algo similar a esto:

 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; } 

La tarea principal del juego en s铆 es revelar los cuadrados que comienzan en el punto 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, tenemos el siguiente algoritmo:

  • Si la posici贸n est谩 fuera del campo, finalice;
  • Si se revela la posici贸n, finalice;
  • Abrimos la posici贸n actual;
  • Si tenemos una bomba cerca de la posici贸n actual, finalice;
  • Si llegamos a este punto durante la ejecuci贸n de la funci贸n, se encontr贸 la posici贸n actual dentro del campo de juego y no hay bombas al lado, abre cuadrados adyacentes.

B谩sicamente, el resto del juego es el mismo. El c贸digo completo se puede encontrar haciendo clic en este enlace .

Si quieres saber sobre visualizaci贸n, sigue leyendo.

Visualizaci贸n

Aqu铆 todo deber铆a quedar claro, pero explicar茅 las partes dif铆ciles.

Entonces, tenemos una variable cellSize, que determina el n煤mero de p铆xeles en cada cuadrado.

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

Por lo tanto, creamos un campo con lados gridW x gridH, donde los tama帽os de cada cuadrado ser谩n iguales al valor de cellSize.

Luego devolvemos las variables a su 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 un 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; } } } 

Y luego active la respuesta a los clics del 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); } } } 

Y la funci贸n de visualizaci贸n, la llamamos una vez para cada cuadro.

 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); } } } } 

Y eso es todo, aqu铆 est谩 nuestro Buscaminas.

El juego parece simple, pero en general es completamente funcional. Y recuerda: 隆Buscaminas es adictivo!

Skillbox recomienda:

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


All Articles