Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 81d689c1ba | |||
| ecfe5c09a8 | |||
| 10e36d9aee | |||
| cb05b091d8 |
Binary file not shown.
@@ -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
|
from flask_login import login_required, current_user
|
||||||
|
|
||||||
main_bp = Blueprint("main", __name__)
|
main_bp = Blueprint("main", __name__)
|
||||||
@@ -11,3 +11,54 @@ def home():
|
|||||||
@login_required
|
@login_required
|
||||||
def dashboard():
|
def dashboard():
|
||||||
return render_template('dashboard.html', user=current_user)
|
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)
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
+181
-24
@@ -1,51 +1,208 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
|
<html lang="de">
|
||||||
<html lang="en">
|
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>Dashboard</title>
|
<title>Dashboard</title>
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="../static/css/dashboard.css">
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<nav>
|
<!-- 🔝 Navbar -->
|
||||||
<a href="{{ url_for('main.dashboard') }}">Dashboard</a>
|
<nav class="navbar">
|
||||||
<a href="{{ url_for('login.logout') }}">Logout</a>
|
<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>
|
</nav>
|
||||||
|
|
||||||
|
<!-- 📦 Container -->
|
||||||
<div class="container">
|
<div class="container">
|
||||||
|
|
||||||
```
|
<!-- 👤 User Card -->
|
||||||
<h1>Dashboard</h1>
|
<div class="card">
|
||||||
|
<h2>👋 Willkommen, {{ current_user.username }}</h2>
|
||||||
|
|
||||||
<p>Welcome back <strong>{{ current_user.username }}</strong> 👋</p>
|
<div class="user-info">
|
||||||
|
<p><strong>ID:</strong> {{ current_user.id }}</p>
|
||||||
|
<p><strong>Username:</strong> {{ current_user.username }}</p>
|
||||||
|
|
||||||
<div class="user-info">
|
{% if current_user.email %}
|
||||||
<h3>Your Account</h3>
|
<p><strong>Email:</strong> {{ current_user.email }}</p>
|
||||||
|
{% else %}
|
||||||
|
<p><strong>Email:</strong> Not set</p>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
<p><strong>User ID:</strong> {{ current_user.id }}</p>
|
<p><strong>Erstellt:</strong> {{ current_user.created_at }}</p>
|
||||||
<p><strong>Username:</strong> {{ current_user.username }}</p>
|
</div>
|
||||||
|
|
||||||
{% if current_user.email %}
|
|
||||||
<p><strong>Email:</strong> {{ current_user.email }}</p>
|
|
||||||
{% else %}
|
|
||||||
<p><strong>Email:</strong> Not set</p>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
<p><strong>Account created:</strong> {{ current_user.created_at }}</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="logout">
|
|
||||||
<form action="{{ url_for('login.logout') }}" method="post">
|
<form action="{{ url_for('login.logout') }}" method="post">
|
||||||
<button type="submit">Logout</button>
|
<button class="btn danger" type="submit">Logout</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</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>
|
</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>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
<nav>
|
<nav>
|
||||||
<a href="/">Home</a>
|
<a href="/">Home</a>
|
||||||
<a href="/solver">Solver</a>
|
<a href="/dashboard">Solver</a>
|
||||||
|
|
||||||
{% if session.get('user_id') %}
|
{% if session.get('user_id') %}
|
||||||
<a href="/dashboard">Dashboard</a>
|
<a href="/dashboard">Dashboard</a>
|
||||||
|
|||||||
Reference in New Issue
Block a user