检测零分和交叉中获胜的比赛

发布于 2024-08-29 03:06:09 字数 119 浏览 11 评论 0原文

我需要知道在圈和十字游戏中检测获胜动作的最佳方法。源代码并不重要,我只需要一个示例或可以开始的东西。

我唯一能想到的就是使用循环并测试玩家所做的每个动作的每个方向,例如连续搜索五个。有没有更快更有效的方法呢?

I need to know the best way to detect a winning move in a game of noughts and crosses. Source code doesn't matter, I just need a example or something I can start with.

The only thing I can come up with is to use loops and test every direction for every move a player makes, to search for e.g five in a row. Is there a faster and more efficient way?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

淡淡绿茶香 2024-09-05 03:06:09

真正简单的解决方案是从最后一步开始检查...显然,之前的任何一步都不可能赢得比赛,否则你就不会在这里...所以你只需要检查是否有 5 (或无论多少)在刚刚放置的棋子周围的行/列/对角线上。

例如,如果棋盘看起来像这样,并且 X 标记了最近的移动:

.............
.............
.............
.............
.....X.......
.............
.............
.............
.............
.............

您不需要检查“C”范围之外的任何内容:

.C...C...C...
..C..C..C....
...C.C.C.....
....CCC......
.CCCCXCCCC...
....CCC......
...C.C.C.....
..C..C..C....
.C...C...C...
.............

这有帮助吗? (看起来您可能在最初的问题中提到了这一点,但我不确定。)

除此之外,简单的循环将成为您最好的朋友。您可能可以进行一些微观优化,但是(取决于您的实际应用程序正在做什么)这可能不值得。

需要注意的一件事是,您不能从最近的举动中向任何方向跳出 5 来连续寻找那么多,因为该举动可能处于连续走势的中间。所以我会做类似的事情

From the new move
    left = how many in a row we have to the left of the lastest move
    right = how many in a row we have to the right of the latest move
    if (left + right + 1 >= 5) then you have a winner

    up = how many in a row we have above the latest move
    down = how many in a row we have below the latest move
    if (up + down + 1 >= 5) then you have a winner

    // repeat for both diagonal directions.

The real easy solution is to just check from the last move made...obviously, no prior move could have won the game, or you wouldn't be here...so you just need to check to see if there are 5 (or however many) in a row/column/diagonal around the move that was just placed.

For example, if the board looks like this, and X marks the most recent move:

.............
.............
.............
.............
.....X.......
.............
.............
.............
.............
.............

You don't need to check anything outside the range of "C":

.C...C...C...
..C..C..C....
...C.C.C.....
....CCC......
.CCCCXCCCC...
....CCC......
...C.C.C.....
..C..C..C....
.C...C...C...
.............

