/**
* @file serialVersion.ino
* @brief 시리얼 모니터를 이용한 3x3 슬롯 머신 게임
*
* [동작 순서]
* 1. 시작(1), 멈춤(2), 리셋(3) 선택지를 사용자에게 보여줌
* 2. 시작 시 2.5초부터 0초까지 카운트다운 (시리얼 모니터에 표시)
* 3. 0초가 되면 3x3 격자에 랜덤한 단어 출력
* 4. 가로, 세로, 대각선 일치 여부 판별 후 결과 출력 (당첨! 또는 꽝)
* 5. 다시 선택지 메뉴 출력
*/
#include <Arduino.h>
// --- 설정 및 상수 ---
const unsigned long COUNTDOWN_MS = 2500;
const unsigned long UPDATE_INTERVAL_MS = 500;
const int GRID_SIZE = 3;
// 슬롯에 사용할 심볼들
const char* symbols[] = {"체리", "레몬", "사과", "포도", "7!!", "스타"};
const int numSymbols = 6;
// --- 상태 정의 ---
enum GameState {
STATE_MENU,
STATE_COUNTDOWN,
STATE_RESULT
};
GameState currentState = STATE_MENU;
unsigned long stateStartTime = 0;
String symbolsGrid[GRID_SIZE][GRID_SIZE];
// --- 함수 선언 ---
void showMenu();
void handleSerialInput();
void runCountdown();
void generateAndShowResult();
bool checkWin();
void setup() {
Serial.begin(115200);
randomSeed(analogRead(0)); // 랜덤 시드 초기화
showMenu();
}
void loop() {
handleSerialInput();
switch (currentState) {
case STATE_MENU:
// 입력을 기다림 (handleSerialInput에서 처리)
break;
case STATE_COUNTDOWN:
runCountdown();
break;
case STATE_RESULT:
generateAndShowResult();
currentState = STATE_MENU;
showMenu();
break;
}
}
/**
* @brief 사용자 선택 메뉴를 시리얼 모니터에 출력
*/
void showMenu() {
Serial.println(F("\n=============================="));
Serial.println(F(" [ 슬롯 머신 게임 ]"));
Serial.println(F(" 1. 시작 | 2. 멈춤 | 3. 리셋"));
Serial.println(F("=============================="));
Serial.print(F("선택 > "));
}
/**
* @brief 시리얼 입력을 처리하여 상태 전환
*/
void handleSerialInput() {
if (Serial.available() > 0) {
String input = Serial.readStringUntil('\n');
input.trim();
if (input == "1" || input == "시작") {
if (currentState == STATE_MENU) {
Serial.println(F("\n게임을 시작합니다!"));
currentState = STATE_COUNTDOWN;
stateStartTime = millis();
}
} else if (input == "2" || input == "멈춤") {
Serial.println(F("\n게임을 멈춥니다. 대기 상태로 돌아갑니다."));
currentState = STATE_MENU;
showMenu();
} else if (input == "3" || input == "리셋") {
Serial.println(F("\n게임을 리셋합니다."));
currentState = STATE_MENU;
showMenu();
}
}
}
/**
* @brief 2.5초 카운트다운 로직
*/
void runCountdown() {
static unsigned long lastUpdate = 0;
unsigned long elapsed = millis() - stateStartTime;
if (elapsed >= COUNTDOWN_MS) {
Serial.println(F("0.0! (회전 완료)"));
currentState = STATE_RESULT;
lastUpdate = 0; // 초기화
} else {
// 0.5초마다 카운트다운 출력
if (millis() - lastUpdate >= UPDATE_INTERVAL_MS) {
float remaining = (float)(COUNTDOWN_MS - elapsed) / 1000.0;
Serial.print(remaining, 1);
Serial.println(F("..."));
lastUpdate = millis();
}
}
}
/**
* @brief 3x3 격자 생성 및 결과 출력
*/
void generateAndShowResult() {
Serial.println(F("\n------- [ 결과 ] -------"));
for (int i = 0; i < GRID_SIZE; i++) {
Serial.print(F("| "));
for (int j = 0; j < GRID_SIZE; j++) {
int randIdx = random(numSymbols);
symbolsGrid[i][j] = symbols[randIdx];
Serial.print(symbolsGrid[i][j]);
Serial.print(F(" | "));
}
Serial.println();
}
Serial.println(F("------------------------"));
if (checkWin()) {
Serial.println(F("★ ★ ★ 당첨! 축하합니다! ★ ★ ★"));
} else {
Serial.println(F("꽝! 다음 기회에..."));
}
}
/**
* @brief 가로, 세로, 대각선 일치 여부 확인
* @return 당첨 시 true
*/
bool checkWin() {
// 가로 확인
for (int i = 0; i < GRID_SIZE; i++) {
if (symbolsGrid[i][0] == symbolsGrid[i][1] && symbolsGrid[i][1] == symbolsGrid[i][2]) return true;
}
// 세로 확인
for (int j = 0; j < GRID_SIZE; j++) {
if (symbolsGrid[0][j] == symbolsGrid[1][j] && symbolsGrid[1][j] == symbolsGrid[2][j]) return true;
}
// 대각선 확인
if (symbolsGrid[0][0] == symbolsGrid[1][1] && symbolsGrid[1][1] == symbolsGrid[2][2]) return true;
if (symbolsGrid[0][2] == symbolsGrid[1][1] && symbolsGrid[1][1] == symbolsGrid[2][0]) return true;
return false;
}