首页-达尔闻    全部    项目分享| 自制井字游戏,人机大战谁赢?代码说了算

项目分享| 自制井字游戏,人机大战谁赢?代码说了算

如何设计这个游戏(Arduino Tic-Tac-Toe )吧。

只要有一块Arduino开发板、一个可触摸的显示屏就可以制作了。
收藏
  • 人机大战井字游戏,你猜谁会赢?

    想让谁赢,谁就能赢。为啥?因为程序是人编写的呀。想要知道为什么的,接着往下看,如何设计这个游戏(Arduino Tic-Tac-Toe )吧。

    只要有一块Arduino开发板、一个可触摸的显示屏就可以制作了。不管是新手,还是老手;不管是有孩子的,还是有女朋友的,都可以玩起来了。

    是不是在想用什么人工智能算法?并没有。Arduino 虽然简单易用,但为 Arduino 开发游戏并不容易,而且需要大量时间。

    第1步:获取所需硬件

    此项目所需的硬件如下:

    • Arduino Uno开发板

    • 2.8 英寸触摸屏

    由此可见,搭建这个游戏的成本极低,不会超过100元,如果手头上有现成的就更棒了,拿来就能用。

    第2步:用于 Arduino 的 2.8" 触摸彩色显示屏

    在某宝上,此类屏幕一大把,任君挑选,50元以内搞定。

     

    视频中用的显示屏分辨率为320x240,并且以电路板的形式封装好,这这样屏幕和Arduino之间的连接变得非常容易。电路板另一个优点是提供了一个非常易于使用的 micro SD 插槽。

    显示屏几乎使用了 Arduino Uno 的所有数字和模拟引脚。使用电路连接板就只剩下 2 个数字引脚和 1 个模拟引脚。显示屏也可以与 Arduino Mega 配合使用,因此当需要更多引脚时,可以使用 Arduino Mega 或其他的MCU。

    大家在选用显示屏的时候,需要确认下是否和自己的MCU匹配。比如这个项目中用的显示屏就不适用于 Arduino Due 或 Wemos D1 ESP8266 板。

    第3步:搭建并测试

    将屏幕连接到 Arduino Uno 后,就可以加载代码并准备玩起来。

    首先,按下“开始游戏”按钮,游戏开始。Arduino首先会下第一颗棋子,然后我们只需触摸屏幕即可下棋。成功将三个棋子放置在水平、垂直或对角线中的玩家赢得游戏。游戏结束时,会出现“游戏结束”提示。然后可以按下再次播放按钮,重新开始游戏。

    Arduino非常擅长这个游戏,大部分的比赛它都能赢,除非你是一个高手,才可能以很小的概率赢得比赛或是平局。2 美元的 Arduino CPU 芯片怎么能打败人脑呢?我们开发的程序肯定不会比人脑更聪明的。前面说了,想要让人赢得Arduino,只要在代码里添加两行即可。

    所以,接下来的算法,是游戏的核心所在。

    第4步:游戏算法

    先来看一下视频里实现的算法。

     

    Arduino先下第一手棋(玩过这个游戏的人就知道,先出手会更容易赢得比赛)。Arduino的第一步永远是一个角落,第二步也是剩余的随机角落,根本不关心玩家是怎么放棋子。

     

    从第三步开始,Arduino 就会检查玩家是否可以在下一步中获胜并放置棋子阻止。如果玩家不能在这一步中获胜,Arduino 会在可用的情况下进行角移动,或者从剩余移动中随机移动。就是这样,这个简单的算法每次都可以击败人类玩家,或者在最坏的情况下,游戏平局。这不是最好的井字游戏算法,而是最简单的算法之一。

    井字游戏非常简单,我们可以很容易地分析,所以这个算法很容易在 Arduino 中实现。如果我们设计博弈树状图,就可以发现一些获胜策略并在代码中轻松实现它们,或者我们可以让 CPU 实时计算博弈树并自行选择最佳移动位置。

    第5步:项目代码

    首先,需要三个库来编译代码。

    📥 修改后的Adafruit TFTLCD:

     https://educ8s.tv/wp-content/uploads/2016/11/Adafruit_TFTLCD.zip

    📥 Adafruit GFX:https ://github.com/adafruit/Adafruit-GFX-Library

    📥 触摸屏:https ://github.com/adafruit/Touch-Screen-Library

     

    一直说这是一个非常简单的游戏,但代码却是超过600行了。代码很复杂,这里不多解释了,感兴趣的可以下载学习。(在“达尔闻说微信回复:井字游戏

    这里,为大家展示 Arduino 移动算法的实现。

    首先,我们玩两个随机角。

    int firstMoves[]={0,2,6,8}; // will use these positions first for(counter=0;counter<4;counter++) //Count first moves played { if(board[firstMoves[counter]]!=0) // First move is played by someone { movesPlayed++; } } do{ if(moves<=2) { int randomMove =random(4); int c=firstMoves[randomMove]; if (board[c]==0) { delay(1000); board[c]=2; Serial.print(firstMoves[randomMove]); Serial.println(); drawCpuMove(firstMoves[randomMove]); b=1;      }            }

    接下来,在每一轮中,我们检查玩家是否可以在下一步中获胜。

    <p>int checkOpponent()<br>{ 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; else return 100;}

    如果是,在大多数情况下都会阻止。我们不会为了给人类玩家一个获胜的机会而阻止所有的动作。你能找出哪些动作没有被阻止吗?阻止移动后,我们玩剩余的角落,或随机移动。可以研究代码,轻松实现自己无与伦比的算法。

    第6步:最后的想法和改进

    即使使用 Arduino Uno,我们也可以为简单游戏构建无与伦比的算法。这个项目很有趣,也很容易复制,同时也很好地介绍了人工智能和游戏编程。感兴趣的小伙伴可以试试使用性能更高的控制器实现五子棋的游戏,相信这会是一个不小的挑战哟。

    来源:hackster.io

    作者:Nick Koumaris

Control Render Error!ControlType:productSlideBind,StyleName:Style1,ColorName:Item0,Message:InitError, ControlType:productSlideBind Error:未将对象引用设置到对象的实例。