Arduino Dueで作るタッチスクリーン三目並べゲーム
必要な部品
| 部品 | 数量 |
|---|---|
| Arduino Due | 1 |
| 2.8インチTFT LCD(タッチスクリーン付き、ILI9341等) | 1 |
| ジャンパーワイヤ | 1式 |
必要なライブラリ
- Adafruit GFX Library
- Adafruit ILI9341 Library
- URTouch Library
配線
タッチスクリーン側
| タッチピン | Arduino Dueピン |
|---|---|
| T_IRQ | 22 |
| T_DO | 24 |
| T_DIN | 26 |
| T_CS | 28 |
| T_CLK | 30 |
ディスプレイ側
| ディスプレイピン | Arduino Dueピン |
|---|---|
| SDO (MISO) | A25 |
| LED (バックライト) | 3.3V |
| SCK | A27 |
| SDI (MOSI) | A26 |
| DC | 9 |
| RESET | 8 |
| CS | 10 |
| GND | GND |
| VCC | 3.3V |

プロジェクト概要
Nickthegreek82氏の「Arduino Touch Tic Tac Toe Game」をベースに、AIを強化しコードを最適化した版です。2.8インチタッチスクリーン上でCPUと対戦できます。
開発履歴
- 2017/08/22:AI改良とコード最適化
- 2017/08/26:さらなるコード最適化
- 2017/08/27:CPUに勝てるか挑戦!
- 2018/03/13:より良いAIアルゴリズムを採用(klauscam氏の実装を参考)
実装されている2つのバージョン
バージョン1:基本版(TIC TAC TOE)
- シンプルな防御的AI:
- CPUが先手なら角(0,2,6,8)をランダム選択
- 2手目で中央(4)が空いていれば取得
- 以降:CPUの2手完成→阻止、プレイヤーの2手完成→ブロック、それ以外はランダム
- タッチボタンで「先手/後手」選択、「もう一度」でリプレイ
バージョン2:強化版(TicTacToe_new - ミニマックスAI)
- ミニマックス法(Minimax)を実装し、完全な読み切りAIを実現
- 再帰的に全手を探索し、最善手を選択
difficultyパラメータで探索深度を制限可能(デフォルト8=ほぼ全探索)- 盤面評価:CPU勝ち=+1、プレイヤー勝ち=-1、引き分け=0
- 理論上CPUに勝つことは不可能(引き分けが最善)
- 描画ルーチンを自前の
drawBitmap()で最適化
主要コード構成(強化版)
盤面管理
int board[9] = {0,0,0,0,0,0,0,0,0}; // 0=空, 1=CPU(○), -1=プレイヤー(×)
勝利判定
int win(const int board[9]) {
unsigned wins[8][3] = {{0,1,2},{3,4,5},{6,7,8},{0,3,6},{1,4,7},{2,5,8},{0,4,8},{2,4,6}};
for (int i=0; i<8; ++i) {
if (board[wins[i][0]] != 0 &&
board[wins[i][0]] == board[wins[i][1]] &&
board[wins[i][0]] == board[wins[i][2]])
return board[wins[i][2]];
}
return 0;
}
ミニマックス探索
int minimax(int board[9], int player, int depth) {
int winner = win(board);
if (winner != 0) return winner * player; // 視点統一
int move = -1, score = -2;
for (int i=0; i<9; ++i) {
if (board[i] == 0) {
board[i] = player;
int thisScore = (depth < difficulty) ? -minimax(board, -player, depth+1) : 0;
board[i] = 0;
if (thisScore > score) { score = thisScore; move = i; }
}
}
return (move == -1) ? 0 : score;
}
CPU手選択
void computerMove(int board[9]) {
int move = -1, score = -2;
for (int i=0; i<9; ++i) {
if (board[i] == 0) {
board[i] = 1;
int tempScore = -minimax(board, -1, 0);
board[i] = 0;
if (tempScore > score) { score = tempScore; move = i; }
}
}
board[move] = 1;
drawCpuMove(move);
}
タッチ入力処理
void playerMove(int board[9]) {
int move = 0; bool wait = true;
do {
if (myTouch.dataAvailable()) {
myTouch.read();
x = myTouch.getX(); y = myTouch.getY();
// 9マスの座標判定(各セル約70×70ピクセル)
if (x>55 && x<125 && y>0 && y<80 && board[0]==0) { move=0; wait=false; }
// ... 他8マス同様 ...
}
} while (wait);
board[move] = -1;
drawPlayerMove(move);
}
ビットマップ描画(PROGMEM格納)
○(赤)と×(青)を65×65ピクセルのビットマップとしてフラッシュメモリに格納し、drawBitmap()で高速描画。
遊び方
- 起動時「Gamestart」ボタンをタッチ
- 「YOU」で先手、「CPU」で後手を選択
- 3×3グリッドの任意のセルをタッチして×を置く
- CPUが自動で○を置く
- 勝敗または引き分けで「GAME OVER」表示、「Again?」でリプレイ
カスタマイズのヒント
difficultyを下げるとCPUを弱くできる(初心者向け)- ビットマップデータを差し替えて駒のデザイン変更可能
- 盤面サイズ・色・フォントを変更して見た目をカスタマイズ
- サウンド機能(ブザー)を追加して効果音をつける
製造プロセス
- 名刺サイズPCBで作る4×4三目並べゲーム - 設計・製作・プログラミングガイド
- K30 CO2センサで室内空気質をリアルタイム監視する
- 1SheeldとArduinoで盲ろう者のコミュニケーションを支援する
- スマート貯金箱を作ろう:Arduino Nanoでコインアクセプターを制御
- ArduinoでBluetooth経由でLEDを制御 – シンプルDIYガイド
- DFRobot静電容量式指紋センサーをArduino/ESP8266で使う – 登録・認証・削除の完全ガイド
- Arduino MegaとNextion HMIで作る高機能ウェザーステーション
- Arduinoベースのヌンチャク操作6自由度ロボットアームキット
- Arduino UNOとEthernetシールドで太陽放射を測定する自作ピラノメーター
- コンパクトなArduinoレーダーシステム – HC-SR04超音波センサー & 1.8インチST7735ディスプレイ搭載
- Arduinoで楽器演奏:音階生成のステップバイステップガイド