Arduino Touch Tic-Tac-Toe Game
组件和用品
| × | 1 | ||||
| × | 1 |
应用和在线服务
|
关于这个项目
图> 图>
亲爱的朋友们,欢迎来到另一个 Arduino 教程!在这个详细的教程中,我们将构建一个 Arduino 井字游戏。如您所见,我们使用的是触摸屏,并且是在与计算机对战。像 Tic-Tac-Toe 这样的简单游戏是对游戏编程和人工智能的绝佳介绍。虽然我们不会在这个游戏中使用任何人工智能算法,但我们会理解为什么在更复杂的游戏中需要人工智能算法。
为 Arduino 开发游戏并不容易,需要大量时间。但是我们可以为 Arduino 构建一些简单的游戏,因为它很有趣,并且可以让我们探索一些更高级的编程主题,比如人工智能。这是一次很棒的学习体验,最后您将为孩子们提供一场精彩的游戏!
现在让我们构建这个项目。
第 1 步:获取所有零件
构建此项目所需的部分如下:
- 一个 Arduino Uno
- 2.8 英寸触摸屏
该项目的成本非常低。它只有 15 美元。
在尝试构建此项目之前,请通过单击此处的卡片观看我准备的有关触摸显示器的视频。它将帮助您理解代码,并校准触摸屏。
第 2 步:Arduino 的 2.8" 触摸彩色显示屏 图>
我在 banggood.com 上发现了这个触摸屏,并决定购买它以尝试在我的一些项目中使用它。如您所见,这款显示器价格低廉,售价约为 11 美元。
从这里获取。
显示器提供 320x240 像素的分辨率,它作为一个盾牌提供,这使得与 Arduino 的连接非常容易。如您所见,显示器几乎使用了 Arduino Uno 的所有数字和模拟引脚。使用此屏蔽时,我们的项目只剩下 2 个数字引脚和 1 个模拟引脚。幸运的是,显示器也可以与 Arduino Mega 配合使用,因此当我们需要更多引脚时,我们可以使用 Arduino Mega 而不是 Arduino Uno。不幸的是,此显示器不适用于 Arduino Due 或 Wemos D1 ESP8266 板。盾的另一个优点是它提供了一个非常容易使用的micro SD插槽。
第 3 步:构建项目并对其进行测试 图> 图>
将屏幕连接到 Arduino Uno 后,我们可以加载代码,我们就可以开始玩了。
首先,我们按下“开始游戏”按钮,游戏开始。 Arduino 首先播放。然后我们可以简单地通过触摸屏幕来玩我们的动作。然后 Arduino 开始移动,依此类推。成功将他们的三个标记放置在水平、垂直或对角线上的玩家赢得游戏。游戏结束后,会出现游戏结束画面。然后我们可以按再次播放按钮重新开始游戏。
Arduino 非常擅长这个游戏。它会赢得大部分比赛,或者如果你是一个非常好的球员,比赛将以平局告终。我故意设计这个算法来犯一些错误,以便让人类玩家有机会获胜。通过在游戏代码中再添加两行,我们可以让 Arduino 不可能输掉游戏。但是 2 美元的芯片 Arduino CPU 怎么能打败人脑呢?我们开发的程序比人脑还聪明吗?
第 4 步:博弈算法 图>
为了回答这个问题,让我们看看我实现的算法。
电脑总是先播放。仅凭这一决定,Arduino 就可以更轻松地赢得比赛。第一步总是一个角落。 Arduino 的第二个移动也是从剩余的一个随机角落,根本不关心玩家的移动。从这一点开始,Arduino 首先检查玩家是否可以在下一步中获胜并阻止该移动。如果玩家不能在一次移动中获胜,则它会在可用的情况下进行角移动或从剩余的随机移动中进行。就是这样,这个简单的算法每次都可以击败人类玩家,或者在最坏的情况下,游戏将导致平局。这不是最好的井字游戏算法,而是最简单的算法之一。
这个算法可以很容易地在Arduino中实现,因为井字游戏很简单,我们可以很容易地对其进行分析和解决。如果我们设计博弈树,我们可以发现一些获胜策略并轻松地在代码中实现它们,或者我们可以让 CPU 实时计算博弈树并自行选择最佳棋步。当然,我们在这个游戏中使用的算法非常简单,因为游戏非常简单。如果我们试图为国际象棋设计一个获胜算法,即使我们使用最快的计算机,我们也无法计算一千年后的博弈树!对于这样的游戏,我们需要另一种方法,我们需要一些人工智能算法,当然还有巨大的处理能力。在以后的视频中会详细介绍这一点。
第五步:项目代码
让我们快速浏览一下项目的代码。我们需要三个库来编译代码。
- 改进的 Adafruit TFTLCD
- Adafruit GFX
- 触摸屏
如您所见,即使是这样一个简单的游戏,也需要 600 多行代码。代码很复杂,所以我不会尝试在简短的教程中解释它。不过,我将向您展示 Arduino 移动算法的实现。
一开始,我们随机打两个角。
int firstMoves[]={0,2,6,8}; // 将首先使用这些位置 for(counter=0;counter<4;counter++) //计算第一个动作 { if(board[firstMoves[counter]]!=0) // 第一个动作由某人执行 { movePlayed++; } } do{ if(moves<=2) { int randomMove =random(4); int c=firstMoves[randomMove];如果(板[c]==0){延迟(1000);板[c]=2; Serial.print(firstMoves[randomMove]); Serial.println(); drawCpuMove(firstMoves[randomMove]); b=1; } }
接下来,在每一轮中,我们检查玩家是否可以在下一步中获胜。
int checkOpponent()
{ if(board[0]==1 &&board[1]==1 &&board[2]==0) return 2; else if(board[0]==1 &&board[1]==0 &&board[2]==1) return 1; else if (board[1]==1 &&board [2]==1 &&board[0]==0) return 0; else if (board[3]==1 &&board[4]==1 &&board[5]==0) return 5; else if (board[4]==1 &&board[5]==1&&board[3]==0) return 3; else if (board[3]==1 &&board[4]==0&&board[5]==1) return 4; else if (board[1]==0 &&board[4]==1&&board[7]==1) return 1;否则返回 100;}
如果是,我们在大多数情况下阻止该移动。我们不会为了让人类玩家有机会获胜而阻止所有动作。你能找出哪些动作没有被阻挡吗?阻挡移动后,我们玩剩余的角落,或随机移动。您可以研究代码,并轻松实现自己的无与伦比的算法。与往常一样,您可以在本教程中找到该项目的代码。
注意:由于 Banggood 提供具有两个不同显示驱动程序的相同显示,如果上述代码不起作用,请将 initDisplay 函数更改为以下内容:
void initDisplay(){tft.reset();tft.begin(0x9341);tft.setRotation(3);}
graphics.c TicTacToeEasy.ino
第 6 步:最后的想法和改进
如您所见,即使使用 Arduino Uno,我们也可以为简单游戏构建无与伦比的算法。这个项目很棒,因为它很容易构建,同时也是对人工智能和游戏编程的一个很好的介绍。未来我会尝试使用更强大的树莓派构建一些更高级的人工智能项目,敬请期待!我很想听听你对这个项目的看法。
请在下面发表您的评论,如果您觉得有趣,请不要忘记喜欢本教程。谢谢!
代码
- 代码片段 #1
- 代码片段#2
代码片段 #1纯文本
int firstMoves[]={0,2,6,8}; // 将首先使用这些位置
for(counter=0;counter<4;counter++) //计算第一个动作 { if(board[firstMoves[counter]]!=0) // 第一个动作被某人玩了 { movePlayed++; } } do{ if(moves<=2) { int randomMove =random(4); int c=firstMoves[randomMove];如果(板[c]==0){延迟(1000);板[c]=2; Serial.print(firstMoves[randomMove]); Serial.println(); drawCpuMove(firstMoves[randomMove]); b=1; } }
代码片段#2纯文本
int checkOpponent()
{ if(board[0]==1 &&board[1]==1 &&board[2]==0) return 2; else if(board[0]==1 &&board[1]==0 &&board[2]==1) return 1; else if (board[1]==1 &&board [2]==1 &&board[0]==0) return 0; else if (board[3]==1 &&board[4]==1 &&board[5]==0) return 5; else if (board[4]==1 &&board[5]==1&&board[3]==0) return 3; else if (board[3]==1 &&board[4]==0&&board[5]==1) return 4; else if (board[1]==0 &&board[4]==1&&board[7]==1) return 1;否则返回 100;}
Github
https://github.com/adafruit/Adafruit-GFX-Libraryhttps://github.com/adafruit/Adafruit-GFX-LibraryGithub
https://github.com/adafruit/Touch-Screen-Libraryhttps://github.com/adafruit/Touch-Screen-Library制造工艺