gpt4 book ai didi

c++ - 推荐用于 gem 迷阵游戏的改进匹配查找算法?

转载 作者:可可西里 更新时间:2023-11-01 17:56:59 26 4
gpt4 key购买 nike

我正在尝试确定一种合理的方法来为每行和每列查找 3、4 或 5 个匹配项。玩家在游戏板上寻找相同“ gem ”所在的区域(行或列),在交换两个相邻的棋子(每轮交换一个)后,重复 3-5 个连续点。

这是一个配对 Action 的示例场景:

  • 玩家移动前的棋盘(粗体表示需要交换):

    A C B B C

    D D B A D

    D A A C C

    A D B B A

    D C D A A

  • 玩家移动后的棋盘(粗体表示匹配结果):

    A C B B C

    D D B A D

    D A A C C

    D A B B A

    D C D A A

在此示例中,在第一行之后的第一列中有 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));
}

最佳答案

重读更新后的问题后,我认为您的目标是测试对于给定的 5x5 棋盘,是否存在两个相邻符号的任何可能交换,从而产生具有 3 个或更多相同符号的棋盘行或列中的符号。

如果之前的尝试产生越界错误,则意味着实现中存在错误,而不是算法中的错误。因此,使用不同的算法对解决该问题无济于事,您仍然需要实现适当的数组边界检查。没有办法解决这个问题,但从好的方面来说,这并不是特别困难。在访问数组之前,只需检查每个索引是否小于零或大于数组维度大小。如果是,请追溯您的程序用于获取该值的步骤,并找到必须存在的错误。

当然,如果程序除了越界错误之外还产生了错误的结果,那么您的算法可能也是错误的。

话虽如此,我仍然不确定我是否理解您描述的算法,但对于这个问题来说它们似乎太复杂了。除非您需要每秒评估数千 block 电路板,否则一个简单的蛮力算法就足够了。只需尝试所有可能的交换,并在每次交换时检查棋盘的一行或一列是否包含 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 板来说,其他一切都太过分了。

关于c++ - 推荐用于 gem 迷阵游戏的改进匹配查找算法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15713452/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com