对Tic Tac Toe的建议

时间:2010-11-14 01:52:17

标签: java tic-tac-toe

我正在为Tic-Tac-Toe游戏设计我的实施策略。由于这是我的第一个游戏实现,我有点困惑,需要一些通用指针。

现在,Tic-Tac-Toe中的获胜组合总数为8.目前,我计划将这些获胜组合存储在一个阵列中。一旦最终用户进行了至少3次移动,我将通过比较Player对阵此阵列的当前位置来开始检查玩家是否赢得了游戏。但是,我确信这不是检查玩家是否有获胜组合的有效方法。

有人可以建议我如何设计游戏的逻辑吗?

6 个答案:

答案 0 :(得分:11)

不要担心效率。我写了一个回溯解决方案,只有549,945个可能的游戏状态。在笔记本电脑上运行这些操作只需不到0.25秒。这是我的逻辑,看看游戏是否结束 - 显然效率不高,但无所谓:

private boolean isWinningMove(int row, int col) {
    int piece = board[row][col];

    // check current row
    boolean w = true;
    for (int x = 0; x < 3; x++) { w = w && (board[row][x] == piece); }
    if (w) { return true; }

    // check current column
    w = true;
    for (int x = 0; x < 3; x++) { w = w && (board[x][col] == piece); }
    if (w) { return true; }

    // check 0,0 diagonal
    w = true;
    for (int x = 0; x < 3; x++) { w = w && (board[x][x] == piece); }
    if (w) { return true; }

    // check 0,2 diagonal
    w = true;
    for (int x = 0; x < 3; x++) { w = w && (board[x][2 - x] == piece); }
    return w;
}

以下是我的结果,它与维基百科页面上的数据匹配:

Moves Simulated: 549945
Draws=46080   Player1-Wins=131184   Player2-Wins=77904
Perfect Strategy Implies: Always a tie.

Games won in 0 moves? 0
Games won in 1 moves? 0
Games won in 2 moves? 0
Games won in 3 moves? 0
Games won in 4 moves? 0
Games won in 5 moves? 1440
Games won in 6 moves? 5328
Games won in 7 moves? 47952
Games won in 8 moves? 72576
Games won in 9 moves? 81792

答案 1 :(得分:5)

由于井字游戏的状态空间非常小,你可以存储所有可能的最终游戏位置,并使用旋转,但我认为你过度思考它。 / p>

不是为游戏板存储3x3阵列,而是使用7x7阵列,游戏板最内部为3x3。每个方块至少应包含三个值 - 例如PLAYER_1PLAYER_2NONE。最初,所有值都应设置为NONE。然后,在每个玩家的移动之后,检查所选择的正方形周围的所有3个; 2以上,2下,2左,2右,2左上,2右下,2右上,2左下。

为什么7x7阵列?使用7x7阵列,您可以安全地从3x3区域中的任何方向搜索所有方向,而无需if语句来查看您是否正在离开阵列的边缘。董事会将如下所示:

  0 1 2 3 4 5 6
0 * * * * * * *

1 * * * * * * *

2 * * * * * * *

3 * * * * * * *

4 * * * * * * *

5 * * * * * * *

6 * * * * * * *

例如,如果第一个玩家移动到tic-tac-toe板上的0,0,则与在7x7板上移动到2,2相同。当进行移动时,你会在2,2平方左右进行检查,以查看一行中是否有三个具有相同值的正方形

  • 以上:2,0和2,1和2,2
  • 以下:2,2和2,3和2,4
  • 左:0,2和1,2和2,2
  • 右:2,2,2,3和2,4
  • 左上:0,0和1,1和2,2
  • 右上:2,2和3,1和4,0
  • 左下:0,4和1,3和2,2
  • 右下:2,2和3,3和4,4

由于3x3板周围的方块带总是具有值NONE,因此它们永远不会触发获胜条件。

