Arduino 触摸屏井字棋游戏:分步制作教程
零部件清单
| 组件 | 数量 |
|---|---|
| Arduino UNO | 1 |
| 2.8 英寸触摸屏 | 1 |
所需软件
- Arduino IDE
项目简介
欢迎来到另一个 Arduino 教程!今天我们将构建一个基于触摸屏的井字棋游戏,人类玩家将与电脑对战。虽然这个简单游戏不会用到复杂的 AI 算法,但它是理解游戏编程和人工智能原理的绝佳入门项目。
为 Arduino 开发游戏并不容易,需要投入大量时间。但制作简单游戏不仅有趣,还能让我们探索更高级的编程主题,如人工智能算法。这是一个极好的学习体验,完成后你还将拥有一个适合孩子玩耍的小游戏!
第一步:准备所有零件
项目所需零件如下:
- Arduino Uno ×1
- 2.8 英寸触摸屏 ×1
项目成本非常低,仅约 15 美元。开始前建议观看我准备的触摸屏介绍视频,帮助你理解代码并校准触摸屏。
第二步:了解 2.8 英寸触摸彩屏
这款触摸屏来自 banggood.com,价格约 11 美元。分辨率为 320×240 像素,采用扩展板形式,与 Arduino Uno 连接极其简单。但请注意:该扩展板会占用几乎所有数字和模拟引脚,仅剩 2 个数字引脚和 1 个模拟引脚可用。好在它也兼容 Arduino Mega,需要更多引脚时可改用 Mega。但不兼容 Arduino Due 或 Wemos D1 ESP8266。另一个优势是板载 micro SD 卡槽,使用非常方便。
第三步:组装与测试
将屏幕连接到 Arduino Uno,上传代码即可开始游戏。首先点击“开始游戏”按钮,电脑先行。玩家通过触摸屏落子,随后电脑落子,以此类推。率先在横、竖、对角线连成三子者获胜。游戏结束后会出现“游戏结束”界面,点击“再玩一次”可重新开始。
电脑在这个游戏中表现极强,大多时候会获胜,即便你是高手也只能打平。我特意在算法中加入了一些“失误”,给人类玩家获胜机会。只需在代码中添加两行,就能让 Arduino 变得“不败”。一个 2 美元的芯片为何能战胜人脑?我们编写的程序真的比人脑更聪明吗?
第四步:游戏算法解析
电脑总是先手,且首步必走角落。第二步从剩余角落随机选择,完全不理会玩家落子。此后每一步,电脑首先检查玩家下一步能否获胜,若能则拦截;若不能,则优先占据剩余角落,否则随机落子。这个简单算法就能让电脑每局必胜或打平。
之所以能轻松实现,是因为井字棋游戏状态空间极小,我们可以轻松分析并找出必胜策略。若尝试为国际象棋设计类似算法,即使最快的超级计算机也要计算上千年!复杂游戏需要完全不同的方法——人工智能算法和强大算力。未来视频会详细探讨。
第五步:项目代码
代码需要三个库:
- 修改版 Adafruit TFTLCD
- Adafruit GFX
- Touchscreen
即使是这么简单的游戏,代码也超过 600 行。这里只展示核心算法实现:
前两步随机占角
int firstMoves[] = {0, 2, 6, 8}; // 角落位置索引
for (counter = 0; counter < 4; counter++) {
if (board[firstMoves[counter]] != 0) movesPlayed++;
}
do {
if (moves <= 2) {
int randomMove = random(4);
int c = firstMoves[randomMove];
if (board[c] == 0) {
delay(1000);
board[c] = 2; // 电脑标记
drawCpuMove(firstMoves[randomMove]);
b = 1;
}
}
} while (!b);
拦截玩家必胜手
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;
else return 100; // 无需拦截
}
检测到玩家必胜手时会拦截,但并非拦截所有情况,以保留人类获胜机会。你能找出哪些情况未被拦截吗?拦截后,电脑会选择剩余角落或随机落子。完整代码已附在教程中。
注意: Banggood 同款屏幕有两种驱动 IC,若上述代码不工作,请将 initDisplay 函数修改为:
void initDisplay() { tft.reset(); tft.begin(0x9341); tft.setRotation(3); }
第六步:总结与改进
即使是 Arduino Uno 这种基础板卡,也能为简单游戏实现“不败”算法。本项目制作简单,却是游戏编程和人工智能的绝佳入门。未来我将尝试用更强大的 Raspberry Pi 构建更高级的 AI 项目,敬请期待!欢迎在评论区分享你的想法。
制造工艺
- 国际象棋:从古代起源到现代制造的专家概览
- Arduino Nano 与 MPU-6050 构建实时陀螺仪游戏
- 用 Arduino UNO 和 OLED 显示屏制作经典 Pong 游戏:分步教程
- 用 Arduino 制作便携电容触控钢琴:分步指南
- DIY Arduino USB 游戏手柄 — 自制高性能游戏手柄
- 用 Arduino Nano 与 MAX7219 制作 24×16 LED Pong 游戏机
- Arduino 触控打砖块:在 2.4 英寸 TFT LCD 上重现经典街机
- 自制巨型乐高迷你人偶动画操作游戏:Arduino 控制舵机与音效
- Pixel Chaser:Arduino Nano 单键 NeoPixel 追逐小游戏
- Arduino 自动化 Chrome 恐龙游戏 - LDR 光敏电阻 + Python 实现全自动跳跃
- Arduino 电容式触控开关:一枚硬币点亮 LED 的极简 DIY
- DIY LED 轮盘赌游戏机 —— Arduino Nano 打造单人桌面街机