制作记忆瓷砖游戏,如何检查两个瓷砖是否相同

时间:2012-11-27 00:41:50

标签: arrays image processing

使用2D阵列制作游戏,加载12张图像;确切地说是6对。单击一个图块时,会向其添加1,从而使其成为2,从而显示它。当显示2个图块,并且单击第三个图块时,前两个图块被隐藏。

我的问题: 如何检查两个显示的图块是否显示相同的图像? 如果他们显示相同的图像,我怎样才能确保他们熬夜并且不会被点击第3个瓷砖隐藏?

我尝试制作某种与数组相对应的计数器,但根本不起作用。也没有检查一个阵列是否与另一个阵列相等。

任何帮助将不胜感激。非常感谢你。

以下是我的参考代码:

    // Number of columns and rows in the grid
int cols;
int rows;
int counter = 0; //counts how many are shown
boolean[] tracker = new boolean[12];
PImage [][] img = new PImage[4][3]; // load images

int[][] grid;

void setup() {
  size(600, 600);
  cols = height/4; //I want 4
  rows = width/3; //I want 3
  for (int m =0; m<tracker.length;m++){
        tracker[m]=false; //To laod array as false. Will be used to track numbers given out to make sure each every image is only put out once (but in reality I have pairs)
  }
  for (int i =0; i<img.length; i++) {
    for (int j=0; j<img[i].length;j++) {
      //int k = (j * 4 + i)%6;//2D array to 1D
      int k = (int)random(0,12);
      while(tracker[k]) //While it's true, pick 0-11 corepsonding to an image
      {
        k = (int)random(0,12);
      }
      tracker[k]=true; //Make it true, therefore can't be picked again
      img[i][j] = loadImage("img" + k + ".jpeg"); //Load the images
    }
  }
  grid = new int[cols][rows]; //To make the 2D array of 30 and 30
  for (int i=0; i<cols; i++) {
    for (int j=0; j<rows; j++) {
      grid[i][j] = 1; //If mouse clicked, will by multiplied by -1 to change if black or white
    }
  }
}

void draw() {
  rects(); //Calls the function to display rectangles
}

void rects() {
  for (int i=0; i<cols; i++) {
    for (int j=0; j<rows; j++) {
      if (grid[i][j]== 1) { //if grid at i,j is 1, change white
        fill(255); //white
        rect(cols*i, rows*j, cols, rows);
      }
      if (grid[i][j]== 2) { //if grid at i,j is -1, change black
        image(img[i][j], cols*i, rows*j);
        //rect(cols*0, rows*0, cols, rows);
      }
    }
  }
}

void mouseClicked() {
  for (int i=0; i<cols; i++) {
    for (int j=0; j<rows; j++) {
      if (mouseX<(i*cols)+cols && mouseX >= i*cols && mouseY<((j)*rows+rows) && mouseY >= (j)*rows) { // find square that is clicked then change color
        counter++;
        if (counter == 3) {
          for (int k=0; k<cols; k++) {
            for (int l=0; l<rows; l++) {
              grid[k][l]=1; //Making it 1 again, thus white
            }
          }
          counter =1;
        }
        grid[i][j] +=1; //By adding one, we make it show the imahe
      }
    }
  }
}

1 个答案:

答案 0 :(得分:2)

您不想尝试比较PImage,因为它很慢而且并不总是准确。

您不希望存储超出需要的图像,因为这会浪费内存。只存储独特的图像。

您想要将模型与视图分开。您无需操纵图像。您只需知道它们应显示在何处以及搜索匹配的过程。存储图像的方式应该与逻辑分开。

我建议您创建6个独特图像的“PImage”数组。然后,创建一个“int”数组,其大小是唯一图像数量的两倍(因为您希望有对)。最后,创建一个“boolean”数组,其长度与“int”数组相同。

