科大讯飞 ai算法挑战赛
by Ben Carp
通过本·卡尔普
为井字游戏挑战构建AI算法 (Building an AI algorithm for the Tic-Tac-Toe challenge)
As part of the freeCodeCamp curriculum, I was challenged build a Tic-Tac-Toe web app. It was a real pleasure.
作为freeCodeCamp课程的一部分,我遇到了构建Tic-Tac-Toe网络应用程序的挑战。 真的很高兴。
The app includes an ultimate computer player. It can optimize any given situation on the Tic-Tac-Toe board. The outcome surprised me.
该应用程序包括一个终极的计算机播放器。 它可以优化井字游戏板上的任何给定情况。 结果使我感到惊讶。
Even in such a simple game, the computer player taught me some new moves. As for the code I wrote, it is somewhat unique and interesting to explore.
即使在这样简单的游戏中,计算机玩家也会教给我一些新的动作。 至于我编写的代码,它有些独特且有趣。
看看这个 (Check it out)
Visit this link and choose to play against the computer. I challenge you to win. You might find…that you can’t.
访问此链接,然后选择与计算机对战。 我挑战你赢 。 您可能会发现……您做不到。
Yet, if you are hard on the defense, you might find out that the computer is not able to win either. I learned by experience that Tic-Tac-Toe has a simple non-lose strategy.
但是,如果您在防御上很努力,则可能会发现计算机也无法获胜。 我从经验中学到,井字游戏有一个简单的不输球策略。
This means that if you manage to get a tie you are making the right defensive choices. The computer still optimizes its’ moves. So, the best result it can achieve against a player such as yourself might only be a tie.
这意味着,如果您设法获得平局,那么您将做出正确的防守选择。 电脑仍在优化其动作。 因此,对您这样的玩家所能达到的最佳结果可能只是平局。
主要解决方案步骤 (Main Solution steps)
1.板子数据结构 (1. board data structure)
_gameBoard: [[“”, “”, “”],[“”, “”, “”],[“”, “”, “”]]
The board Array contains 3 arrays, each representing a row.Each row array contains 3 character or string elements.
板子数组包含3个数组,每个数组代表一行。每个行数组包含3个字符或字符串元素。
These elements are either:
这些元素是:
- “ ” as an empty string, representing an empty cell “”为空字符串,表示一个空单元格
- “X” representing the X player 代表X播放器的“ X”
- “O” representing the O player 代表O玩家的“ O”
2. getResult函数 (2. getResult function)
At any given state, the board will be in one and one only of these possible states:
在任何给定状态下,董事会将处于以下一种或一种可能的状态:
- Incomplete 不完整
- player X won 玩家X赢了
- Player O won 玩家O赢了
- or a tie 或领带
The getResult
function receives a board array, iterates over all the rows, through all the columns and across both diagonals. It checks the succession of symbols. Then it lets us know the current state of that board.
getResult
函数接收一个board数组,遍历所有行,所有列以及两个对角线。 它检查符号的连续性。 然后,它让我们知道该板的当前状态。
3. getBestMove函数 (3. getBestMove Function)
Here it gets more difficult. When the board is empty it is very difficult to identify the best possible move. Take a look at this board.
在这里变得更加困难。 当木板为空时,很难确定最佳移动方式。 看一下这个板子。
Which is the best possible possible move?
哪个可能是最好的举动?
When the board becomes populated, the best possible move pops out to our eyes.
当木板装满时,最好的动作突然出现在我们眼前。
Let’s use this populated board as our starting point. Lets decide that the next move is ours, and that our symbol is an “X”.
让我们以填充的木板为起点。 让我们决定下一步是我们的行动,我们的符号是“ X”。
Let’s try to identify the best possible move with the tools we already have. There are 3 empty cells that correspond with 3 possible moves. Lets check the result for each of these options.
让我们尝试使用我们现有的工具来确定最佳的移动方式。 有3个空单元格,它们对应3种可能的移动。 让我们检查每个选项的结果。
We can do this by iterating over the possible moves, and for each of them:
我们可以通过迭代可能的移动来实现此目的,对于每个移动:
- Create a new board 创建一个新板
- Add our symbol to the corresponding empty cell 将我们的符号添加到相应的空单元格中
Send this board to the
getResult
function将该板发送到
getResult
函数
From the 3 boards in the figure above, when we send the second board to the getResult
function, we will receive our trophy.
从上图中的3个板中,当我们将第二个板发送到getResult
函数时,我们将获得奖杯。
Please concentrate for the next essential steps:
请集中精力进行以下基本步骤:
- We need to grade the possible moves so we can compare them. Let’s decide that if a move yields a winning board we will grade it 1. If it yields a losing board it will receive the grade of -1. A tie will receive a grade of 0. 我们需要对可能的移动进行分级,以便可以对其进行比较。 让我们决定,如果一个举动产生一个获胜的棋盘,我们将其评分为1。如果它产生一个失败的棋盘,则其评分将为-1。 平局得分为0。
- Move 2 will receive a grade of 1. When we find a move graded with 1 we can ignore all other possible moves. There is no other better possible move than a definite victory. 动作2的等级为1。当我们找到等级为1的动作时,我们可以忽略所有其他可能的动作。 没有比确定的胜利更好的举动了。
- But for the sake of understanding, how would we grade moves 1 or 3, or any other move with an incomplete result? 但是为了理解,我们将如何对第1或第3步或任何其他结果不完整的步进行评分?
Let’s Focus on move 3. The solution is to send the corresponding board recursively to the getBestMove
function.
让我们关注移动3。解决方案是将相应的板递归发送到getBestMove
函数。
You might be thinking, “But wait! Our opponent plays the next move.” That’s right. Let’s find out what grade our opponent gets for his best future move.
您可能会想,“但是等等! 我们的对手下一个动作。” 那就对了。 让我们找出对手最好的未来举动所获得的等级。
Our opponent has only two possible moves:
我们的对手只有两个可能的举动:
Move 3–1 will win the game in favor of our opponent. Since we are using the exact same getBestMove
function, Move 3–1 will receive a grade of 1.
3–1的举动将赢得我们对手的胜利。 由于我们使用的是完全相同的getBestMove
函数,因此Move 3–1的等级为1。
This might be a bit confusing as both our victory and our loss will receive grades of 1. We need to remember that this function call belongs to our opponent, and his victory is our loss and vice versa.
这可能有点令人困惑,因为我们的胜利和失败都将得到1级。我们需要记住,此函数调用属于我们的对手,而他的胜利就是我们的失败,反之亦然。
We must negate any grade returned to the getBestMove
function by the getBestMove
function.
我们必须取消由getBestMove
函数返回给getBestMove
函数的任何成绩。
Move 3–1 receives a grade of 1. The getBestMove
function returns a grade of 1, and we can grade Move 3 with a -1.
移动3-1的等级为getBestMove
函数返回的等级为1,我们可以将移动3的等级getBestMove
-1。
In this manner, the getBestMove
function continues to explore moves and consequent moves. This process will continue until:
以这种方式, getBestMove
函数继续探索移动以及随后的移动。 该过程将持续到:
- It finds a move graded with 1, in which case it will return the move immediately 它会找到等级为1的移动,在这种情况下,它将立即返回该移动
- It will continue until each possible move has a grade. The possible moves (with grades 0 and -1) are stored in an array 它将继续,直到每个可能的动作都得到评分。 可能的移动(等级0和-1)存储在数组中
The array will then be:
该数组将是:
[a] randomized
[a]随机
[b] sorted from high to low
[b]从高到低排序
[c] the first element will be returned
[c]第一个元素将被返回
These steps guarantee that:
这些步骤保证:
- A losing move will be avoided unless it’s the only option 除非是唯一的选择,否则将避免失败。
- The computer player can play diversely 电脑播放器可以玩多种游戏
尾注: (End Notes:)
There are strong legitimate concerns over the risks Artificial Intelligence (AI) brings with it.
人们对人工智能(AI)带来的风险有强烈的正当担忧。
Lets use AI for the benefit of all.
让AI造福所有人。
The best possible AI software is that which can prevent us from misusing AI.
最好的AI软件是可以防止我们滥用AI的软件。
I consulted Assaf Weinberg in the process of writing the app
在编写应用程序的过程中,我咨询了阿萨夫·温伯格 ( Assaf Weinberg)
See my code on GitHub.
在GitHub上查看我的代码 。
科大讯飞 ai算法挑战赛