如何在“加入五人”游戏中找到所有可能的5点对齐方式

时间:2019-04-11 19:14:56

标签: c algorithm

我正在尝试实施Join Five游戏。在给定网格和点的初始配置的情况下,您必须在自由交叉中添加点,以便添加的每个点与网格中已有的点形成5点线。两条线可能只有一个共同点(它们可能交叉或端到端接触)

我的游戏网格是一个包含0或1的int数组。如果有一个点,则为1;如果没有,则为0。

我在实现方面做得不错,但我想展示所有可能的动作。 我做了一个很长很丑陋的功能,可以在这里使用:https://pastebin.com/tw9RdNgi(对我的帖子来说太长了,很抱歉) 这是一个代码片段:

if(jeu->plat[i][j] == 0) // if we're on a empty spot
            {
                for(k = 0; k < lineSize; k++) // for each direction
                {
                    //NORTH    
                    if(jeu->plat[i-1-k][j] == 1) // if there is a dot north 
                    {
                        n++; // we count it 
                    }
                    else
                    {
                        break; //we change direction
                    }
                } //  

此代码在改变方向的其他七次重复自身,如果n或任何其他变量达到4,我们将x和y视为可能的移动。

它甚至都没有处理所有情况,如果可用点在2到2点之间,它将不计算在内。 3和1以及1和3相同。

但是我不认为我的开始方式是最好的。我很确定有一种更简单,更优化的方法,但是我不知道。

所以我的问题是:有人可以帮助我找出如何找到所有可能的5点对齐方式,还是告诉我是否有更好的方法?

1 个答案:

答案 0 :(得分:2)

好吧,这个问题比看起来要困难得多,并且需要很多代码。如果您发布了运行它所需的所有必要代码,那就是Minimal, Complete, and Verifiable Example,一切都会变得更加简单。无论如何,我采取了一种针对该问题的结构来对其进行测试。

回答您问题的那部分是以下内容:

typedef struct board {
    int side_;
    char **dots_;
} board;

void board_set_possible_moves(board *b)
{
    /* Directions
        012
        7 3
        654 */
    static int dr[8] = { -1,-1,-1, 0, 1, 1, 1, 0 };
    static int dc[8] = { -1, 0, 1, 1, 1, 0,-1,-1 };

    int side_ = b->side_;
    char **dots_ = b->dots_;
    for (int r = 0; r < side_; ++r) {
        for (int c = 0; c < side_; ++c) {
            // The place already has a dot
            if (dots_[r][c] == 1)
                continue;
            // Count up to 4 dots in the 8 directions from current position
            int ndots[8] = { 0 };
            for (int d = 0; d < 8; ++d) {
                for (int i = 1; i <= 4; ++i) {
                    int nr = r + dr[d] * i;
                    int nc = c + dc[d] * i;
                    if (nr < 0 || nc < 0 || nr >= side_ || nc >= side_ || dots_[nr][nc] != 1)
                        break;
                    ++ndots[d];                        
                }
            }
            // Decide if the position is a valid one
            for (int d = 0; d < 4; ++d) {
                if (ndots[d] + ndots[d + 4] >= 4)
                    dots_[r][c] = 2;
            }
        }
    }
}

请注意,我定义了一个带有点的正方形板。如果它们为0,则没有点;如果它们为1,则有一个点;如果它们为2,则该点没有点但有效移动。此处有效表示至少有4个点与当前点对齐。 您可以使用0到7之间的数字(从NW开始,顺时针移动)对方向建模。每个方向都有一个关联的运动,表示为drdc。沿各个方向移动时,我会计算出其中有多少个点(最多4个,发现非点后立即停止),然后我可以对相反的方向求和以获得对齐点的总数。

这些动作当然不一定有效,因为我们缺少已经绘制的线条的定义,因此我们无法对其进行检查。

在这里您可以找到对该功能的测试。

#include <stdio.h>
#include <stdlib.h>

board *board_init(board *b, int side) {
    b->side_ = side;
    b->dots_ = malloc(side * sizeof(char*));
    b->dots_[0] = calloc(side*side, 1);
    for (int r = 1; r < side; ++r) {
        b->dots_[r] = b->dots_[r - 1] + side;
    }
    return b;
}
board *board_free(board *b) {
    free(b->dots_[0]);
    free(b->dots_);
    return b;
}
void board_cross(board *b) {
    board_init(b, 18);
    for (int i = 0; i < 4; ++i) {
        b->dots_[4][7 + i] = 1;
        b->dots_[7][4 + i] = 1;
        b->dots_[7][10 + i] = 1;
        b->dots_[10][4 + i] = 1;
        b->dots_[10][10 + i] = 1;
        b->dots_[13][7 + i] = 1;

        b->dots_[4 + i][7] = 1;
        b->dots_[4 + i][10] = 1;
        b->dots_[7 + i][4] = 1;
        b->dots_[7 + i][13] = 1;
        b->dots_[10 + i][7] = 1;
        b->dots_[10 + i][10] = 1;
    }
}
void board_print(const board *b, FILE *f)
{
    int side_ = b->side_;
    char **dots_ = b->dots_;
    for (int r = 0; r < side_; ++r) {
        for (int c = 0; c < side_; ++c) {
            static char map[] = " oX";
            fprintf(f, "%c%s", map[dots_[r][c]], c == side_ - 1 ? "" : " - ");
        }
        fprintf(f, "\n");
        if (r < side_ - 1) {
            for (int c = 0; c < side_; ++c) {
                fprintf(f, "|%s", c == side_ - 1 ? "" : "   ");
            }
            fprintf(f, "\n");
        }
    }
}

int main(void)
{
    board b;
    board_cross(&b);

    board_set_possible_moves(&b);
    board_print(&b, stdout);

    board_free(&b);
    return 0;
}