2013-05-10 42 views
4

我是一名初级程序员,我知道pascal和C++的基础知识。我用玩家电脑制作了一个Tic Tac Toe游戏,游戏全部结束。解决TicTacToe引擎

计算机生成一个随机的地方,Os在桌子上,这是不好的。

我以为我应该检查每个获胜位置的多个程序,并且计算机应该尝试阻止玩家的X或获得胜利的位置,但是如果是这样的话,这将会浪费很多时间。

然后我想到了一个更简单的版本,但它仍然需要很多时间来完成。

然后我想到更深入的了解:如何找到四个游戏?如何在地球上有人会设法检查每个可用的空间,以及如何有可能做出一个功能,绝对检查任何获胜或进步的球员/计算机的位置,哦,等待,这不是全部,如果玩家正在做一些技巧,所以他阻止了电脑?计算机如何知道?!?当然,这需要很长时间才能编程。我不是在谈论更不可能的事情:国际象棋。

所以我在这里问自己,应该有一种更简单的方式来让计算机搜索和解决一些问题,而不是吨的ifs。在这种情况下,如果你们中的任何一个知道解决这个问题的方法,我怎样才能使最简单的程序在TicTacToe游戏中阻止和击败玩家?

如果有人想检查我的代码或使用它:http://pastebin.com/jhyUn7d1

+0

有* *许多技巧。对于像TTT这样的简单游戏,您应该搜索“深度优先搜索”。对于更复杂的游戏,您可以开始研究“alpha-beta修剪”。对于*真正*复杂的游戏,您可以阅读,比如说,“蒙特卡洛树搜索”。 – 2013-05-10 18:54:05

+2

http://imgs.xkcd.com/comics/tic_tac_toe.png:P – BlackBear 2013-05-10 18:59:22

+0

[Simple tic-tac-toe AI]的可能重复(http://stackoverflow.com/questions/15753572/simple-tic-tac-脚趾爱) – 2013-05-10 19:29:00

回答

1

井字算法是这样的:

  1. 采取现货,如果要赢
  2. 采取现货,如果要输
  3. 带角
  4. 带非角落非中心
  5. 带中心
+0

我相信你应该移动5到3. – 2013-05-10 19:01:42

+0

有更好的技术。角落并不总是最好的举措。有些情况下,移动可能会产生两个可能的胜利,而这两个胜利都不能被阻止。 – 2013-05-10 19:12:10

0

我最近处理了这个,虽然我的代码是在C#中。

我想出了一个评分每个候选人移动的方法。我采取的方法根据胜出所需的移动次数创建一个分数(需要的移动次数越少,得分越高)。

我的算法还考虑多个方块的组合移动数。因此,该算法倾向于产生多个潜在胜利的移动(我知道的唯一真正的策略是Tic Tac Toe)。举例来说,有时候可能会产生两个必须被阻止的潜在胜利。由于对手只能阻挡一个,所以会赢得胜利。

我在文章A Tic-Tac-Toe Game Engine上发布了我的整个代码和说明。

0

简短的回答是“尝试所有不同的动作,直到赢得比赛,并记录哪些将导致计算机获胜”。

朗answerÖ

在有限的尺寸TTT游戏,可能的移动游戏赢之前的数量,并不算多,所以索性尝试了每一种可能的举动,然后递归尝试所有可能的对手的动作,并继续前进,直到比赛结束。给每一个动作一个“得分”,说明它有多好(例如,你有多少种不同的解决方案取得了成功的电脑,有多少成功的对手,并选择“最好”的结果)。要小心,如果你做得好,你可能会得到一些近乎不可能胜出的东西。

3

你要寻找的是Minimax

使用这种算法的计算机将赢得每一个井字游戏或者你可以调整计算机进行分析,以达到某种中等难度的动作的深度。

这并不难实现,你应该熟悉递归性和你设置,当然根据执行你的代码不同,但维基百科页面提供了一个很好的起点。

+1

这是完全正确的。最小极大值将用于在任何2人游戏中确定最佳移动,确定性游戏具有完美的游戏状态知识。所以它也适用于连接4,跳棋,甚至国际象棋。(尽管对于象棋这样的状态空间极其复杂的游戏,该算法在实践中是难以处理的)。另外,对于n个玩家游戏,具有隐藏信息的游戏,具有随机元素的游戏等,存在该算法的扩展。 – 2013-05-10 19:28:00

0

我这样做一次,很久以前。我不知道我是否仍然有代码躺在...

无论如何,我创建了一个函数,返回类型int,这是计算机应该放置其块的方形(假设0是左上角, 8是右下方)。你的使用二维数组,所以会有所不同。

无论如何,对于每一行,列和对角线,检查是否在该行任意两件属于球员。如果他们没有,检查相同但属于计算机。在第一行,这是真实的,检查剩下的一块 - 如果它可用,把那块作为胜利。如果你有一个以玩家为主的行,请检查你是否已经有一个零件,然后将其粘住。

const int PlayerPiece = 1; 
const int CPiece = 2; 
const int Empty = 0; 

int board[3][3]; 
if(board[0][0] == PlayerPiece && board[0][1] == PlayerPiece && board [0][2] == Empty) 
{ 
    //Put_Your_Piece_In_[0][2] 
} 

然后,您可以去改变它,以便它可以检查每一行即

int numRows = 3; 

for(int i = 0; i < numRows; i++) 
{ 
if(board[i][0] == PlayerPiece && board[i][1] == PlayerPiece && board[i][2] == Empty) 
    { 
    //Put_Piece_In_[i][2] 
    } 
} 

然后,做同样的行。

你总是可以考虑井字棋本质上只是一个幻方,还算描述以及这里:http://www.sciforums.com/showthread.php?134281-An-isomorphism-Tic-Tac-Toe-on-Magic-Square

0

没有为井字棋available on wikipedia一个完美的策略。这非常简单。由于网格尺寸较小,因此需要测试的案例数量(例如,测试连续有两个块)是非常小的。