# Bejeweled-like match checking / Board Randomization

This topic is 3272 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

I currently have a grid of blocks, each of a different color. I'm currently having some logic issues about checking for matches when a player shifts a block. The player is allowed to swap two adjacent blocks in any of the 4 cardinal directions. Currently, I'm only allowing matches of 3 in a row. (I also have a problem getting my boards random enough.) After each swap, I need to check for matches including the blocks that have been swapped. It's turning into a complicated mess and I feel like I'm losing sight of occam's razor here. Has anyone implemented this before that can give me a few hints? Also, how do these puzzle games generally make sure their boards are not initialized with 3-4 matches already aligned? I currently have 6 colors and on my 10x10 board, there's usually 3-5 matches after initialization. I naively assign each block a random color. Thanks

##### Share on other sites
Checking for matches (three in a row) should be trivial. Scan the board piece by piece, tag pieces that makes three-in-a-row.

Once all pieces are tagged, drop the pieces down (from left-right, bottom-up), and do another full-board scan.

enum { COLUMNS = 12, ROWS = 20, LENGTH = 3, EMPTY = -1 };struct Piece{    Piece() { val = EMPTY; chained = false; }    int val;    bool chained;};Piece board[COLUMNS][ROWS];Piece* piece(int c, int r);bool analyseBoard();bool analysePieces(int c, int  r, int  dc, int  dr);void dropColumn(int c, int r, int count);void resolveBoard();void updateBoard();Piece* piece(int c, int r){    if(c < 0 || c >= COLUMNS) return NULL;    if(r < 0 || r >= ROWS) return NULL;    return &(board[c][r]);}bool analyseBoard(){    bool foundChain = false;    for(int c = 0; c < COLUMNS; c++)    {        for(int r = 0; r < ROWS; r++)        {           Piece* p = piece(c, r);           if(p->val == EMPTY) continue;           // only need to check two cardinal directions.           foundChain |= analysePieces(c, r, 0, 1);           foundChain |= analysePieces(c, r, 1, 0);        }    }    return foundChain;}// check pieces from coordinates (c, r), and along direction (dc, dr)bool analysePieces(int c, int  r, int  dc, int  dr){    int val = piece(c, r)->val;  // value to match    int count = 0; // number of pieces sharing that value    Piece* p[LENGTH]; // pointers to pieces    for(int i = 0; i = LENGTH; i ++, c += dc, r += dr)    {        p = piece(c, r);        // neighbouring piece matches that value        if(p && p->val == val)            count++;    }    // we've reached our length    if(count == LENGTH)    {        for(int i = 0; i = LENGTH; i ++)            p->chained = true;        return true;    }    return false;}void resolveBoard(){   for(int c = 0; c < COLUMNS; c++)    {        for(int r = 0; r < ROWS; )        {           Piece* p = piece(c, r);                 // piece flagged as chained           if(p->chained)           {               // drop column (c), from row(r) down by one.               dropColumn(c, r, 1);           }           // piece not chained, go to next piece above           // else we need to check it again as it's been replaced.           else           {               r++;           }        }    }}// drop column (c), from row (r), down by (count) pieces.void dropColumn(int c, int r, int count){    for(int i = r; i < ROWS; i++)    {        // piece to replace        Piece* p = piece(c, i);        // piece above        Piece* above = piece(c, i + count);        // replace piece with the one above        // if outside the board, replace with empty piece.        *p = (above != NULL)? (*above) : Piece();     }}void updateBoard(){    // while we find chains, remove the chained pieces.    while(analyseBoard())        resolveBoard();}

in case of your randomisation, just replace some of the piece that part of a chain by another value. The chances are, that will break the chain. If it doesn;t use another random value until it does.

You can analyse the board, find tagged pieces, and change some of them with another value (one that is not the same as the its neighbours), analyse again (clear the chained flag first!), ect, until you find no more chains. Not ideal, but that should reset the board pretty quickly.

EDIT : CODE NOT TESTED!

[Edited by - oliii on December 2, 2009 5:16:54 AM]

##### Share on other sites
Thanks a lot. :) I wrote similar code that worked out fine with a few tweaks to allow me to call the same function AnalyzeBoard(), but have it perform different logic depending on whether I'm sanitizing the board before the player begins or simply checking for player-created matches.

You're right though. This was rather trivial and I'm not sure why I was making it so complicated before. It happens. :)

1. 1
Rutin
39
2. 2
3. 3
4. 4
5. 5

• 12
• 17
• 12
• 14
• 9
• ### Forum Statistics

• Total Topics
633358
• Total Posts
3011507
• ### Who's Online (See full list)

There are no registered users currently online

×