Projekt Schiffeversenken
Der Spielcode
In diesem Kapitel wird der Spielcode generiert und in der Datenbanktabelle gespeichert.
Wichtig zum Verständnis:
auf dieser Seite ist der Endzustand der version_03 dokumentiert. Die einzelnen Schritte sind:
- Erstellen Modul
generate_code.py- Aufruf
generate_code.pyin routeroutes.pyfür Spieler 1 einbauen- Speichern des Codes in der Datenbanktabelle
- Implementieren von Beitritt Spieler 2 zum Spiel
- Update der Datenbanktabelle
- Bei Erfolg Weiterleiten an neue Seite
game.html, diese muss dann auch in derroutes.pyaufgenommen werdenEine genauere Beschreibung gibt es in der Projektdoku (Download hier) im gleichnamigen Kapitel.
Îm letzten Kapitel kam ja "nur" die Datei game.html dazu, daher brauchen wir keine neue Version, wir integrieren die nächsten Änderungen in der version_03. Schauen wir uns zuerst wieder die neue Struktur an:
Der Sourcecode für generate_code.py sieht so aus:
import random
from string import ascii_uppercase
from app_init import db
from sqlalchemy import func
from models import Game
# Funktion liefert Großbuchstaben für die übergebene
# Anzahl an Stellen
def gen(length):
gen_code = ""
for _ in range(length):
gen_code += random.choice(ascii_uppercase)
return gen_code
# Funktion schaut nach, ob der generierte Code schon
# vorhanden ist und liefert True oder False zurück
def lookup(gen_code):
valid = True
lookup = Game.query.all()
for item in lookup:
if str(item) == gen_code:
valid = False
break
return valid
#Funktion liefert den generierten Code zurück
def generate_unique_code(length):
generate_new = True
is_valid = False
gen_code = ""
# Testschalter - falls gewünscht, unten einen
# in der DB existierenden Code mitgeben und
# Schalter auf True setzen
test = False
while generate_new:
is_valid = False
while not is_valid:
if test:
#hier einen existierenden Code eingeben
gen_code = "ABCDEF"
test = False
else:
gen_code = gen(length)
is_valid = lookup(gen_code)
if is_valid:
generate_new = False
else:
gen_code = gen(length)
is_valid = lookup(gen_code)
generate_new = False
return gen_code
Die Erweiterung in unserem Backend, also der routes.py, umfasst den Aufruf von generate_code.py und die neue Route für die Seite game.html. Der Code sieht so aus:
from flask import Blueprint, render_template, request, redirect, url_for, session
import generate_code
from app_init import db
from models import Game
# Erstelle ein Blueprint für die Routen
main = Blueprint('main', __name__)
@main.route('/')
def index():
return render_template('index.html')
@main.route("/setup", methods=["GET", "POST"])
def setup():
error = None
board_init = "0000000000" * 10 # 10x10 Spielfeld, initial leer
# Wenn Methode "POST" ist, erwarten wir Formulardaten
if request.method == "POST":
if request.form.get('p1_pressed') == 'True':
p_1_name = request.form.get("p_1_name", "").strip()
# Generiere einen eindeutigen Code
game_code = generate_code.generate_unique_code(6)
new_game = Game(game_code=game_code,
p_1_name=p_1_name,
p_1_board=board_init,
p_1_status="Spiel generiert")
db.session.add(new_game)
db.session.commit()
session["p_actual"] = p_1_name
return redirect(url_for("main.game", game_code=game_code))
# hier könnten wir auch else: setzen, da wir nur bei Klick auf einen
# der beiden Button hier landen
if request.form.get('p2_pressed') == 'True':
p_2_name = request.form.get("p_2_name", "").strip()
game_code = request.form.get("game_code", "").strip()
#Versuch, den Datensatz mit dem angegebenen Code zu finden
existing_game = Game.query.filter_by(game_code=game_code).first()
if not existing_game:
error = f"Ups {p_2_name}, der Code {game_code} existiert nicht"
return render_template(
"setup.html",
error=error,
p_2_name=p_2_name,
game_code=game_code
)
else:
if existing_game.p_1_status != "Spiel generiert":
error = f"Ups {p_2_name}, das Spiel mit dem Code {game_code} ist bereits gestartet"
return render_template(
"setup.html",
error=error,
p_2_name=p_2_name,
game_code=game_code
)
else:
p_1_name = existing_game.p_1_name
game_code = existing_game.game_code
existing_game.p_2_name = p_2_name
existing_game.p_2_board = board_init
existing_game.p_2_status = "Spieler 2 angemeldet"
db.session.commit()
session["p_actual"] = p_2_name
return redirect(url_for("main.game", game_code=game_code))
else:
return render_template(
"setup.html"
)
@main.route("/game/")
def game(game_code):
game_code=game_code
p_actual = session.get("p_actual")
return render_template(
"game.html",
game_code=game_code,
p_actual=p_actual
)
Die neue Seite game.html ist erst einmal nur rudimentär gefüllt und sieht so aus:
{% extends 'base.html' %}
{% block content %}
<div>
<h3>aktueller Spieler ist {{ p_actual }}, Spielcode ist {{ game_code }}
</h3>
</div>
{% endblock %}
Lassen wir es laufen. Spieler Klaus eröffnet das Spiel:
Sprung auf game.html, der redirekt hat geklappt:
Der Eintrag in der Datenbanktabelle hat auch funktioniert:
Kathleen kommt dazu. Wir öffnen dazu den anderen Browser, geben dort http://127.0.0.1:5000 in die Suchleiste ein, Klick auf "Go" und landen auf unserer setup.html:
Der redirekt auf game.html hat auch hier funktioniert:
Auch hier wieder die Kontrolle in der Datenbanktabelle:
Super, das sieht doch gut aus.
Bravo, damit haben wir auch dieses Kapitel erfolgreich abgeschlossen! Dann können wir uns jetzt der Erstellung der Spielfelder widmen.
Inhaltsverzeichnis:
1. Vorwort2. Das Projekt
3. Vorarbeiten
4. Das Projekt „Schiffeversenken“
4.1. Der Funktionsumfang
4.2. Die Planung der Umsetzung
4.3. Das Coden
4.3.1 Arbeiten mit Flask
4.3.2 Die Datenbank
4.3.3 Der Spielstart
4.3.4 Der Spielcode
4.3.5 Die Spielfelder
4.3.6 Setzen der Schiffe
4.3.7 Das Spielen
4.4. Die Veröffentlichung
5. Abschluss







