Connect 4 - You vs AI Buddy
by SwiftPanda95339 lines9.9 KB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Connect 4 - You vs AI Buddy</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Segoe UI', Roboto, sans-serif;
}
body {
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background: linear-gradient(135deg, #f0f4ff, #e6e9ff);
padding: 20px;
}
.game-container {
background: white;
border-radius: 24px;
padding: 30px 20px;
box-shadow: 0 10px 40px rgba(100, 100, 255, 0.15);
text-align: center;
max-width: 550px;
width: 100%;
}
h1 {
font-size: 2.8rem;
background: linear-gradient(90deg, #ff5e99, #ff9a56);
-webkit-background-clip: text;
color: transparent;
margin-bottom: 8px;
}
.subtitle {
color: #888;
font-size: 1.1rem;
margin-bottom: 20px;
}
.turn-bar {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 25px;
padding: 12px 20px;
background: #f8f9ff;
border-radius: 16px;
}
.player-tag {
display: flex;
align-items: center;
gap: 8px;
font-weight: 600;
color: #555;
}
.dot {
width: 24px;
height: 24px;
border-radius: 50%;
}
.dot.you { background: #ff5252; }
.dot.buddy { background: #ffc107; }
.turn-text {
font-size: 1rem;
color: #555;
font-weight: 500;
}
/* Game Board */
.board {
display: grid;
grid-template-columns: repeat(7, 1fr);
gap: 10px;
background: linear-gradient(180deg, #6366f1, #8b5cf6);
padding: 18px;
border-radius: 16px;
margin: 0 auto 25px;
max-width: 480px;
}
.cell {
aspect-ratio: 1;
background: rgba(255,255,255,0.2);
border-radius: 50%;
position: relative;
cursor: pointer;
transition: background 0.2s;
}
.cell:hover {
background: rgba(255,255,255,0.35);
}
.piece {
position: absolute;
width: 85%;
height: 85%;
left: 7.5%;
top: 7.5%;
border-radius: 50%;
box-shadow: inset 0 3px 6px rgba(0,0,0,0.2);
animation: drop 0.4s ease-out forwards;
}
.piece.player { background: radial-gradient(circle at 30% 30%, #ff7b7b, #ff3838); }
.piece.ai { background: radial-gradient(circle at 30% 30%, #ffdd70, #ffc107); }
@keyframes drop {
0% { transform: translateY(-500px); opacity: 0; }
100% { transform: translateY(0); opacity: 1; }
}
/* Buttons & Messages */
.message {
font-size: 1.3rem;
font-weight: 600;
color: #6366f1;
margin-bottom: 20px;
min-height: 2rem;
}
#restartBtn {
padding: 14px 36px;
font-size: 1.1rem;
font-weight: 600;
border: none;
border-radius: 12px;
background: linear-gradient(90deg, #ff7eb3, #ff758c);
color: white;
cursor: pointer;
transition: transform 0.2s, box-shadow 0.2s;
}
#restartBtn:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(255, 117, 140, 0.4);
}
/* Mobile Responsive */
@media (max-width: 480px) {
h1 { font-size: 2rem; }
.board { gap: 6px; padding: 12px; }
.turn-bar { padding: 10px; font-size: 0.9rem; }
}
</style>
</head>
<body>
<div class="game-container">
<h1>Connect 4</h1>
<p class="subtitle">You vs AI Buddy 🤝</p>
<div class="turn-bar">
<div class="player-tag">
<div class="dot you"></div>
<span>You</span>
</div>
<div class="turn-text" id="turnText">Your turn! Drop a piece 😊</div>
<div class="player-tag">
<span>AI Buddy 🤖</span>
<div class="dot buddy"></div>
</div>
</div>
<div class="board" id="board"></div>
<div class="message" id="message"></div>
<button id="restartBtn">Restart Game</button>
</div>
<script>
// Game Settings
const ROWS = 6;
const COLS = 7;
let board = [];
let currentPlayer = 'player';
let gameOver = false;
const boardEl = document.getElementById('board');
const turnText = document.getElementById('turnText');
const messageEl = document.getElementById('message');
const restartBtn = document.getElementById('restartBtn');
// Start New Game
function initGame() {
board = Array(ROWS).fill().map(() => Array(COLS).fill(null));
currentPlayer = 'player';
gameOver = false;
messageEl.textContent = '';
turnText.textContent = 'Your turn! Drop a piece 😊';
renderBoard();
}
// Draw Game Board
function renderBoard() {
boardEl.innerHTML = '';
for (let r = 0; r < ROWS; r++) {
for (let c = 0; c < COLS; c++) {
const cell = document.createElement('div');
cell.classList.add('cell');
cell.dataset.col = c;
if (board[r][c]) {
const piece = document.createElement('div');
piece.classList.add('piece', board[r][c]);
cell.appendChild(piece);
}
if (!gameOver && currentPlayer === 'player') {
cell.addEventListener('click', () => handleColClick(c));
}
boardEl.appendChild(cell);
}
}
}
// Handle Player Move
function handleColClick(col) {
if (gameOver || currentPlayer !== 'player') return;
const row = getAvailableRow(col);
if (row === -1) return;
dropPiece(row, col, 'player');
if (checkWin(row, col, 'player')) {
endGame('🎉 You win! AI Buddy is sad 😢');
return;
}
if (isBoardFull()) {
endGame('🤝 It\'s a draw!');
return;
}
currentPlayer = 'ai';
turnText.textContent = 'AI Buddy is thinking... 🤔';
setTimeout(aiMove, 700);
}
// Find Empty Row
function getAvailableRow(col) {
for (let r = ROWS - 1; r >= 0; r--) {
if (!board[r][col]) return r;
}
return -1;
}
// Place Piece
function dropPiece(row, col, player) {
board[row][col] = player;
renderBoard();
}
// Check Win Condition
function checkWin(row, col, player) {
const directions = [[0,1],[1,0],[1,1],[1,-1]];
for (let [dr, dc] of directions) {
let count = 1;
for (let i=1; i<4; i++) {
const r = row + dr*i, c = col + dc*i;
if (r>=0 && r<ROWS && c>=0 && c<COLS && board[r][c]===player) count++;
else break;
}
for (let i=1; i<4; i++) {
const r = row - dr*i, c = col - dc*i;
if (r>=0 && r<ROWS && c>=0 && c<COLS && board[r][c]===player) count++;
else break;
}
if (count >=4) return true;
}
return false;
}
// Check Full Board
function isBoardFull() {
return board[0].every(cell => cell !== null);
}
// End Game
function endGame(text) {
gameOver = true;
messageEl.textContent = text;
turnText.textContent = 'Game Over!';
}
// AI Logic
function aiMove() {
let move = findWinningMove('ai');
if (move === -1) move = findWinningMove('player');
if (move === -1) move = chooseSmartColumn();
const row = getAvailableRow(move);
dropPiece(row, move, 'ai');
if (checkWin(row, move, 'ai')) {
endGame('😜 AI Buddy wins! Try again?');
return;
}
if (isBoardFull()) {
endGame('🤝 It\'s a draw!');
return;
}
currentPlayer = 'player';
turnText.textContent = 'Your turn! Drop a piece 😊';
}
// Find Winning Move
function findWinningMove(player) {
for (let c=0; c<COLS; c++) {
const r = getAvailableRow(c);
if (r === -1) continue;
board[r][c] = player;
const win = checkWin(r, c, player);
board[r][c] = null;
if (win) return c;
}
return -1;
}
// Smart Column Selection
function chooseSmartColumn() {
const priority = [3,2,4,1,5,0,6];
for (let c of priority) {
if (getAvailableRow(c) !== -1) return c;
}
return 0;
}
restartBtn.addEventListener('click',Game Source: Connect 4 - You vs AI Buddy
Creator: SwiftPanda95
Libraries: none
Complexity: complex (339 lines, 9.9 KB)
The full source code is displayed above on this page.
Remix Instructions
To remix this game, copy the source code above and modify it. Add a ARCADELAB header at the top with "remix_of: connect-4-you-vs-ai-buddy-swiftpanda95" to link back to the original. Then publish at arcadelab.ai/publish.