Does that help? (It looked like you might be alluding to this in your original question, but I wasn't sure.)

Beyond this, simple loops are going to be your best friend. You could probably do some micro-optimization, but (depending on what your actual application is doing) it's probably not worth it.

One thing to keep track of is that you can't just jump out 5 in any direction from the most recent move looking for that many in a row, because this move might be in the middle of a streak. So I'd do something like

From the new move
    left = how many in a row we have to the left of the lastest move
    right = how many in a row we have to the right of the latest move
    if (left + right + 1 >= 5) then you have a winner

    up = how many in a row we have above the latest move
    down = how many in a row we have below the latest move
    if (up + down + 1 >= 5) then you have a winner

    // repeat for both diagonal directions.
桜花祭 2024-09-05 03:06:09

圈和叉是一个巧妙的编程挑战,因为您可以使用很多数学技巧来简化问题。

圈和叉通常是 3×3 网格。如果为网格中的每个位置分配一个从 1 到 9 的数字(不按数字顺序),您可以排列数字,使每个水平、垂直和对角线行的总和为 15

+----+----+----+
| 4  | 3  | 8  |
|    |    |    |
+----+----+----+
| 9  | 5  | 1  |
|    |    |    |
+----+----+----+
| 2  | 7  | 6  |
|    |    |    |
+----+----+----+ 

为什么这有用?如果您可以选择属于“O”或“X”的任意三个方格,并且这三个方格的总和为 15,则您知道该玩家赢得了游戏。

Noughts and crosses is a neat programming challenge, because there's alot of mathematical tricks you can use to simplify the problem.

Noughts and crosses is typically a 3-by-3 grid. If you assign each position in your grid a number from one to nine (not in numerical order) you can arrange the numbers so that every horizontal, vertical, and diagonal row adds up to 15

+----+----+----+
| 4  | 3  | 8  |
|    |    |    |
+----+----+----+
| 9  | 5  | 1  |
|    |    |    |
+----+----+----+
| 2  | 7  | 6  |
|    |    |    |
+----+----+----+ 

Why's that useful? If you can pick any three squares belonging to either 'O' or 'X', and those three squares add up to a total sum of 15, you know that player has won the game.

秉烛思 2024-09-05 03:06:09

考虑 3X3 板

令 X = 1
令 O = -1
空格用零表示。

因此,如果顶行看起来像这样 [X][X][X],则总和为 3,因此获胜
[O][O][O] 总和是-3,因此是另一场胜利。

[X][X][ ]为2,因此如果是X回合,他可以通过移动到空白处获胜,否则O必须阻止。

[X][O][X] 为 1,因此没有获胜。

在 3x3 棋盘中,有 8 个位置需要评估。

在 NXN 中,数字会变大,但想法保持不变,

如果 N=8 并且行或列的总和为 7,那么您就知道 X 在该行/列上有一个获胜的动作

。这种方法在高中时对我有用。

最好的祝愿

邪恶

Consider the 3X3 board

Let X = 1
Let O = -1
and a space is represented by a zero.

So if the top row looks like this [X][X][X] the sum is 3, hence it is a win
[O][O][O] the sum is -3, hence it is the other win.

[X][X][ ] is 2, hence if it is X turn, he can win by moving to the blank, or O must block.

[X][O][X] is 1, hence no win.

In a 3x3 board there are 8 positions to evaluate.

In NXN the number gets larger but the idea remains the same

if N=8 and a row or column sums to 7, then you know there is a winning move for X on that row/column

That method worked for me in high school.

Best Wishes

Evil

浅黛梨妆こ 2024-09-05 03:06:09

我不知道还有比循环更好的方法,但是板子太小了,它非常微不足道。

一些 Python 伪代码:

def get_winner(board):
    if board[0][0] != EMPTY and board[0][0] == board[1][1] == board[2][2]:
        return board[0][0]
    if board[2][0] != EMPTY and board[2][0] == board[1][1] == board[0][2]:
        return board[2][0]
    for i in xrange(3):
        if board[i][0] != EMPTY and board[i][0] == board[i][1] == board[i][2]:
            return board[i][0]
        if board[0][i] != EMPTY and board[0][i] == board[1][i] == board[2][i]:
            return board[0][i]

I'm not aware of a better method then looping, but the board is so small, it's quite trivial.

A little Python psuedo code:

def get_winner(board):
    if board[0][0] != EMPTY and board[0][0] == board[1][1] == board[2][2]:
        return board[0][0]
    if board[2][0] != EMPTY and board[2][0] == board[1][1] == board[0][2]:
        return board[2][0]
    for i in xrange(3):
        if board[i][0] != EMPTY and board[i][0] == board[i][1] == board[i][2]:
            return board[i][0]
        if board[0][i] != EMPTY and board[0][i] == board[1][i] == board[2][i]:
            return board[0][i]
寄人书 2024-09-05 03:06:09

有更有效的方法,但只有当您将游戏扩展到更大的棋盘配置时,它们才真正重要。例如,如果您在方向对象中存储了圈和十字的分组(例如,存储对角线配置),则可以按长度 winLength-1 的那些进行排序,并且仅根据这些来测试新的移动分组。您可以保存一些迭代,但必须在内存中保留大量额外信息。

There are more efficient ways, but they really only matter when you extend this game for much, much larger board configurations. For example, if you stored groupings of noughts and crosses in directional objects (store a diagonal configuration, for example), you could sort by those with length winLength-1, and only test the new move against these groupings. You save some iterations, but you have to maintain a lot of extra information in memory.

深爱不及久伴 2024-09-05 03:06:09

这是一个代表性问题。如何存放游戏板?现在跳出框框思考;您还能如何存储它?例如,您可以将棋盘表示为一对位图 - 一个代表零,一个代表十字 - 然后进行数字模式匹配来检测获胜条件。

It's a question of representation. How do you store the game board? Now think outside the box; how else could you store it? You might for example represent the board as a pair of bitmaps - one for noughts and one for crosses - then do a numerical pattern match to detect winning conditions.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文