我正在尝试实施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点对齐方式,还是告诉我是否有更好的方法?
答案 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开始,顺时针移动)对方向建模。每个方向都有一个关联的运动,表示为dr
和dc
。沿各个方向移动时,我会计算出其中有多少个点(最多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;
}