代表四开棋盘游戏棋子的最佳方式
Best way to represent Quarto Board Game Pieces
我正在制作棋盘游戏 Quarto。它本质上是高级连接 4.
每件作品都有四个显着特征(白色 VS 黑色 | 高 VS 短 | 方形 VS 圆形 | 实心 VS 空心)。如果您连续获得其中任何四个功能,您就赢了。
目前,我正在尝试编写一个函数来检查是否获胜。然而,它有望成为 O(n^4),我认为我可以根据我的代码结构来改进它。
目前,我有这个:
enum Piece
{
WTSS, WTSH, WTHS, WTHH,
WSSS, WSSH, WSHS, WSHH,
BTSS, BTSH, BTHS, BTHH,
BSSS, BSSH, BSHS, BSHH,
EMPTY
};
static const char * PieceStrings[] = {
"WTSS ", "WTSH ", "WTHS ", "WTHH ",
"WSSS ", "WSSH ", "WSHS ", "WSHH ",
"BTSS ", "BTSH ", "BTHS ", "BTHH ",
"BSSS ", "BSSH ", "BSHS ", "BSHH ",
"____ ",
};
但我认为这不是很有效。我曾考虑过让它们成为自己的 class,但这样就很难初始化和使用所有这些部分。
这就是我开始检查获胜的方式:
// go through all N+2 possible connections
// check if any have shared feature
bool Board::isWin() {
int i, j, k;
for (i = 0, k = BOARDSIZE-1; i < BOARDSIZE; i++, k--) {
for (j = 0; j < BOARDSIZE; j++) {
//Horizontal case
// board[i][j];
//Vertical case
// board[j][i];
}
// Diagonal cases
// board[i][i];
// board[k][i];
}
return false;
}
// Checks if pieces have a similar component
bool Board::checkPieces(list<string> & piecesInARow) {
int i, j;
list<string>::iterator it = piecesInARow.begin();
for (i = 0; i < BOARDSIZE; i++) {
for (j = 0; j < BOARDSIZE; j++) {
// check if pieces all have shared char at index
}
}
}
我该如何改进它并让自己更轻松?
每个 属性 有 2 种可能性,因此您可以将它们作为 0 或 1 存储在位域中。例如:
unsigned char type = (color << 0) | (size << 1) | (shape << 2) | (thickness << 3)
其中每个值都是 0 或 1。假设:
enum Color { BLACK = 0, WHITE = 1 };
enum Size { SHORT = 0, TALL = 1 };
enum Shape { CIRCLE = 0, SQUARE = 1 };
enum Thickness { HOLLOW = 0, SOLID = 1 };
然后您可以通过检查 XNOR(位相等性)来比较它们,以便在一次操作中一次比较 2,其中每次比较将 return 比较相等的类型的位域。
(piece1 XNOR piece2) AND (piece2 XNOR piece3) AND (piece3 XNOR piece4) != 0
像这样
class Piece {
public:
Piece(Color color, Size size, Shape shape, Thickness thickness) {
type = (color) | (size << 1) | (shape << 2) | (thickness << 3);
}
Color color() const {
return static_cast<Color>((type >> 0) & 1);
}
Size size() const {
return static_cast<Size>((type >> 1) & 1);
}
Shape shape() const {
return static_cast<Shape>((type >> 2) & 1);
}
Thickness thickness() const {
return static_cast<Thickness>((type >> 3) & 1);
}
static bool compare(Piece p0, Piece p1, Piece p2, Piece p3) {
unsigned char c[3];
c[0] = ~( p0.type ^ p1.type ); // XNOR
c[1] = ~( p1.type ^ p2.type ); // XNOR
c[2] = ~( p2.type ^ p3.type ); // XNOR
return (c[0] & c[1] & c[2] & 0b1111) != 0;
}
protected:
unsigned char type;
};
我用这段代码测试了它:
int main() {
Piece p0(WHITE, SHORT, CIRCLE, HOLLOW);
Piece p1(WHITE, SHORT, CIRCLE, HOLLOW);
Piece p2(BLACK, SHORT, CIRCLE, HOLLOW);
Piece p3(BLACK, TALL, CIRCLE, SOLID);
const char* str = Piece::compare(p0, p1, p2, p3) ? "success" : "fail";
std::cout << str << '\n';
return 0;
}
我决定用一个class来管理它,但是,每一块都是一个4位的值,所以它可以很容易地用一个整数类型来管理。
这样做的另一个结果是,可以通过选择 0b0000 和 0b1111 之间的值来随机化片段,该值包含 [0,15]。
我正在制作棋盘游戏 Quarto。它本质上是高级连接 4.
每件作品都有四个显着特征(白色 VS 黑色 | 高 VS 短 | 方形 VS 圆形 | 实心 VS 空心)。如果您连续获得其中任何四个功能,您就赢了。
目前,我正在尝试编写一个函数来检查是否获胜。然而,它有望成为 O(n^4),我认为我可以根据我的代码结构来改进它。
目前,我有这个:
enum Piece
{
WTSS, WTSH, WTHS, WTHH,
WSSS, WSSH, WSHS, WSHH,
BTSS, BTSH, BTHS, BTHH,
BSSS, BSSH, BSHS, BSHH,
EMPTY
};
static const char * PieceStrings[] = {
"WTSS ", "WTSH ", "WTHS ", "WTHH ",
"WSSS ", "WSSH ", "WSHS ", "WSHH ",
"BTSS ", "BTSH ", "BTHS ", "BTHH ",
"BSSS ", "BSSH ", "BSHS ", "BSHH ",
"____ ",
};
但我认为这不是很有效。我曾考虑过让它们成为自己的 class,但这样就很难初始化和使用所有这些部分。
这就是我开始检查获胜的方式:
// go through all N+2 possible connections
// check if any have shared feature
bool Board::isWin() {
int i, j, k;
for (i = 0, k = BOARDSIZE-1; i < BOARDSIZE; i++, k--) {
for (j = 0; j < BOARDSIZE; j++) {
//Horizontal case
// board[i][j];
//Vertical case
// board[j][i];
}
// Diagonal cases
// board[i][i];
// board[k][i];
}
return false;
}
// Checks if pieces have a similar component
bool Board::checkPieces(list<string> & piecesInARow) {
int i, j;
list<string>::iterator it = piecesInARow.begin();
for (i = 0; i < BOARDSIZE; i++) {
for (j = 0; j < BOARDSIZE; j++) {
// check if pieces all have shared char at index
}
}
}
我该如何改进它并让自己更轻松?
每个 属性 有 2 种可能性,因此您可以将它们作为 0 或 1 存储在位域中。例如:
unsigned char type = (color << 0) | (size << 1) | (shape << 2) | (thickness << 3)
其中每个值都是 0 或 1。假设:
enum Color { BLACK = 0, WHITE = 1 };
enum Size { SHORT = 0, TALL = 1 };
enum Shape { CIRCLE = 0, SQUARE = 1 };
enum Thickness { HOLLOW = 0, SOLID = 1 };
然后您可以通过检查 XNOR(位相等性)来比较它们,以便在一次操作中一次比较 2,其中每次比较将 return 比较相等的类型的位域。
(piece1 XNOR piece2) AND (piece2 XNOR piece3) AND (piece3 XNOR piece4) != 0
像这样
class Piece {
public:
Piece(Color color, Size size, Shape shape, Thickness thickness) {
type = (color) | (size << 1) | (shape << 2) | (thickness << 3);
}
Color color() const {
return static_cast<Color>((type >> 0) & 1);
}
Size size() const {
return static_cast<Size>((type >> 1) & 1);
}
Shape shape() const {
return static_cast<Shape>((type >> 2) & 1);
}
Thickness thickness() const {
return static_cast<Thickness>((type >> 3) & 1);
}
static bool compare(Piece p0, Piece p1, Piece p2, Piece p3) {
unsigned char c[3];
c[0] = ~( p0.type ^ p1.type ); // XNOR
c[1] = ~( p1.type ^ p2.type ); // XNOR
c[2] = ~( p2.type ^ p3.type ); // XNOR
return (c[0] & c[1] & c[2] & 0b1111) != 0;
}
protected:
unsigned char type;
};
我用这段代码测试了它:
int main() {
Piece p0(WHITE, SHORT, CIRCLE, HOLLOW);
Piece p1(WHITE, SHORT, CIRCLE, HOLLOW);
Piece p2(BLACK, SHORT, CIRCLE, HOLLOW);
Piece p3(BLACK, TALL, CIRCLE, SOLID);
const char* str = Piece::compare(p0, p1, p2, p3) ? "success" : "fail";
std::cout << str << '\n';
return 0;
}
我决定用一个class来管理它,但是,每一块都是一个4位的值,所以它可以很容易地用一个整数类型来管理。
这样做的另一个结果是,可以通过选择 0b0000 和 0b1111 之间的值来随机化片段,该值包含 [0,15]。