Skip to content

Instantly share code, notes, and snippets.

@hermesthecat
Created February 1, 2025 07:14
Show Gist options
  • Save hermesthecat/41bd9a49e839a9b92d486637595bd5dd to your computer and use it in GitHub Desktop.
Save hermesthecat/41bd9a49e839a9b92d486637595bd5dd to your computer and use it in GitHub Desktop.
autonomous snake game - claude 3.5 sonnet. javascript.
<!DOCTYPE html>
<html lang="tr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Çift Yılan Oyunu - A. Kerem Gök</title>
<style>
body {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
margin: 0;
background-color: #2c3e50;
}
canvas {
border: 2px solid #fff;
background-color: #34495e;
}
.score {
color: white;
font-size: 24px;
margin: 10px 0;
font-family: Arial, sans-serif;
}
</style>
</head>
<body>
<div class="score">Yılan 1: <span id="score1">0</span> | Yılan 2: <span id="score2">0</span></div>
<canvas id="gameCanvas" width="600" height="400"></canvas>
<script>
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
// Yılanlar için sınıf oluşturma
class Snake {
constructor(x, y, color) {
this.body = [
{x: x, y: y},
{x: x - 10, y: y},
{x: x - 20, y: y}
];
this.color = color;
this.direction = 'right';
this.score = 0;
}
// Akıllı hareket sistemi
move() {
const head = {x: this.body[0].x, y: this.body[0].y};
// Diğer yılanın konumunu al
const otherSnake = this === snake1 ? snake2 : snake1;
// En yakın yılan parçasının mesafesini hesapla
let minDistance = Infinity;
otherSnake.body.forEach(segment => {
const distance = Math.sqrt(
Math.pow(head.x - segment.x, 2) +
Math.pow(head.y - segment.y, 2)
);
minDistance = Math.min(minDistance, distance);
});
// Yem yönünü hesapla
const foodDirection = {
x: food.x - head.x,
y: food.y - head.y
};
// Yeme olan mesafeyi hesapla
const foodDistance = Math.sqrt(
Math.pow(foodDirection.x, 2) +
Math.pow(foodDirection.y, 2)
);
// Mevcut yönü tersine çeviren yön sözlüğü
const oppositeDir = {
'up': 'down',
'down': 'up',
'left': 'right',
'right': 'left'
};
// Duvar yakınlığını kontrol et
const wallProximity = {
up: head.y < 30,
down: head.y > canvas.height - 30,
left: head.x < 30,
right: head.x > canvas.width - 30
};
// Yön seçimi için puanlama sistemi
const directionScores = {
up: 0,
down: 0,
left: 0,
right: 0
};
// Yem duvar dibinde mi kontrol et
const foodNearWall = (
food.x < 30 || food.x > canvas.width - 30 ||
food.y < 30 || food.y > canvas.height - 30
);
// Gelişmiş yem puanlaması (duvar dibindeyse daha yüksek puan)
const foodWeight = foodNearWall ? 300 / (foodDistance + 1) : 150 / (foodDistance + 1);
if (Math.abs(foodDirection.x) > Math.abs(foodDirection.y)) {
directionScores.right += foodDirection.x > 0 ? foodWeight : 0;
directionScores.left += foodDirection.x < 0 ? foodWeight : 0;
} else {
directionScores.down += foodDirection.y > 0 ? foodWeight : 0;
directionScores.up += foodDirection.y < 0 ? foodWeight : 0;
}
// Diğer yılandan kaçınma puanlaması
const snakeAvoidanceWeight = 150 / (minDistance + 1);
['up', 'down', 'left', 'right'].forEach(dir => {
let testHead = {x: head.x, y: head.y};
switch(dir) {
case 'up': testHead.y -= 10; break;
case 'down': testHead.y += 10; break;
case 'left': testHead.x -= 10; break;
case 'right': testHead.x += 10; break;
}
// O yöne gidersek diğer yılana olan mesafeyi hesapla
let wouldCollide = false;
otherSnake.body.forEach(segment => {
if (testHead.x === segment.x && testHead.y === segment.y) {
wouldCollide = true;
}
});
// Çarpışma olacaksa o yönü cezalandır
if (wouldCollide) {
directionScores[dir] -= 1000;
}
// Yakınsa o yönden kaçın
else if (minDistance < 50) {
directionScores[dir] -= snakeAvoidanceWeight;
}
});
// Duvar yakınlığı kontrolü (yem duvar dibindeyse görmezden gel)
if (!foodNearWall) {
Object.keys(wallProximity).forEach(dir => {
if (wallProximity[dir]) {
directionScores[dir] -= 3;
}
});
}
// Mevcut yönün tersine gitmeyi engelle
directionScores[oppositeDir[this.direction]] = -10;
// En yüksek puanlı yönü seç
let bestDirection = this.direction;
let maxScore = -Infinity;
Object.keys(directionScores).forEach(dir => {
if (directionScores[dir] > maxScore) {
maxScore = directionScores[dir];
bestDirection = dir;
}
});
// Sıkışma durumundan kurtulma
if (maxScore < -500) { // Eğer tüm yönler tehlikeli ise
const directions = ['up', 'down', 'left', 'right']
.filter(dir => dir !== oppositeDir[this.direction]);
bestDirection = directions[Math.floor(Math.random() * directions.length)];
}
this.direction = bestDirection;
// Yön'e göre hareket
switch(this.direction) {
case 'up': head.y -= 10; break;
case 'down': head.y += 10; break;
case 'left': head.x -= 10; break;
case 'right': head.x += 10; break;
}
// Duvar çarpışma kontrolü
if (head.x < 0 || head.x >= canvas.width ||
head.y < 0 || head.y >= canvas.height) {
// Yılanı başlangıç konumuna resetle
this.body = [
{x: Math.floor(Math.random() * (canvas.width / 10)) * 10,
y: Math.floor(Math.random() * (canvas.height / 10)) * 10},
{x: this.body[0].x - 10, y: this.body[0].y},
{x: this.body[0].x - 20, y: this.body[0].y}
];
this.score = Math.max(0, this.score - 50); // Ceza puanı
return;
}
this.body.unshift(head);
this.body.pop();
}
// Yılanı çizme
draw() {
ctx.fillStyle = this.color;
this.body.forEach(segment => {
ctx.fillRect(segment.x, segment.y, 9, 9);
});
}
// Çarpışma kontrolü
checkCollision(food) {
const head = this.body[0];
if (head.x === food.x && head.y === food.y) {
this.grow();
this.score += 10;
return true;
}
return false;
}
// Yılanı büyütme
grow() {
const tail = this.body[this.body.length - 1];
this.body.push({x: tail.x, y: tail.y});
}
}
// Oyun değişkenleri
const snake1 = new Snake(100, 100, '#e74c3c');
const snake2 = new Snake(400, 300, '#2ecc71');
let food = generateFood();
const scoreElement1 = document.getElementById('score1');
const scoreElement2 = document.getElementById('score2');
// Yem oluşturma fonksiyonu
function generateFood() {
return {
x: Math.floor(Math.random() * (canvas.width / 10)) * 10,
y: Math.floor(Math.random() * (canvas.height / 10)) * 10
};
}
// Yem çizme
function drawFood() {
ctx.fillStyle = '#f1c40f';
ctx.fillRect(food.x, food.y, 9, 9);
}
// Ana oyun döngüsü
function gameLoop() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Yılanların hareketi ve çizimi
snake1.move();
snake2.move();
// Yem kontrolü
if (snake1.checkCollision(food) || snake2.checkCollision(food)) {
food = generateFood();
}
// Skor güncelleme
scoreElement1.textContent = snake1.score;
scoreElement2.textContent = snake2.score;
// Çizimler
drawFood();
snake1.draw();
snake2.draw();
setTimeout(gameLoop, 50); // Oyun hızı 2 katına çıkarıldı
}
// Oyunu başlat
gameLoop();
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment