计算机系统应用教程网站

网站首页 > 技术文章 正文

自制井字游戏,人机大战谁赢?代码说了算

btikc 2024-09-05 12:37:59 技术文章 8 ℃ 0 评论

人机大战井字游戏,你猜谁会赢?



想让谁赢,谁就能赢。为啥?因为程序是人编写的呀。想要知道为什么的,接着往下看,如何设计这个游戏(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 板。

【嵌入式物联网单片机学习资料】整理了全套精华学习资料,除了教程外,还有一些大厂面经+笔试面试题,开源共享给大家。

点击加V自取:加微信领取资料


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

原文链接:https://mp.weixin.qq.com/s/1leWSh71gRaDBnrBKpeTew

文章转载自:达尔闻说

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

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

版权声明:本文来源于网络,免费传达知识,版权归原作者所有,如涉及作品版权问题,请联系我进行删除

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表