import network
import time
from machine import I2C, Pin
from lcd_i2c import I2cLcd
from umqtt.simple import MQTTClient
import json
MQTT_CLIENT_ID = "esp32_tic_tac_toe_7v_board"
MQTT_BROKER = "broker.mqttdashboard.com"
MQTT_TOPIC = "elsys/v/tic_tac_toe"
AddressOfLcd = 0x27
i2c = I2C(scl=Pin(22), sda=Pin(21), freq=400000)
lcd = I2cLcd(i2c, AddressOfLcd, 4, 20)
current_player = "Player1"
board = [[" " for _ in range(3)] for _ in range(3)]
def process_msg(topic, msg):
global current_player
move = json.loads(msg)
print(move)
if move["type"] == "server":
return
if move["player"] == current_player and validate_move(move):
process_move(move)
current_player = "Player1" if current_player == "Player2" else "Player2"
notify_next_player()
elif move["player"] == current_player:
message = {"type": "server", "player": move["player"], "status": "Invalid move!"}
client.publish(MQTT_TOPIC, json.dumps(message))
else:
message = {"type": "server", "player": move["player"], "status": "Not your turn!"}
client.publish(MQTT_TOPIC, json.dumps(message))
def validate_move(move):
x, y = move["move"]
if 0 <= x < 3 and 0 <= y < 3 and board[x][y] == " ":
return True
return False
def process_move(move):
x, y = move["move"]
symbol = "X" if move["player"] == "Player1" else "O"
board[x][y] = symbol
lcd.move_to(x, y)
lcd.putstr(symbol)
print(board)
if check_win(symbol):
message1 = {"type": "server", "player": "Player1", "status": move["player"] + " " + "won!"}
message2 = {"type": "server", "player": "Player2", "status": move["player"] + " " + "won!"}
client.publish(MQTT_TOPIC, json.dumps(message1))
client.publish(MQTT_TOPIC, json.dumps(message2))
reset_game()
elif check_tie():
message1 = {"type": "server", "player": "Player1", "status": "It's a tie!"}
message2 = {"type": "server", "player": "Player2", "status": "It's a tie!"}
client.publish(MQTT_TOPIC, json.dumps(message1))
client.publish(MQTT_TOPIC, json.dumps(message2))
reset_game()
def check_win(player):
for i in range(3):
if all(board[i][j] == player for j in range(3)) or all(board[j][i] == player for j in range(3)):
return True
if all(board[i][i] == player for i in range(3)) or all(board[i][2 - i] == player for i in range(3)):
return True
return False
def check_tie():
return all(board[i][j] != " " for i in range(3) for j in range(3))
def notify_next_player():
global current_player
message = {"type": "server", "player": current_player, "status": "Your turn!"}
client.publish(MQTT_TOPIC, json.dumps(message))
def reset_game():
global board
board = [[" " for _ in range(3)] for _ in range(3)]
lcd.clear()
client = MQTTClient(MQTT_CLIENT_ID, MQTT_BROKER)
client.set_callback(process_msg)
def connect_to_wifi():
print("Connecting to Wi-Fi", end="")
sta_if = network.WLAN(network.STA_IF)
sta_if.active(True)
sta_if.connect('Wokwi-GUEST', '')
while not sta_if.isconnected():
print(".", end="")
time.sleep(0.1)
print(" Connected!")
def connect_to_mqtt_broker():
connect_to_wifi()
print("Connecting to MQTT server... ", end="")
client.connect()
print("Connected!")
client.subscribe(MQTT_TOPIC)
print("Subscribed to {}".format(MQTT_TOPIC))
def main():
connect_to_mqtt_broker()
while True:
client.wait_msg()
if __name__ == "__main__":
main()