如果其中任何一个都匹配相同的玩家价值(例如第一个玩家的PLAYER_1),则游戏结束并获胜。否则,如果所有方格都被拍摄,那么游戏就是平局。

我过去曾将它用于其他类似的游戏并且效果很好。

答案 2 :(得分:3)

而不是迭代某些东西,我只写了8个组合。

我的评价函数执行以下操作:如果A是移动的一侧&amp;如果在所有组合之一中有两个A元素和一个0(空),那么它就是胜利:

boolean player_can_win(int value) { //value is side's element*2
    return board[0] + board[1] + board[2] == value
            || board[3] + board[4] + board[5] == value
            || board[6] + board[7] + board[8] == value
            || board[0] + board[3] + board[6] == value
            || board[1] + board[4] + board[7] == value
            || board[2] + board[5] + board[8] == value
            || board[0] + board[4] + board[8] == value
            || board[2] + board[4] + board[6] == value;
}

答案 3 :(得分:3)

考虑用整数表示董事会。

-1 = X
 0 = empty
 1 = O

现在,将8种可能性中的每一种加上正方形的值(3个上下,3个左右,2个区域)。

如果总和为3,则O获胜 如果总和为-3,则X胜出

如果总和为2,那么O在其中一个位置有一个获胜的动作 如果总和为-2,那么X在其中一个位置有一个获胜的动作。

AI可以将其作为决策的基础。向前看一步就足以永远不会失败。

如果AI开始游戏,那么最好的动作就是一个角落。如果对手未能占据中锋,则AI获胜。如果他确实占据了中心,那么AI就赢了,或者抽签。

答案 4 :(得分:2)

如果你正在播放广义的NXN tic-tac-toe,那么明确地存储和比较解决方案并不是最有效的,但是因为它就像小板,只有8个这样的组合,所以明确存储像这样的解决方案没有任何问题

更大的问题是,根据存储风格,与解决方案无关的空间可能是个问题。

O - -        - O -
X X X   vs.  X X X
O - O        O - O

比较3x3状态数组这些是不同的,因此这种方法需要超过8个结束状态

我认为你保留类似gameState 3x3数组的东西,空白= 0,X = 1,O = 2?

除了那些明确的比较,你可以做类似

的事情
win = false   
// rows/columns
for i in 0,1,2
   if (state[i][0] != BLANK && state[i][0] == state[i][1] == state[i][2]) win = true
          #extensible to NxN - all(j == state[i][0] for j in state[i])
   if (state[0][i] != BLANK && state[0][i] == state[1][i] == state[2][i]) win = true
          #extensible to NxN - all(j == state[0][i] for j in zip(*state)[i])
//diagonals
if (state[0][0] != BLANK && state[0][0] == state[1][1] == state[2][2]) win = true
          #extensible to NxN - all(state[j][j] == state[0][0] for j in range(len(state))
if (state [2][0] != BLANK && state[2][0] == state[1][1] == state[0][2]) win = true

如果你想获胜来存储胜利者而不是旗帜,那么将win = BLANK置于顶部,并设置为任何相关正方形的值。不应该是必要的,胜利者显然是最近的举动!

我认为编写井字游戏的那部分你可能会发现最具挑战性,但并不太难,是AI。编写一个不会丢失的AI(总是至少可以强制打平)并不是很困难,但并非完全无足轻重。如果你想要一个能够偶尔丢失的相对优秀的AI,你需要添加一些随机性或其他东西。

答案 5 :(得分:0)

实施Tic Tac Toe游戏可能是就AI而言要解决的最简单问题 和搜索空间。

关键是要使用MinimaxIterative deepening Depth-first searchAlpha-beta pruning算法来解决问题。

这是我用Python编写的游戏implementation,它只有约200行代码,并具有以Human vs. HumanHuman vs. Computer和{{1} }。它还可以统计到达/修剪的节点的深度和数量,从而达到最佳移动效果。

我强烈推荐Computer vs. Computer人工智能course,它提供了有关当前AI主题和解决方案的基础知识。