4 Commits

Author SHA1 Message Date
ScriptSorcerer 81d689c1ba Added chess board specification (number and cahracters), aswell as a detail view for the damen 2026-03-26 19:38:56 +01:00
ScriptSorcerer ecfe5c09a8 Simple chessboard design + slove button (shows you the solution with the algorithm) and marks conflicts with damen red.
conflict still has some errors (damen despawn somethimes) and css is very simple.
2026-03-26 11:06:27 +01:00
ScriptSorcerer 10e36d9aee Merge pull request #7 from ScriptSorcerer20/main
Update Dev branch
2026-03-23 13:04:40 +01:00
ScriptSorcerer cb05b091d8 Merge pull request #6 from ScriptSorcerer20/1-design-improvement
added gradients to backgroudn added functional button animation
2026-03-23 12:59:50 +01:00
5 changed files with 377 additions and 26 deletions
Binary file not shown.
+52 -1
View File
@@ -1,4 +1,4 @@
from flask import Blueprint, render_template
from flask import Blueprint, jsonify, render_template, request
from flask_login import login_required, current_user
main_bp = Blueprint("main", __name__)
@@ -11,3 +11,54 @@ def home():
@login_required
def dashboard():
return render_template('dashboard.html', user=current_user)
@main_bp.route("/check", methods=["POST"])
def check():
data = request.json
board = data["board"]
row = data["row"]
col = data["col"]
for r in range(len(board)):
c = board[r]
if c == -1 or r == row:
continue
# gleiche Spalte
if c == col:
return jsonify({"valid": False})
# gleiche Diagonale
if abs(c - col) == abs(r - row):
return jsonify({"valid": False})
return jsonify({"valid": True})
@main_bp.route("/solve")
def solve():
n = 8
solutions = []
board = [-1] * n
def is_safe(row, col):
for r in range(row):
c = board[r]
if c == col or abs(c - col) == abs(r - row):
return False
return True
def backtrack(row):
if row == n:
solutions.append(board[:])
return
for col in range(n):
if is_safe(row, col):
board[row] = col
backtrack(row + 1)
board[row] = -1
backtrack(0)
return jsonify(solutions)
+143
View File
@@ -0,0 +1,143 @@
body {
margin: 0;
font-family: Arial, sans-serif;
background: #f5f7fa;
}
/* 🔝 Navbar */
.navbar {
display: flex;
justify-content: space-between;
align-items: center;
background: #1e293b;
color: white;
padding: 15px 30px;
}
.navbar a {
color: white;
margin-left: 15px;
text-decoration: none;
}
.navbar a:hover {
text-decoration: underline;
}
/* 📦 Layout */
.container {
max-width: 900px;
margin: 30px auto;
padding: 10px;
}
/* 📇 Cards */
.card {
background: white;
padding: 20px;
margin-bottom: 25px;
border-radius: 12px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
}
.game-card {
text-align: center;
}
/* ♟️ Board */
.board-grid {
display: grid;
grid-template-columns: 30px repeat(8, 60px);
grid-template-rows: 30px repeat(8, 60px);
margin: 20px auto;
width: max-content;
border: 6px solid #1e293b;
border-radius: 10px;
overflow: hidden;
}
.label {
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
background: #aec8eb;
color: #1e293b;
}
.cell {
width: 60px;
height: 60px;
display: flex;
align-items: center;
justify-content: center;
font-size: 30px;
cursor: pointer;
transition: 0.2s;
}
.cell:hover {
transform: scale(1.05);
}
.white {
background: #e2e8f0;
}
.black {
background: #475569;
color: white;
}
.invalid {
background: #ef4444 !important;
}
/* 🎛️ Buttons */
.controls {
margin-top: 15px;
}
.btn {
padding: 10px 15px;
margin: 5px;
border: none;
border-radius: 8px;
background: #3b82f6;
color: white;
cursor: pointer;
}
.btn:hover {
background: #2563eb;
}
.btn.secondary {
background: #64748b;
}
.btn.secondary:hover {
background: #475569;
}
.btn.danger {
background: #ef4444;
}
.btn.danger:hover {
background: #dc2626;
}
#queenList {
list-style: none;
padding: 0;
}
#queenList li {
padding: 5px;
background: #f1f5f9;
margin: 4px 0;
border-radius: 6px;
}
+171 -14
View File
@@ -1,31 +1,34 @@
<!DOCTYPE html>
<html lang="en">
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Dashboard</title>
<link rel="stylesheet" href="../static/css/dashboard.css">
</head>
<body>
<nav>
<!-- 🔝 Navbar -->
<nav class="navbar">
<div class="nav-left">♛ 8-Queens App</div>
<div class="nav-right">
<a href="{{ url_for('main.dashboard') }}">Dashboard</a>
<a href="{{ url_for('login.logout') }}">Logout</a>
</div>
</nav>
<!-- 📦 Container -->
<div class="container">
```
<h1>Dashboard</h1>
<p>Welcome back <strong>{{ current_user.username }}</strong> 👋</p>
<!-- 👤 User Card -->
<div class="card">
<h2>👋 Willkommen, {{ current_user.username }}</h2>
<div class="user-info">
<h3>Your Account</h3>
<p><strong>User ID:</strong> {{ current_user.id }}</p>
<p><strong>ID:</strong> {{ current_user.id }}</p>
<p><strong>Username:</strong> {{ current_user.username }}</p>
{% if current_user.email %}
@@ -34,18 +37,172 @@
<p><strong>Email:</strong> Not set</p>
{% endif %}
<p><strong>Account created:</strong> {{ current_user.created_at }}</p>
<p><strong>Erstellt:</strong> {{ current_user.created_at }}</p>
</div>
<div class="logout">
<form action="{{ url_for('login.logout') }}" method="post">
<button type="submit">Logout</button>
<button class="btn danger" type="submit">Logout</button>
</form>
</div>
```
<!-- ♟️ Game Card -->
<div class="card game-card">
<h2>♟️ 8-Damen Spiel</h2>
<div class="board" id="board"></div>
<div class="controls">
<button class="btn" onclick="solve()">Solve</button>
<button class="btn secondary" onclick="resetBoard()">Reset</button>
</div>
</div>
</div>
<script>
let board = Array(8).fill(-1);
const boardDiv = document.getElementById("board");
function getConflicts() {
let conflicts = [];
for (let r1 = 0; r1 < 8; r1++) {
if (board[r1] === -1) continue;
for (let r2 = r1 + 1; r2 < 8; r2++) {
if (board[r2] === -1) continue;
let c1 = board[r1];
let c2 = board[r2];
if (
c1 === c2 ||
Math.abs(c1 - c2) === Math.abs(r1 - r2)
) {
conflicts.push([r1, c1]);
conflicts.push([r2, c2]);
}
}
}
return conflicts;
}
function drawBoard() {
boardDiv.innerHTML = "";
boardDiv.className = "board-grid";
const conflicts = getConflicts();
const letters = ["A", "B", "C", "D", "E", "F", "G", "H"];
for (let row = -1; row < 8; row++) {
for (let col = -1; col < 8; col++) {
const cell = document.createElement("div");
// 🔹 Ecke oben links
if (row === -1 && col === -1) {
cell.classList.add("label");
}
// 🔹 Buchstaben (oben)
else if (row === -1) {
cell.textContent = letters[col];
cell.classList.add("label");
}
// 🔹 Zahlen (links)
else if (col === -1) {
cell.textContent = 8 - row;
cell.classList.add("label");
}
// 🔹 echtes Spielfeld
else {
cell.classList.add("cell");
if ((row + col) % 2 === 0) {
cell.classList.add("white");
} else {
cell.classList.add("black");
}
if (board[row] === col) {
cell.textContent = "♛";
if (conflicts.some(([r, c]) => r === row && c === col)) {
cell.classList.add("invalid");
}
}
cell.onclick = () => placeQueen(row, col);
}
boardDiv.appendChild(cell);
}
}
updateQueenList();
}
function placeQueen(row, col) {
if (board[row] === col) {
board[row] = -1;
} else {
board[row] = col;
}
drawBoard();
updateQueenList();
}
async function solve() {
const res = await fetch("/solve");
const solutions = await res.json();
board = solutions[0];
drawBoard();
}
function resetBoard() {
board = Array(8).fill(-1);
drawBoard();
updateQueenList();
}
drawBoard();
</script>
<div class="card">
<h3>📋 Damen Positionen</h3>
<ul id="queenList"></ul>
</div>
<script>
function updateQueenList() {
const list = document.getElementById("queenList");
list.innerHTML = "";
const letters = ["A", "B", "C", "D", "E", "F", "G", "H"];
let count = 1;
for (let row = 0; row < 8; row++) {
if (board[row] !== -1) {
let col = board[row];
let pos = letters[col] + (8 - row);
const li = document.createElement("li");
li.textContent = `Dame ${count}: ${pos}`;
list.appendChild(li);
count++;
}
}
}
</script>
</body>
</html>
+1 -1
View File
@@ -21,7 +21,7 @@
<nav>
<a href="/">Home</a>
<a href="/solver">Solver</a>
<a href="/dashboard">Solver</a>
{% if session.get('user_id') %}
<a href="/dashboard">Dashboard</a>