Recommended Improved Match Search Algorithm for Bejeweled?

I am trying to define a reasonable method of finding matches 3, 4 or 5 for each row and column. The player views the areas (rows or columns) on the playing field, where the same “gem” will be, after replacing two adjacent parts (one swap at each step), repeat for 3-5 consecutive points.

Here is an example move script to create matches:

  • Advice before moving a player (bold exchange required):

    ACBBC

    DDBAD

    DAACC

    AD BBA

    Dcdaa

  • Tip after moving the player (bold result matches):

    ACBBC

    D DBAD

    D AACC

    D ABBA

    D CDAA

4- "D". , 1.) , , , 2.) , . , , .

, , / . , , , "" , . , - . , , , .

, :

  • . ( , ). , ; , ( ); , ( ); , . .

  • . ( , ). , ; , ( ); , ( ); , . .

, . Gem ( ), , , , .

bool Board::findMatches(bool scoringMove) // false if board is being setup before game
{
    bool matchesFound = false;

    // loops through entire board, where "size" is the width, not the number of spots
    for (int i = 0; i < size.getSize()*size.getSize(); i++)
    {
        // loops for each type of Gem, six total (_not identical to given example_)
        for (int k = 0; k < gems.getNumGems(); k++)
        {
            Gem traverseGems(k); // next Gem (in sequence)
            char nextGem = traverseGems.getGem(); // next Gem set to a char

            // ROWS check
            // default match search for 3-match
            if ((i < (size.getSize()*size.getSize())-4)
            && (board[i]->getGem() == nextGem)
            && (board[i+1]->getGem() == nextGem)
            && (board[i+2]->getGem() == nextGem))
            {
                // if the player is making a move
                if (!scoringMove)
                    return true;

                matchesFound = true;

                // just adds points to score; irrelevant to algorithm
                scoreMatches(3, 'R', i, 3);

                // no 4-match, but a 3-match
                if (board[i+3]->getGem() != nextGem)
                    scoreMatches(3, 'R', i, 3);
                else
                    scoreMatches(4, 'R', i, 4);

                // 5-match found
                if (board[i+3]->getGem() == nextGem && board[i+4]->getGem() == nextGem)
                    scoreMatches(5, 'R', i, 5);
            }

            // COLUMNS check (comments for rows check apply here as well)

            if ((i <= (size.getSize()-1))
            && (board[i]->getGem() == nextGem)
            && (board[i+size.getSize()]->getGem() == nextGem)
            && (board[i+(size.getSize()*2)]->getGem() == nextGem))
            {
                if (!scoringMove)
                    return true;

                matchesFound = true;

                scoreMatches(3, 'C', i, 3);

                if (board[i+(size*3)]->getGem() != nextGem)
                    scoreMatches(3, 'C', i, 3);
                else
                    scoreMatches(4, 'C', i, 4);
                if (board[i+(size*3)]->getGem() == nextGem && board[i+(size*4)]->getGem() == nextGem)
                    scoreMatches(5, 'C', i, 5);
            }
        }
    }

    return matchesFound;
}

Board.h

#ifndef BOARD_H
#define BOARD_H

#include "Size.h"
#include "Score.h"
#include "Move.h"
#include "Gem.h"

#include <iostream>
#include <iomanip>
#include <ctime>

class Board
{
private:
    Size size;
    Score score;
    Gem **board;
    bool moreSwaps;

    void swapGems(Move);
    void swapGems(int, int);
    void setNewRandGem(int);
    void findMoreSwaps();
    void scoreMatches(int, char, int, int);
    bool findMatches(bool);

public:
    Board();
    Board(Size, Score&);
    ~Board();
    void displayBoard() const;
    bool isMatch(Move);
    bool moreMovesFound() const;
};

#endif

Board::Board(Size size, Score &score)
{
    srand((unsigned int)time(NULL)); // I can always move this to main()

    this->size = size;
    this->score = score;

    board = new Gem *[size.getSize()*size.getSize()];

    for (int i = 0; i < size.getSize()*size.getSize(); i++)
        board[i] = new Gem;

    //This is the "pre-game" block.
    //As long as the program finds a new match after performing its
    //own swaps, it'll randomize the entire board and start over again.
    //This is incredibly unefficient, but I will try to fix it later.
    do
    {
        for (int i = 0; i < size.getSize()*size.getSize(); i++)
            setNewRandGem(i);

    } while (findMatches(false));
}
+5
1

, , , , 5x5 , 3 .

, , . , , . , . , , . , , , , .

, , .

, , , , . , . , , 3 .

:

function is_there_a_valid_move(board)
// returns true if there is a valid bejewelled move

   // test all horizontal swaps
   for (x = 0; x++; x< board-width - 1):
      for (y = 0; y++; y < board-height):
         make a copy of the board: board2
         swap board2[x,y] and board2[x+1,y]
         check_matches(board2, 3)
         if match found: return true

   // test all vertical swaps
   for (x = 0; x++; x< board-width):
      for (y = 0; y++; y < board-height - 1):
         make a copy of the board: board2
         swap board2[x,y] and board2[x,y+1]
         check_matches(board2, 3)
         if match found: return true

   return false

function check_matches(board, num_matches)
// returns true if there are num_matches or more of the same symbol in a row or column

   // check rows
   for (y = 0; y++; y < board-height):
      consecutive_symbols = 0
      for (x = 0; x++; x< board-width - 1):
         if board[x,y] == board[x+1,y]: consecutive_symbols++
         else: consecutive_symbols = 0
         if consecutive_symbols >=num_matches: return true

   // check columns
   for (x = 0; x++; x< board-width):
      consecutive_symbols = 0
      for (y = 0; y++; y < board-height - 1):
         if board[x,y] == board[x,y+1]: consecutive_symbols++
         else: consecutive_symbols = 0
         if consecutive_symbols >=num_matches: return true     

   return false

, , , 5x5 .

+2

All Articles