Flatlogic Bot 88f61bb064 T-1
2025-10-21 19:22:51 +00:00

363 lines
12 KiB
JavaScript

document.addEventListener('DOMContentLoaded', function() {
const playNowButton = document.querySelector('.btn-primary');
if (playNowButton) {
playNowButton.addEventListener('click', function(e) {
e.preventDefault();
document.querySelector('#game-section').scrollIntoView({ behavior: 'smooth' });
});
}
const gameBoard = document.getElementById('game-board');
const resetButton = document.getElementById('reset-button');
const gameStatus = document.getElementById('game-status');
const boardSizeSelect = document.getElementById('board-size-select');
const aiDifficultySelect = document.getElementById('ai-difficulty-select');
const WIN_CONDITION = 4;
const PLAYER_SYMBOL = '🐾';
const AI_SYMBOL = '🧶';
let BOARD_SIZE = 5;
let boardState;
let currentPlayer;
let gameActive;
let cells;
function createBoard(size) {
BOARD_SIZE = size;
gameBoard.innerHTML = '';
gameBoard.className = 'game-board';
gameBoard.classList.add(`size-${size}`);
gameBoard.style.gridTemplateColumns = `repeat(${size}, 1fr)`;
gameBoard.style.gridTemplateRows = `repeat(${size}, 1fr)`;
cells = [];
for (let i = 0; i < size * size; i++) {
const cell = document.createElement('div');
cell.classList.add('game-cell');
const row = Math.floor(i / BOARD_SIZE);
const col = i % BOARD_SIZE;
cell.addEventListener('click', () => handleCellClick(row, col));
gameBoard.appendChild(cell);
cells.push(cell);
}
}
function handleCellClick(row, col) {
if (!gameActive || boardState[row][col] !== null || currentPlayer !== 'PLAYER') {
return;
}
boardState[row][col] = 'PLAYER';
renderBoard();
if (checkWin('PLAYER')) {
endGame('Player');
return;
}
if (isDraw()) {
endGame('Draw');
return;
}
currentPlayer = 'AI';
updateStatus("AI's turn...");
setTimeout(makeAIMove, 500);
}
function makeAIMove() {
if (!gameActive) return;
const difficulty = aiDifficultySelect.value;
let move;
if (difficulty === 'easy') {
move = findRandomMove();
} else if (difficulty === 'medium') {
move = findBestMoveMedium();
} else { // Hard
move = findBestMoveHard();
}
if (move) {
boardState[move.row][move.col] = 'AI';
renderBoard();
if (checkWin('AI')) {
endGame('AI');
return;
}
if (isDraw()) {
endGame('Draw');
return;
}
}
currentPlayer = 'PLAYER';
updateStatus("Your turn!");
}
function findRandomMove() {
let availableCells = [];
for (let i = 0; i < BOARD_SIZE; i++) {
for (let j = 0; j < BOARD_SIZE; j++) {
if (boardState[i][j] === null) {
availableCells.push({ row: i, col: j });
}
}
}
if (availableCells.length > 0) {
return availableCells[Math.floor(Math.random() * availableCells.length)];
}
return null;
}
function findBestMoveMedium() {
// 1. Check if AI can win
for (let i = 0; i < BOARD_SIZE; i++) {
for (let j = 0; j < BOARD_SIZE; j++) {
if (boardState[i][j] === null) {
boardState[i][j] = 'AI';
if (checkWin('AI')) {
boardState[i][j] = null; // Reset
return { row: i, col: j };
}
boardState[i][j] = null; // Reset
}
}
}
// 2. Check if Player is about to win and block
for (let i = 0; i < BOARD_SIZE; i++) {
for (let j = 0; j < BOARD_SIZE; j++) {
if (boardState[i][j] === null) {
boardState[i][j] = 'PLAYER';
if (checkWin('PLAYER')) {
boardState[i][j] = null; // Reset
return { row: i, col: j };
}
boardState[i][j] = null; // Reset
}
}
}
// 3. Otherwise, make a random move
return findRandomMove();
}
function findBestMoveHard() {
let bestScore = -Infinity;
let move = null;
for (let i = 0; i < BOARD_SIZE; i++) {
for (let j = 0; j < BOARD_SIZE; j++) {
if (boardState[i][j] === null) {
boardState[i][j] = 'AI';
let score = evaluateBoard();
boardState[i][j] = null;
if (score > bestScore) {
bestScore = score;
move = { row: i, col: j };
}
}
}
}
return move || findRandomMove(); // Fallback to random if no good move
}
function evaluateBoard() {
let score = 0;
// Prioritize winning moves
if (checkWin('AI')) return 10000;
// Prioritize blocking player's winning moves
if (checkWin('PLAYER')) return -9000;
// Evaluate lines for potential
score += evaluateLinesForPlayer('AI');
score -= evaluateLinesForPlayer('PLAYER');
return score;
}
function evaluateLinesForPlayer(player) {
let score = 0;
const symbol = player;
for (let i = 0; i < BOARD_SIZE; i++) {
for (let j = 0; j < BOARD_SIZE; j++) {
// Horizontal
if (j + WIN_CONDITION <= BOARD_SIZE) {
score += evaluateLine(i, j, 0, 1, symbol);
}
// Vertical
if (i + WIN_CONDITION <= BOARD_SIZE) {
score += evaluateLine(i, j, 1, 0, symbol);
}
// Diagonal (down-right)
if (i + WIN_CONDITION <= BOARD_SIZE && j + WIN_CONDITION <= BOARD_SIZE) {
score += evaluateLine(i, j, 1, 1, symbol);
}
// Diagonal (down-left)
if (i + WIN_CONDITION <= BOARD_SIZE && j - WIN_CONDITION + 1 >= 0) {
score += evaluateLine(i, j, 1, -1, symbol);
}
}
}
return score;
}
function evaluateLine(row, col, dr, dc, player) {
let playerCount = 0;
let emptyCount = 0;
for (let k = 0; k < WIN_CONDITION; k++) {
const current = boardState[row + k * dr][col + k * dc];
if (current === player) {
playerCount++;
} else if (current === null) {
emptyCount++;
}
}
// If the line is blocked by the opponent, it has no potential.
if (playerCount + emptyCount < WIN_CONDITION) {
return 0;
}
// Assign scores based on the number of pieces in a line
if (playerCount === 3 && emptyCount === 1) return 100;
if (playerCount === 2 && emptyCount === 2) return 10;
if (playerCount === 1 && emptyCount === 3) return 1;
return 0;
}
function checkWin(player) {
const symbol = player;
for (let i = 0; i < BOARD_SIZE; i++) {
for (let j = 0; j < BOARD_SIZE; j++) {
// Horizontal
if (j + WIN_CONDITION <= BOARD_SIZE) {
let count = 0;
for (let k = 0; k < WIN_CONDITION; k++) {
if (boardState[i][j + k] === symbol) count++;
}
if (count === WIN_CONDITION) return true;
}
// Vertical
if (i + WIN_CONDITION <= BOARD_SIZE) {
let count = 0;
for (let k = 0; k < WIN_CONDITION; k++) {
if (boardState[i + k][j] === symbol) count++;
}
if (count === WIN_CONDITION) return true;
}
// Diagonal (down-right)
if (i + WIN_CONDITION <= BOARD_SIZE && j + WIN_CONDITION <= BOARD_SIZE) {
let count = 0;
for (let k = 0; k < WIN_CONDITION; k++) {
if (boardState[i + k][j + k] === symbol) count++;
}
if (count === WIN_CONDITION) return true;
}
// Diagonal (down-left)
if (i + WIN_CONDITION <= BOARD_SIZE && j - WIN_CONDITION + 1 >= 0) {
let count = 0;
for (let k = 0; k < WIN_CONDITION; k++) {
if (boardState[i + k][j - k] === symbol) count++;
}
if (count === WIN_CONDITION) return true;
}
}
}
return false;
}
function isDraw() {
return boardState.every(row => row.every(cell => cell !== null));
}
function endGame(winner) {
gameActive = false;
if (winner === 'Draw') {
updateStatus("It's a draw!");
} else {
updateStatus(`${winner} wins!`);
}
}
function resetGame() {
const size = parseInt(boardSizeSelect.value);
createBoard(size);
boardState = Array(BOARD_SIZE).fill(null).map(() => Array(BOARD_SIZE).fill(null));
currentPlayer = 'PLAYER';
gameActive = true;
renderBoard();
updateStatus("Your turn!");
}
function renderBoard() {
cells.forEach((cell, index) => {
const row = Math.floor(index / BOARD_SIZE);
const col = index % BOARD_SIZE;
const state = boardState[row][col];
if (state === 'PLAYER') {
cell.innerHTML = `<div class="symbol">${PLAYER_SYMBOL}</div>`;
} else if (state === 'AI') {
cell.innerHTML = `<div class="symbol">${AI_SYMBOL}</div>`;
} else {
cell.innerHTML = '';
}
});
}
function updateStatus(message) {
gameStatus.textContent = message;
}
if (resetButton) {
resetButton.addEventListener('click', resetGame);
}
if (boardSizeSelect) {
boardSizeSelect.addEventListener('change', resetGame);
}
if(aiDifficultySelect) {
aiDifficultySelect.addEventListener('change', resetGame);
}
resetGame();
const catGallery = document.getElementById('cat-gallery');
if (catGallery) {
fetch('api/pexels.php')
.then(response => response.json())
.then(images => {
images.forEach(image => {
const galleryItem = document.createElement('div');
galleryItem.className = 'cat-gallery-item';
const img = document.createElement('img');
img.src = image.src;
img.alt = 'A cute cat';
const credit = document.createElement('div');
credit.className = 'photographer-credit';
credit.innerHTML = `Photo by <a href="${image.photographer_url}" target="_blank">${image.photographer}</a>`;
galleryItem.appendChild(img);
galleryItem.appendChild(credit);
catGallery.appendChild(galleryItem);
});
})
.catch(error => {
console.error('Error fetching cat images:', error);
catGallery.innerHTML = '<p class="text-center">Could not load cat pictures. Meow-be later?</p>';
});
}
});