# Processing match 3

**URL:** <https://discourse.processing.org/t/processing-match-3/21507>\
**Category:** Coding Questions\
**Created:** [June 2, 2020, 4:11pm UTC](https://discourse.processing.org/t/processing-match-3/21507 "2020-06-02T16:11:04Z")\
**Posts on this page:** 17\
**Page:** 1

<div class="post-metadata">

**Author:** ![ctrembla](https://avatars.discourse-cdn.com/v4/letter/c/aeb1de/32.png) [@ctrembla](https://discourse.processing.org/u/ctrembla)\
**Post date:** [June 2, 2020, 4:11pm UTC](https://discourse.processing.org/t/processing-match-3/21507/1 "2020-06-02T16:11:04Z")

</div>

I’m making a match 3 game or at least I think it still called match 3. Anyways you click on a block and all the blocks touching that one of the same type vanish too. My problem is diagonal blocks are being chosen instead of the ones to the right, left, up & down.  
in this pic here you can see it chose a box to the upper left which it shouldn’t be able to do.  
 ![screen](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/b/b02d87995eaeb78fd9104e03e7accc4d775e6d42.png)

main

```auto
int s = 50;

ArrayList<Block> block = new ArrayList<Block>();
ArrayList<Spawner> spawn = new ArrayList<Spawner>();
int minH = 50;
int w = 5;
int h = 5;
int blockTimer = 0;
int chainN = 0;
boolean chose = false;
void setup(){
  size(600,600);
  reset();
}

void reset(){
  for (int i = 0; i < w; i++){
    spawn.add(new Spawner(25 + (s * i), minH + ((h-1) * s)));
  }
}

void draw(){
  background(0);
  textSize(20);
  text("B: " + blockTimer,5,20);
  text("ChainN: " + chainN,50,20);
  if (blockTimer >= 0 && chose == true){
    blockTimer -= 1;
  }
  /*if (blockTimer < 0 && chainN >= 1){
    if (chainN >= 3){
      for (int i = 0; i < block.size(); i++){
        Block b = block.get(i);
        if (b.chain == true){
          b.destroy = true;
        }
        b.coll = false;
        chainN = 0;
        chose = false;
        blockTimer = 0;
      }
    }
    if (chainN < 3){
      for (int i = 0; i < block.size(); i++){
        Block b = block.get(i);
        b.chain = false;
        b.click = false;
        chainN = 0;
        chose = false;
        blockTimer = 0;
      }
    }
  }*/
  for (Spawner s: spawn){
    s.show();
    s.create();
  }
  for (Block b : block){
    b.move();
    b.show();
    b.checked();
  }
  
  for (int i = block.size()-1; i >= 0; i--){
    Block b = block.get(i);
    if (b.destroy == true){
      block.remove(i);
    }
  }
}

void keyPressed(){
  if (key == 'r'){
    for (Block b: block){
      b.destroy = true;
    }
    for (Spawner s: spawn){
      s.coll = false;
    }
  }// r
  if (key == ' '){
    if (blockTimer < 0 && chainN >= 1){
      if (chainN >= 3){
        for (int i = 0; i < block.size(); i++){
          Block b = block.get(i);
          if (b.chain == true){
            b.destroy = true;
          }
          b.coll = false;
          chainN = 0;
          chose = false;
          blockTimer = 0;
        }
      }
      if (chainN < 3){
        for (int i = 0; i < block.size(); i++){
          Block b = block.get(i);
          b.chain = false;
          b.click = false;
          chainN = 0;
          chose = false;
          blockTimer = 0;
        }
      }
    }
  }
}

void mousePressed(){
  for (int i = 0; i < block.size(); i++){
    Block b = block.get(i);
    if (b.check == true){
      b.click = true;
      b.chain = true;
      chainN = 1;
    }
  }
}

```

spawner

```auto
class Spawner{
  PVector pos;
  int timer = 0;
  boolean coll = false;
  
  Spawner(int x, int y){
    pos = new PVector(x,y);
  }
  
  void show(){
    if (coll){fill(0);}
    if (coll == false){fill(125,125,125);}
    rect(pos.x,pos.y,s,s);
  }
  
  void create(){
    for (int i = 0; i < block.size(); i++){
      Block b = block.get(i);
      if (b.pos.y == pos.y && b.pos.x == pos.x){
        coll = true;
        break;
      } else{
        coll = false;
      }
    }
    if (timer >= 0){timer -= 1;}
    if (timer < 0 && coll == false){
      float r = random(2);
      r = round(r);
      block.add(new Block(pos,int(r)));
      timer = 64;
    }// timer
  }// create
}

```

block

```auto
class Block{
  PVector pos;
  int moveSpd = 0;
  boolean coll = false;
  int type = 0;
  boolean check = false;
  boolean click = false;
  boolean chain = false;
  boolean destroy = false;
  
  Block(PVector p, int type){
    pos = p.copy();
    this.type = type;
  }
  
  void checked(){
    if (chainN < 1){
      if (mouseX >= pos.x && mouseX <= pos.x + s && 
          mouseY >= pos.y && mouseY <= pos.y + s){
        check = true;
      } else {
        check = false;
      }
    } else {
      check = false;
    }
    if (click == true){
      for (int i = 0; i < block.size(); i++){
        Block b = block.get(i);
        if (b.type == type){
          if (b.pos.y == pos.y && b.pos.x == pos.x + s && b.chain == false ||
              b.pos.y == pos.y - s && b.pos.x == pos.x && b.chain == false ||
              b.pos.y == pos.y + s && b.pos.x == pos.x && b.chain == false ||
              b.pos.y == pos.y + s && b.pos.x == pos.x && b.chain == false){
            chain = true;
            b.chain = true;
            b.click = true;
            click = false;
            chainN += 1;
            blockTimer = 32;
            chose = true;
          }
        }
      }
    }
  }
  
  void show(){
    if (type == 0){fill(255,0,0);}// red
    if (type == 1){fill(0,255,0);}// green
    if (type == 2){fill(0,0,255);}// blue
    if (type == 3){fill(255,255,0);}// yellow
    if (type == 4){fill(255,0,255);}// purple
    if (type == 5){fill(0,255,255);}// cyan
    if (type == 6){fill(255, 165, 0);}// orange
    if (check == true){fill(255,255,255);}
    rect(pos.x,pos.y,s,s);
    if (chain == true){
      fill(0);
      text("C",pos.x + 5, pos.y + (s-5));
    }
  }
  
  void move(){
    if (pos.y == minH){
      coll = true;
    } else {
      coll = false;
    }
    if (coll == false){
      for (int i = 0; i < block.size(); i++){
        Block b = block.get(i);
        if (b.pos.y == pos.y - s && b.pos.x == pos.x){
          coll = true;
          break;
        }
        else {
          coll = false;
        }
      }// block size
    }
    if (coll == true){moveSpd = 0;}
    if (coll == false){moveSpd = -1;}
    pos.y += moveSpd;
  }// move
}

```

---

<div class="post-metadata">

**Author:** ![Chrisir](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/chrisir/32/45_2.png) [@Chrisir](https://discourse.processing.org/u/Chrisir)\
**Post date:** [June 2, 2020, 4:53pm UTC](https://discourse.processing.org/t/processing-match-3/21507/2 "2020-06-02T16:53:47Z")

</div>

Apart from your question

This is a nice post, well formatted and well put. Also the code is nice, with the arraylist and the idea of for loop backward to remove destroyed cells. Well done!

I just read your code a bit, you got …x+s but no … x-s.

Not solving the problem but a remark.

Is it so that only 4 blocks are destroyed or is the process like a chain going over the entire field?

---

<div class="post-metadata">

**Author:** ![Chrisir](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/chrisir/32/45_2.png) [@Chrisir](https://discourse.processing.org/u/Chrisir)\
**Post date:** [June 2, 2020, 5:00pm UTC](https://discourse.processing.org/t/processing-match-3/21507/3 "2020-06-02T17:00:06Z")

</div>

I mean when it’s a chain:

I observed that the red cell has in fact a red neighbor. So that check might be working correctly.

Maybe the issue is rather that you don’t control whether we have a connection to the initial clicked screen.

Intuitively you would start from the initial cell, check the 4 surrounding neighbors and then check from these 4 again and then etc. - this sounds recursively but can be done also with for loops.

---

<div class="post-metadata">

**Author:** ![ctrembla](https://avatars.discourse-cdn.com/v4/letter/c/aeb1de/32.png) [@ctrembla](https://discourse.processing.org/u/ctrembla)\
**Post date:** [June 2, 2020, 5:05pm UTC](https://discourse.processing.org/t/processing-match-3/21507/4 "2020-06-02T17:05:26Z")

</div>

It should start with block 1 that you clicked on move to block 2 if any around block 1 is same type then move on. Until the block can’t find a match in its neighbors. I’ll post a pic to show what I mean. ![screen](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/3/374bd21462a06221d9d48fa36a5541c6151c3014.png)  
in the pic number 1 is where the click happened then it moves to 2 then 3. At 3 it should choose up or left then stop because none are left, right, up & down.

---

<div class="post-metadata">

**Author:** ![Chrisir](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/chrisir/32/45_2.png) [@Chrisir](https://discourse.processing.org/u/Chrisir)\
**Post date:** [June 2, 2020, 5:10pm UTC](https://discourse.processing.org/t/processing-match-3/21507/5 "2020-06-02T17:10:11Z")

</div>

> [@ctrembla](#):
>
> At 3 it should choose up or left

Ah, so it hits only one of the two randomly?

---

<div class="post-metadata">

**Author:** ![ctrembla](https://avatars.discourse-cdn.com/v4/letter/c/aeb1de/32.png) [@ctrembla](https://discourse.processing.org/u/ctrembla)\
**Post date:** [June 2, 2020, 5:13pm UTC](https://discourse.processing.org/t/processing-match-3/21507/6 "2020-06-02T17:13:53Z")

</div>

looking at the code. I think it checks right, up, then down. I should fix that, but it should choose one of them not both. I think it might do both because I didn’t break it. As can see on this one it went right then got stopped because no others.

 ![screen](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/4/45a47c537afe4ac0b57f4df8c506ab6ee55fc424.png)

---

<div class="post-metadata">

**Author:** ![Chrisir](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/chrisir/32/45_2.png) [@Chrisir](https://discourse.processing.org/u/Chrisir)\
**Post date:** [June 2, 2020, 5:33pm UTC](https://discourse.processing.org/t/processing-match-3/21507/7 "2020-06-02T17:33:21Z")

</div>

Yeah, okay, I see

Chrisir

---

<div class="post-metadata">

**Author:** ![Chrisir](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/chrisir/32/45_2.png) [@Chrisir](https://discourse.processing.org/u/Chrisir)\
**Post date:** [June 2, 2020, 5:34pm UTC](https://discourse.processing.org/t/processing-match-3/21507/8 "2020-06-02T17:34:50Z")

</div>

But no use to go over the entire grid

Instead start a clicked cell and jump on and on…?

---

<div class="post-metadata">

**Author:** ![ctrembla](https://avatars.discourse-cdn.com/v4/letter/c/aeb1de/32.png) [@ctrembla](https://discourse.processing.org/u/ctrembla)\
**Post date:** [June 2, 2020, 5:37pm UTC](https://discourse.processing.org/t/processing-match-3/21507/9 "2020-06-02T17:37:23Z")

</div>

I don’t wanna click each cell just wanna click one then it deletes the others. I’m thinking of switching to boolean right, left, up down to make it more random, but still id get why the adjacent one got chose.

---

<div class="post-metadata">

**Author:** ![Chrisir](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/chrisir/32/45_2.png) [@Chrisir](https://discourse.processing.org/u/Chrisir)\
**Post date:** [June 2, 2020, 5:49pm UTC](https://discourse.processing.org/t/processing-match-3/21507/10 "2020-06-02T17:49:52Z")

</div>

I mean this:

But no use to go over the entire grid

Instead start a mouse clicked cell and then the program jumps on and on…?

---

<div class="post-metadata">

**Author:** ![ctrembla](https://avatars.discourse-cdn.com/v4/letter/c/aeb1de/32.png) [@ctrembla](https://discourse.processing.org/u/ctrembla)\
**Post date:** [June 2, 2020, 5:51pm UTC](https://discourse.processing.org/t/processing-match-3/21507/11 "2020-06-02T17:51:48Z")

</div>

but don’t i still need to get the number of the block?

---

<div class="post-metadata">

**Author:** ![Chrisir](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/chrisir/32/45_2.png) [@Chrisir](https://discourse.processing.org/u/Chrisir)\
**Post date:** [June 2, 2020, 6:10pm UTC](https://discourse.processing.org/t/processing-match-3/21507/12 "2020-06-02T18:10:00Z")

</div>

That’s true, I forgot about this…

---

<div class="post-metadata">

**Author:** ![Chrisir](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/chrisir/32/45_2.png) [@Chrisir](https://discourse.processing.org/u/Chrisir)\
**Post date:** [June 3, 2020, 9:03am UTC](https://discourse.processing.org/t/processing-match-3/21507/13 "2020-06-03T09:03:36Z")

</div>

But I am not happy with the architecture

(I read this code only briefly, so apologies for any mistakes)

For example you call checked from draw() but is this necessary every time draw() runs? Wouldn’t it be enough to call it in mousePressed() when a change happened?

Also, you for-loop over the grid **inside the class** of one block/cell. In my opinion that is not clean code. Because one cell should not access the grid it belongs to (outside the class). Instead it should only take care of itself.

The grid stuff should be in functions outside the class (you could make a class grid though, but it’s not necessary).

I am not entirely sure about this; we should check. There are examples when a cell checks the grid but they are very specific.

Regards

Chrisir

---

<div class="post-metadata">

**Author:** ![Chrisir](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/chrisir/32/45_2.png) [@Chrisir](https://discourse.processing.org/u/Chrisir)\
**Post date:** [June 3, 2020, 10:58am UTC](https://discourse.processing.org/t/processing-match-3/21507/14 "2020-06-03T10:58:45Z")

</div>

> [@ctrembla](#):
>
> but don’t i still need to get the number of the block?

Yes, that’s in mousePressed(); but I mean in the class Block  
in checked()

**class Spawner**

What is the purpose of class Spawner please?

Mainly the animation at start of the Sketch?

---

<div class="post-metadata">

**Author:** ![ctrembla](https://avatars.discourse-cdn.com/v4/letter/c/aeb1de/32.png) [@ctrembla](https://discourse.processing.org/u/ctrembla)\
**Post date:** [June 3, 2020, 3:28pm UTC](https://discourse.processing.org/t/processing-match-3/21507/15 "2020-06-03T15:28:13Z")

</div>

yes spawner spawns the blocks when bock.size don’t equal the amount i want. Checked checks to see if mouse is colliding with the block, so no it can’t be in mousePressed I need to know which block i’m over.

---

<div class="post-metadata">

**Author:** ![uheinema](https://avatars.discourse-cdn.com/v4/letter/u/e99b99/32.png) [@uheinema](https://discourse.processing.org/u/uheinema)\
**Post date:** [June 4, 2020, 12:46pm UTC](https://discourse.processing.org/t/processing-match-3/21507/16 "2020-06-04T12:46:18Z")

</div>

I agree 100% with crisir about the architecture.  
Actually gave it a try, and made it somewhat scaleble…convoluted code.

With the obvious

```auto
      if (b.pos.y == pos.y && b.pos.x == pos.x + s && b.chain == false ||
              b.pos.y == pos.y - s && b.pos.x == pos.x && b.chain == false ||
              b.pos.y == pos.y + s && b.pos.x == pos.x && b.chain == false ||
              b.pos.y == pos.y && b.pos.x == pos.x - s && b.chain == false){
   

```

and displaying chainN it is

 ![Screenshot_20200604_143802_com.calsignlabs.apde.sketchpreview](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/1/1b2b1de5391f261dc66a157ae8f81682ea0ae907.jpeg)

---

<div class="post-metadata">

**Author:** ![uheinema](https://avatars.discourse-cdn.com/v4/letter/u/e99b99/32.png) [@uheinema](https://discourse.processing.org/u/uheinema)\
**Post date:** [June 5, 2020, 12:13am UTC](https://discourse.processing.org/t/processing-match-3/21507/17 "2020-06-05T00:13:10Z")

</div>

## Couldn’t help playing around with it, results [on Github](https://github.com/uheinema/BoxDrop-Example.git)

 ![Screenshot_20200605_011631_com.calsignlabs.apde.sketchpreview](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/6/6fe4d781c9ef467948c16a947526dcecde5747c6.jpeg)