因此,在设置时,您将使用6个图像填充图像数组(“PImage”数组),使用图像数组的键填充标签数组(“int”数组)(重复0到5,即{ 0,1,2,3,4,5,0,1,2,3,4,5),对标签数组进行随机播放,并使用“false”值填充显示数组(“boolean”数组)。 / p>

当用户单击图块时,您将确定图块编号(0到11),将该图块编号的显示设置为true,并将图块编号存储为首次单击。当用户单击另一个图块时,首先检查它是否与第一次单击的图块不同,然后将显示设置为true,并将图块编号存储为第二次单击。现在已经点击了两个,检查每个瓦片编号的标签数组,看看它们是否相等。如果是,则匹配,如果没有,则没有匹配,第一次和第二次单击被重置,并且这些图块编号的显示再次设置为假。

在我下面创建的示例中,有两个pde文件,匹配和颜色。 match.pde文件包含了解标签匹配方法所需的一切。 colors.pde仅作为生成随机颜色的方法包含在内,您无需担心。重点是向您展示使用颜色的逻辑,以便您可以使用图像实现它。

match.pde

import java.util.Arrays; // used for shuffling
import java.util.Collections; // used for shuffling

int COLOR_COUNT = 6; //number of colors we will try to match

int WINDOW_X = 600;
int WINDOW_Y = 600;

//we will set these values during setup
int COLUMN_COUNT;
int ROW_COUNT;

color TILE_BACK_COLOR = color(255);
color TILE_EDGE_COLOR = color(0);

//we will set these values after we set the size of the window
int TILE_WIDTH;
int TILE_HEIGHT;

int ROUNDED_CORNER = 10;

//this is where we will store the colors
color[] COLORS = new color[COLOR_COUNT];

//the following must be Integer to allow for shuffle
//see http://stackoverflow.com/a/3981494/1736092
//this is where we will store the labels for the colors
Integer[] LABELS = new Integer[COLOR_COUNT*2]; 

//this is where we will store which tiles may be displayed
boolean[] DISPLAY = new boolean[COLOR_COUNT*2];

//this is where we will store the last 2 clicked tiles
int[] CLICKED = new int[2];

boolean MATCHED = false;
int MATCH_COUNT = 0;
int GUESS_COUNT = 0;

void setup() {
  /* calculate how many rows and columns we need based on number of tiles
   * since this is a matching game, number of tiles is twice the number of colors
   * we want a board that is as square as possible
   * take the square root of the number of tiles and round down (floor) and set that as rows
   * if rows divide evenly into the number of tiles, just divide tiles by rows to get columns
   * if not, keep subtracting a row until they divide evenly then get columns
   */
  println("Tiles: " + COLOR_COUNT*2);
  ROW_COUNT = floor(sqrt(COLOR_COUNT*2));
  println("Initial ROW_COUNT: " + ROW_COUNT);
  if((COLOR_COUNT*2) % ROW_COUNT == 0) {
    COLUMN_COUNT = (COLOR_COUNT*2) / ROW_COUNT;
    println("Keeping ROW_COUNT: " + ROW_COUNT + ", Setting COLUMN_COUNT: " + COLUMN_COUNT);
  } else {
    for(int i = ROW_COUNT - 1; i > 1; i--) {
      ROW_COUNT = i;
      if((COLOR_COUNT*2) % ROW_COUNT == 0) {
        COLUMN_COUNT = (COLOR_COUNT*2) / ROW_COUNT;
        println("Calculated ROW_COUNT: " + ROW_COUNT + ", Setting COLUMN_COUNT: " + COLUMN_COUNT);
      }
    }  
  }

  // make sure that the rows and columns are valid
  assert(COLUMN_COUNT * ROW_COUNT == COLOR_COUNT*2);

  size(WINDOW_X, WINDOW_Y);
  TILE_WIDTH = width/COLUMN_COUNT;
  TILE_HEIGHT = height/ROW_COUNT;

  populateColors(); // populate the colors
  newGrid(); // set up the initial grid

  background(0);
  drawGrid();
}

void draw() {
// //With no animations, this game is visually static
// //No need for a draw loop
}

void populateColors() {
  //for this game, we'll just generate random colors
  //however, you could change this function to set specific colors
  for(int i = 0; i < COLORS.length; i++) {
    COLORS[i] = getRandomColor();
  }  
}

//this function will create a new grid
//labels will be populated and shuffled
//clicks will be initialized to -1, which we will use to mean no click
void newGrid() {
  print("Initial LABELS[" + LABELS.length + "]:\t");

  for(int i = 0; i < LABELS.length; i++) {
    if(i < LABELS.length/2) LABELS[i] = i;
    else LABELS[i] = i-COLOR_COUNT;

    DISPLAY[i] = false;

    print(LABELS[i] + " ");
  }

  CLICKED[0] = -1;
  CLICKED[1] = -1;

  // shuffles the labels array
  Collections.shuffle(Arrays.asList(LABELS));

  print("\nShuffled LABELS[" + LABELS.length + "]:\t");
  for(int i = 0; i < LABELS.length; i++) print(LABELS[i] + " ");
  println();
}

//this just iterates through the grid and displays tiles as necessary
void drawGrid() {
  stroke(TILE_EDGE_COLOR); //set outline color
  for(int row = 0; row < ROW_COUNT; row++) {
    for(int col = 0; col < COLUMN_COUNT; col++) {
      int tile_number = col + row*(COLUMN_COUNT);
      if(DISPLAY[tile_number]) {
        fill(COLORS[LABELS[tile_number]]); //set fill color to that of tile front
      } else {
        fill(TILE_BACK_COLOR); //set fill color to that of tile back
      }
      //rect(top left x, top left y, width, height)
      rect(col*TILE_WIDTH, row*TILE_HEIGHT, TILE_WIDTH, TILE_HEIGHT, ROUNDED_CORNER);
    }
  }
}

//this is called when two tiles have been clicked
//it checks the labels of the colors of the given tiles, not the actual colors 
void checkMatch() {
  //we want to make sure that both of the clicked tiles have been properly logged
  if(CLICKED[0] != -1 || CLICKED[1] != -1) {
    println("Comparing LABELS of COLORS[" + LABELS[CLICKED[0]] + "] and COLORS[" + LABELS[CLICKED[1]] + "]");
    if(LABELS[CLICKED[0]] == LABELS[CLICKED[1]]) {
      println("Colors match! MATCHED set to true and MATCH_COUNT++");
      MATCHED = true;
      MATCH_COUNT++;
      println("MATCH_COUNT now " + MATCH_COUNT);
      if(MATCH_COUNT == COLOR_COUNT) {
        println("MATCH_COUNT now equals COLOR_COUNT, board must be complete, executing win()"); 
        win();
      }
    } else {
      println("Colors do not match");
    }
  }  
}

//this funciton is called when a win condition has been met
void win() { 
  println("You Win! You made " + GUESS_COUNT + " tile flips, best possible is " + COLOR_COUNT*2);
  if(GUESS_COUNT == COLOR_COUNT*2) println("PERFECT GAME!");
  println("Press SPACE to generate a new board."); 
}

//this function is called when the user wants to reset the board
void reset() {
  println("Resetting the board");

  COLORS = new color[COLOR_COUNT];
  LABELS = new Integer[COLOR_COUNT*2]; 
  DISPLAY = new boolean[COLOR_COUNT*2];

  CLICKED = new int[2];
  MATCHED = false;
  MATCH_COUNT = 0;
  GUESS_COUNT = 0;

  populateColors();
  newGrid();
}

void mouseClicked() {
  println("Mouse Clicked");
  int clicked_column = mouseX/TILE_WIDTH;
  int clicked_row = mouseY/TILE_HEIGHT;
  int tile_number = clicked_column + clicked_row*(COLUMN_COUNT);
  println("Clicked: " + clicked_column + "," + clicked_row + " [" + tile_number + "]");

  //we don't want to allow clicking a tile that is already being displayed
  if(!DISPLAY[tile_number]) {
    GUESS_COUNT++;
    println("Guess count incremented to " + GUESS_COUNT);

    if(CLICKED[0] != -1 && CLICKED[1] != -1) {
      if(!MATCHED) {
        println("Set DISPLAY[" + CLICKED[0] + "] and DISPLAY[" + CLICKED[1] + "] to false");
        DISPLAY[CLICKED[0]] = false;
        DISPLAY[CLICKED[1]] = false;
      } else {
        println("Set MATCHED to false");
        MATCHED = false;  
      }
      CLICKED[0] = -1;
      CLICKED[1] = -1;
    }

    if(CLICKED[0] == -1 && CLICKED[1] == -1) {
      CLICKED[0] = tile_number;
      DISPLAY[tile_number] = true;
      println("Tile " + tile_number + " set as CLICKED[0], set DISPLAY[" + tile_number + "] to true");
    } else if(CLICKED[0] != -1 && CLICKED[1] == -1) {
      CLICKED[1] = tile_number; 
      DISPLAY[tile_number] = true;
      println("Tile " + tile_number + " set as CLICKED[1], set DISPLAY[" + tile_number + "] to true");
      checkMatch();
    } else {
      println("error in mouseClicked()");
    }
  }

  drawGrid();
  if(DISPLAY[tile_number]) {
    println("Tile " + tile_number + " is already being displayed");
    for(int i = 0; i < LABELS.length; i++) {
      print("-["+i+"]-");
      if(i != tile_number && LABELS[tile_number] == LABELS[i]) {

        break;  
      }
    }
  }

}

//allow user to reset the board by pressing SPACE
void keyPressed() {
  if(key == ' ') reset();
}

colors.pde

final float PHI = (1 + sqrt(5))/2;
float rand = random(0,1);

color HSVtoRGB(float h, float s, float v) {
  float r, g, b;
  if (s == 0) {
    r = v * 255;
    g = v * 255;
    b = v * 255;
  } else {
    float var_h = h * 6;
    float var_i = floor(var_h);
    float var_1 = v * (1 - s);
    float var_2 = v * (1 - s * (var_h - var_i));
    float var_3 = v * (1 - s * (1 - (var_h - var_i)));

    float var_r, var_g, var_b;

    if (var_i == 0) {var_r = v; var_g = var_3; var_b = var_1;}
    else if (var_i == 1) {var_r = var_2; var_g = v; var_b = var_1;}
    else if (var_i == 2) {var_r = var_1; var_g = v; var_b = var_3;}
    else if (var_i == 3) {var_r = var_1; var_g = var_2; var_b = v;}
    else if (var_i == 4) {var_r = var_3; var_g = var_1; var_b = v;}
    else {var_r = v; var_g = var_1; var_b = var_2;}

    r = var_r * 255;
    g = var_g * 255;
    b = var_b * 255;
  }
  return color(r, g, b);
}

// returns a random color
color getRandomColor() {
  //0.25,0.8
  float sat = 0.65;
  float val = 0.6;
  rand += PHI - 1;
  rand %= 1;
  //this is a custom function to convert HSV to RGB
  return HSVtoRGB(rand, sat, val);
}

顺便说一句,您不必使用Java shuffle方法,特别是如果您想避免使用Java库并坚持使用Processing。一种流行的方法是Fisher-Yates Shuffle。 http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle