Überlege dir erst, welche Daten gespeichert werden sollen. Für all die benötigst du entsprechende Felder (mit einem name-Attribut). Im besten Fall sollten diese auch validiert werden, um zu verhindern, dass nicht erwünschte Daten aufgenommen werden.

In deinem PHP-Skript kannst du die Daten aus den superglobalen Arrays $_POST oder $_GET herauslesen. Je nachdem, über welche Request-Methode du die Formulardaten hast abschicken lassen. Den Wert eines Feldes erhältst du über den Schlüssel, den du im jeweiligen name-Attribut hinterlegt hast.

Auch im PHP-Code sollte eine Wertvalidation erfolgen, da eine clientseitige Validation umgangen werden kann. Du brauchst einen SQL-Query (INSERT INTO), den du mittels Prepared Statement an die Datenbank schicken kannst.

Im folgenden Beispiel wird ein Name in eine MySQL-Datenbanktabelles names geschrieben. Dafür gibt es ein HTML-Formular, welches seine Daten via POST an den Server schickt.

index.php:

<!doctype html>
<head>
  <title>Example</title>
  <meta charset="utf-8">
</head>
<body>
  <form method="post">
    <label for="name">Name:</label>
    <input id="name" name="name" pattern="[A-Z][a-z]+" required>
    <input type="submit">
    <p><?php include_once 'dbinsert.php'; ?></p>
  </form>
</body>

dbinsert.php:

<?php
  function nameIsValid($name) {
    return preg_match('/^[A-Z][a-z]+$/', $name);
  }

  if (!empty($_POST['name']) && nameIsValid($_POST['name'])) {
    $connection = new mysqli('hostname', 'username', 'password', 'database name');

    if ($connection->connect_error) {
      print 'Data could not be saved.';
    }
    else {
      $connection->set_charset('utf8mb4');
      $statement = $connection->prepare('INSERT INTO names (name) VALUES (?)');
      $statement->bind_param('s', $_POST['name']);

      if ($statement->execute()) {
        print 'Success.';
      }
      else {
        print 'Failed.';
      }
    }
  }
?>

Schau zudem in die PHP-Dokumentation. In der werden alle verfügbaren Datenbankschnittstellen (MySQLi, PDO, etc.) aufgeführt. Zu den einzelnen Funktionen findest du oftmals kurze Praxisbeispiele.

...zur Antwort

Zum Inhalt:

  • Der Toggle-Button sollte eine deutsche Beschriftung erhalten.
  • Rechtschreibfehler: Jahresvortgang und fehlendes Komma vor wenn
  • Sind dem von dir angepeilten Zielnutzer wirklich alle Abkürzungen bekannt?
  • Der Text in der roten Box deutet an, dass der Rechner wohl nicht wirklich getestet wurde und prinzipiell wohl als unbrauchbar betrachtet werden kann. Immerhin liegen dem Programm doch keine hochkomplexen Rechenwege vor.
  • Der Rechner berechnet auch dann einen Wert, wenn nicht alle Felder ausgefüllt wurden. Eine bessere Feldvalidation, die im besten Fall sogar das erste Fehlerfeld fokussiert, wäre praktisch.
  • Je nach Zielgruppe wäre es gut, wenn die Seite auch auf einem mobilen Endgerät vernünftig bedienbar wäre.
  • Der Seite fehlt ein Impressum.
  • Du trackst Daten, ohne dir die Einwilligung des Seitenbesuchers zu holen, geschweige denn ihn überhaupt darüber zu informieren.

Zum Design:

  • Der Toggle-Button sollte den gleichen Cursor bei Mouseover erhalten, wie der andere Button.
  • Wieso sind nicht alle Felder auch Nummernfelder (mit einer Begrenzung auf einen validen Zahlenbereich)?
  • Nummernfelder sollten breiter sein, sodass man Eingaben besser sieht.

Zur technischen Umsetzung:

  • Der Wechsel zwischen Hell- und Dunkelmodus ließe sich einfacher mittels CSS-Variablen lösen. Im body-Element erstellst du je Farbe eine Variable mit einem Standardwert. Überall wo du via CSS Farben setzt, referenzierst du nun auf die entsprechende Variable. Zusätzlich legst du eine Regel (z.B. mit dem Klassenselektor dark) an, in der du deinen Variablen die Werte für den Dunkelmodus zuordnest. Bei Klick auf den Button ordnest du dem body-Element die Klasse dark zu oder entfernst sie wieder.
  • Dem HTML-Entity &nbsp; fehlt bei dir stets das abschließende Semikolon.
  • Der alt-Wert von .gms ist unpassend. Er soll einen ädaquaten Textersatz zum Bild liefern. Wenn das Bild eh nur zur Dekoration ist (typisch für Logos), dann lasse den Wert leer.
  • Auf Eingabefeldern des Typs number ist das maxlength-Attribut nicht erlaubt.
  • Ein einheitlicher Stil bei der Benamung von Elementen wäre vorteilhaft. Aktuell verwendest du mal englische Wörter, dann wieder deutsche. Mal beginnen die Namen mit einem Großbuchstaben, dann wieder nicht.
  • Ebenso wären eindeutige, aussagekräftige Namen von Vorteil. Der Name myFunction für eine Funktion, die zwischen Hell- und Dunkelmodus der Seite hin- und herschalten soll, ist beispielsweise ein Negativbeispiel. Ein anderes ist updateGes2 - die Funktion berechnet doch einen Wert für das Fach Mathematik. Im Funktionsnamen kommt diese Information jedoch nicht vor.
  • Die grundsätzliche Umsetzung der Formularbox finde ich nicht gut. Eignen würde sich eine Tabelle (innerhalb eines Formulars). Du bastelst dir stattdessen alles mit Paragraphen, HTML-Entities und br-Elementen zusammen. Für die beiden letztgenannten Elemente wäre CSS die bessere Wahl.
  • Wieso verwendest du durchgehend var zur Deklaration deiner Variablen, statt const oder let?
  • Es gibt keinen Grund, mehrere Timer zu starten. Zum einen sollen die Berechnungen doch erst bei Buttonklick starten. Zum anderen würde selbst wenn ein einziger Timer vollkommen genügen.
  • All die update-Funktionen könnten abstrahiert werden, sodass nur noch eine Funktion benötigt wird. Im Grunde benötigst du zum Zusammenrechnen mehrerer Felder lediglich einen geeigneten Selektor.

Beispiel:

const fields = Array.from(document.querySelectorAll(".math input[type=number]"));
const sum = fields.reduce((partialSum, field) => {
  const value = parseFloat(field.value);
  return partialSum + value;
}, 0);
const average = sum / fields.length;
...zur Antwort

Zum Textinhalt:

  • Pronomen wie uns oder unsere sind falsch. Du bist doch nur eine Person.
  • Es gibt noch weitere einzelne Rechtschreibfehler (bspw. zu Erfahren, fehlende Punkte nach Sätzen - siehe Sektion Ratschläge (...), Kommas vor Bindewörtern)
  • Da du explizit eine Dienstleistung anbietest und die Seite sich an die Öffentlichkeit richtet, ist sie wohl nicht mehr als privat (d.h. von der Impressumspflicht befreit) einzuordnen.

Zum Seitenaufbau / Design:

  • Eine One-Pager würde mehr Sinn machen. Deine beiden Unterseiten bieten zu wenig Inhalt, der zudem bereits auf der Startseite aufgeführt wird.
  • Die Bilder in der zweiten Sektion sind vertikal nicht auf der gleichen Höhe angeordnet.
  • Die Seite hat zu viel Weißraum. Vermutlich möchtest du sie so strecken, um zu kaschieren, wie wenig Inhalt sie eigentlich bietet. Das gelingt m.E. aber nicht.
  • Ein eigenes Favicon wäre nett.

Ich halte die Seite generell für sinnlos. Die wichtigsten Informationen könntest du ebenso in dein GF-Profil schreiben.

...zur Antwort

Bei summary-Elementen handelt es sich (in der Darstellungsform) um Listitems. Daher kannst du ihren Marker entweder über das list-style-type-Property oder über das ::marker-Pseudeoelement (::-webkit-details-marker als Fallback für Safari) definieren.

Beispiel:

summary {
  list-style-type: none;
}

summary::marker,
summary::-webkit-details-marker {
  content: "+";
}

Die Marker agieren allerdings wie Inline-Elemente (deswegen wird so etwas wie ein Hintergrundbild nicht unterstützt) . Dieses Verhalten kann auch nicht geändert werden. Daher wäre es in deinem Fall besser, mit den Pseudoelementen ::after und ::before zu arbeiten.

Beispiel:

summary {
  list-style-type: none;
}

summary::before {
  background: red;
  content: "";
  display: inline-block;
  height: 12px;
  margin-right: 5px;
  width: 12px;
}
Zusätzlich zu diesem Sandwich-Button würde ich in kleiner Schrift unter dem Botton dann noch Menü stehen haben.

Vermutlich ist es hierfür am besten, den Text via ::after-Element zu setzen. Das Pseudoelement selbst kannst du absolut positionieren.

summary {
  position: relative;
}

summary::before {
  /* ... */
}

summary::after {
  content: "Menü";
  font-size: 8px;
  left: 0; /* still needs to be adjusted */
  position: absolute;
  top: 0; /* still needs to be adjusted */
}
...zur Antwort
Wäre es eine korrekte Vorgehensweise wenn ich innerhalb eines wrappers ein GRID-Raster anlege?

Ich frage mich momentan, ob es eine korrekte Vorgehensweise wäre, wenn ich innerhalb eines wrappers ein GRID-Raster anlege?

Das sähe so aus:

.main-content-wrapper {
    margin: 0 auto;
    padding: 0;
    width: 100%;
    max-width: 72em;    
    height: 100%;
    min-height: 100vh;
    overflow: hidden;
    border: 2px dashed #551A8B;
}

.main-content-wrapper {
    display: grid;
    grid:     "main-head main-head" auto
            "navigations navigations" auto
            "main-content main-content" 1fr
            "main-footer main-footer" auto
          / minmax(0, auto); }


<body id="skip-to-top">
    <div class="main-content-wrapper">
        <header role="header" id="main-head">
[ ... ]
    

Ich habe festgestellt, wenn ich body als wrapper nutze, dann entstehen bei ganz schmalen Browserfenster einige Fehler, die u.a. so aussehen das (wenn ich bei den Dev-Tools grid anzeigen lasse) mein grid seitlich rechts vom body und html hinaus wandern würde oder: mein grid bleibt an einem Punkt stehen und nur html & body wird noch schmaler. Daher meine Entscheidung ein weiteres div einzusetzen.

Ist dies richtig? Wie seht ihr das?

Oder sollte ich eher eine Lösung ohne wrapper anstreben, die ganze Seite mit einem dreispaltigen grid lösen?

body {
	display: grid;
		grid-template-columns: [left] minmax(0.45em,1fr) [main] minmax(10em,78em) [right] minmax(0.45em,1fr);
		grid-template-rows: repeat(2,min-content) auto;
		grid-gap: 0;
		}

Die gridfelder rechts und links sind quasi mein Puffer, wenn ich mein Browserfenster zusammenziehe, und wird dann automatisch weniger/ kleiner.

Was wäre die bessere Herangehensweise?

...zum Beitrag

Beide Ansätze sind legitim. Ein eigener Container bietet den Vorteil, einer zusätzlichen Separation.

(...) mein grid seitlich rechts vom body und html hinaus wandern würde (....)

Setze am besten auch die minimale Breite einer Spalte explizit. Entweder auf dem entsprechenden Element, welches in den Grid-Platzhalter eingefügt wird (min-width: 0) oder bei der Grid-Area-Definition (minmax(0, 1fr)).

Die gridfelder rechts und links sind quasi mein Puffer, (...)

Für eine horizontale Zentrierung würde ich einen Container entweder klassisch mit einer Breite sowie margin: 0 auto ausstatten oder ihn in eine Flexbox / ein einspaltiges Grid packen, in dem die Inhalte zentral ausgerichtet werden.

...zur Antwort

Vorweg, um Missverständnisse zu vermeiden: Ich fasse unter dem Begriff sowohl VB Classic, als auch dessen Nachfolger VB.NET zusammen.

Ich würde das Erlernen nur dann empfehlen, wenn du einen konkreten Anwendungsfall vor dir hast, für den du unbedingt VB brauchst. Also, wenn du beispielsweise:

  • bestehende VB-Programme in irgendeiner Form betreuen musst (warten/erweitern/neu schreiben/...)
  • Programmschnittstellen vorliegen hast, die zur Kommunikation nur VB erlauben
  • besonderes Interesse an VB hast (wieso auch immer)

Andernfalls macht es meines Erachtens aus verschiedenen Gründen wenig Sinn.

  • Microsoft selbst hat nur noch wenig Interesse daran, VB wirklich weiterzuentwickeln bzw. neu aufleben zu lassen. Die aktuelle Strategie sieht vor, für VB.NET ein stable design beizubehalten: Die .NET-Technologien, die bisher für VB.NET verfügbar waren (z.B. für die Entwicklung von Desktopanwendungen), bieten nach wie vor Support (auch für die neuesten Features), aber die Sprache selbst verändert sich in ihrer Syntax nicht. Neue Anwendungsfelder von .NET (z.B. Entwicklung von cross-platform UIs) werden für VB.NET eher nicht eingeführt.
  • VB findet immer weniger Einsatz, du triffst es tendenziell eher in Legacy-Software an und es dürfte immer schwerer werden, Support (z.B. in Foren) seitens anderer Entwickler zu finden.
  • Konkurrenztechnologien (z.B. C#, C++, Delphi, Java) erfahren deutlich mehr Support und sind funktional stärker aufgestellt (bspw. durch neue sprachliche Features, einem größeren Pool externer Tools, u.ä.). Das, was VB damals besonders ausgemacht hat (ein einfacher Baukasten, um relativ schnell grafische Oberflächen zusammenzubauen), findest du ebenso bei anderen Programmiersprachen (C#, Delphi, Java, Swift, ...). Ebenso das Argument, relativ leicht erlernbar zu sein, trifft auch auf neue, moderner gestaltete Sprachen zu.
  • Im Vergleich zu sehr populären Sprachen (wie C++, C#, Java, JavaScript) sowie denen, die so in den letzten ~20 Jahren entwickelt wurden (Dart, Golang, Kotlin, Swift, TypeScript, usw.) unterscheidet sich die Syntax VB recht stark. Sie ist etwas klobig und daher schlechter lesbar.
...zur Antwort
Nun wollte ich fragen welches Programm bzw. Engine man dafür am besten benutzt.

Es gibt verschiedene Optionen:

  • MAUI (hat Xamarin spätestens seit Mai abgelöst)
  • AvaloniaUI
  • Eine Webanwendung mit ASP.NET (alternativ mit Blazor)

Als Entwicklungsumgebung würde ich Visual Studio oder JetBrains Rider empfehlen.

Eigentlich dachte ich an Unity ä, aber des ist ja glaub ich eher für Spiele gemacht.

Richtig.

...zur Antwort

Vorweg: Dein Ziel ist nichts, was von heute auf morgen einfach so realisierbar wäre. Du wirst dafür einige Zeit investieren müssen und vor allem auch selbstständig recherchieren. Ich gebe im Folgenden nur Ansatzpunkte.

1) Beschäftige dich mit 3D-Modelling und Texturing. Ob du dafür nun Autodesk Maya 3D, Blender oder Cinema 4D nutzt, ist an sich egal. Zu dem Thema gibt es zahlreiche Tutorials (schau z.B. auf die YouTube-Kanäle von blenderguru, grabbitt, Greyscalegorilla oder CGMasters), Webartikel oder Bücher.

Gerade da du deine Models später in eine Game Engine importieren möchtest (deren Rendering Engine anders als in den oben genannten Modellierungsprogrammen nur eine begrenzte Zeit hat, das Modell mit seinen Texturen zu zeichnen), wäre es wichtig, ein einfaches strukturiertes, qualitativ hochwertiges Ausgangsmaterial (low-poly-Modell, Texturen bestenfalls in 8k) zu haben.

Möglicherweise findest du auch passende Ressourcen im Asset Store oder Plattformen wie ambientCG, Poliigon, textures.com, u.ä..

2) Via Postprocessing in Unity kannst du nochmals die Qualität (oder den generellen Art Style) beeinflussen. Beschäftige dich mit den Graphic Features der Rendering Engine (Lighting, Textures, Shaders, ...) und ebenso mit HDRP (s. auch diesen Artikel aus dem Unity Blog; doch sicherlich findest du noch mehrere andere Quellen hierfür).

3) Schau im Unity Forum, auf YouTube, GitHub o.ä. Seiten nach Walking Simulator-Projekten, an denen du dich orientieren kannst. Du bist ja nicht die erste Person, die in diese Kerbe schlagen möchte.

...zur Antwort

Dein Programm muss selbst die Map, bzw. die un-/begehbaren Bereiche kennen. Immer wenn sich deine Figur bewegen soll, muss geprüft werden, ob sie sich auf eine unbegehbare Fläche bewegt oder nicht. Wenn ja, müsste es eine Gegenmaßnahme geben (Reduzierung der Spielergeschwindigkeit auf 0 o.ä.).

In Java könnte man sich ein zweidimensionales Array anlegen, welches die Karte (in Form eines Rasters) abbildet (= Tilemap). Jedes Element im Array entspricht also einem Feld im Raster.

Beispiel:

boolean[][] map = {
 { false, true, true },
 { true, true, false },
 { false, false, false },
};

In dieser einfachen Form würde false für ein unbegehbares Feld und true für ein begehbares Feld stehen.

Bestenfalls wird dieses Array nun nicht nur zur Prüfung bei Spielerbewegungen herangezogen, sondern ebenso an den Zeichenprozess gekoppelt.

Beispiel bei einer Ausgabe auf der Konsole:

for (int y = 0; y < map.length; ++y) {
  for (int x = 0; x < map[y].length; ++x) {
    System.out.print(map[y][x] ? " " : "#");
  }

  System.out.println();
}

Für komplexere Maps könnte man statt mit boolschen Werten entweder Zahlen nutzen, die jeweils verschiedene Feldtypen kennzeichnen (z.B. 0 für Blöcke, 1 für Gras, 2 für Schnee, ...) oder eine eigene Feldklasse anlegen.

enum FieldType { GRASS, SNOW, WALL, /* ... */ }

class Field {
  private final FieldType fieldType;

  public Field(final FieldType fieldType) {
    this.fieldType = fieldType;
  }

  /* ... */
}

// map:
Field[][] map = {
  { new Field(FieldType.WALL), new Field(FieldType.GRASS), new Field(FieldType.GRASS) },
  { new Field(FieldType.GRASS), new Field(FieldType.GRASS), new Field(FieldType.WALL) },
  { new Field(FieldType.WALL), new Field(FieldType.WALL), new Field(FieldType.WALL) }
};

Alternativ zu einem Array (bzw. einer Tilemap) könnte man ein Spielfeld ebenso mit einem Quadtree abbilden, dem man entweder nur die Koordinaten der begehbaren oder andersherum, nur der unbegehbaren Bereiche mitteilt.

Für Programmieranfänger ist die Arraylösung allerdings wesentlich einfacher.

...zur Antwort

Dictionaries haben ein Keys-Property. Schau dafür in die Dokumentation. Bei ToArray handelt es sich wiederum um eine Linq-Erweiterungsmethode. Das heißt, du musst dafür noch den entsprechenden Namespace inkludieren.

Beispiel:

using System;
using System.Collections.Generic;
using System.Linq;

var someDictionary = new Dictionary<string, string>();
var someArray = someDictionary.Keys.ToArray();
...zur Antwort

Der erste Schritt wäre stets, das Problem zu erfassen, welches folgend gelöst werden soll. Ob es hierbei nun darum geht, ein komplettes Programm zu entwickeln oder nur um die Entwicklung einer einzigen Funktion in einem Programm, ist an der Stelle egal. Beschreibe also zuerst, in Kurzform (Stichpunkte / wenige Sätze), was du überhaupt erreichen möchtest. Dabei kann man zusätzliche Informationen, wie den aktuellen Zustand mit hineinnehmen, wenn man es als hilfreich empfindet.

Solltest du dabei mit dir unbekannten Themen konfrontiert sein, müsstest du dich in diese erst hineinarbeiten. Wolltest du beispielsweise einen Konverter entwickeln, der Dezimalzahlen in eine Form des Binärsystems umwandelt, müsstet du erst wissen, wie diese Zahlensysteme überhaupt funktionieren und wie der mathematische Weg zur Umwandlung aussieht.

Der zweite Schritt wäre eine Ausarbeitung und der Beginn einer Aufteilung. Vor allem wenn es um ein komplexes Problem geht, welches in seiner Rohform noch zu abstrakt ist, als dass man es direkt lösen könnte, muss man schauen, dass man es zergliedern kann. So oft, bis man konkrete, fassbare Teilaufgaben vor sich hat, mit denen zusammengenommen sich das Gesamtziel erreichen lässt.

Ein sehr einfaches, bildhaftes Beispiel dafür wäre die Ausgabe eines beliebig großen Vierecks mit einem beliebigen Zeichen in der Konsole. So ein Viereck besteht aus mehreren Reihen und Spalten. Insofern kann man erst schauen, wie man eine Reihe ausgibt und noch davor, wie man überhaupt eine Spalte zeichnet.

void printColumn(char symbol) {
  System.out.print(symbol);
}

void printRow(char symbol, int width) {
  for (int x = 0; x < width; ++x) {
    printColumn(symbol);
  }

  System.out.println();
}

void printRectangle(char symbol, int width, int height) {
  for (int y = 0; y < height; ++y) {
    printRow(symbol, width);
  }
}

Es setzt in diesem Beispiel natürlich auch etwas voraus, dass zumindest ein paar Implementationen (siehe print, println) aus der Standard-API bereits bekannt sind, damit man nicht wirklich alles versucht, neu zu erfinden. Bei bestimmten Herausforderungen sollte man daher ebenso eine kurze Recherche in Erwägung ziehen, ob es nicht schon fertige Lösungen gibt. Mathematische Funktionen (log, pow, sin, ...) oder String-Operationen (reverse, substring, ...) sind typische Beispiele.

Die Umstellung in ein recht striktweises Denken ist zugegeben nicht immer einfach. Für Programmiereinsteiger ist es vor allem ungewohnt, da der Mensch an sich sprachlich Operationen meist zusammenfasst. Eine Aktion wie laufen ist für uns alle verständlich. Für den Computer ist es eine komplexe Operation, die erst in die einzelnen Muskelbewegungen heruntergebrochen werden müsste.

Ein paar Tipps, die ich bei der Entwicklung von Funktionen/Algorithmen geben könnte, wären diese:

  • Suche in der Beschreibung des Problems nach Verben, die notwendige Operationen (also Funktionen) darstellen könnten.
  • Überlege dir, was der IST-/Anfangs- und der SOLL-/End-Zustand ist.
  • Halte dich möglichst strikt an die Regel, dass jede Funktion nur einem Zweck dient, nicht mehreren.
  • Scheue nicht davor zurück, Hilfsfunktionen zu formulieren, wenn eine Operation leicht beschreibbar, aber für sich gesehen dennoch komplex ausfällt. Ein typisches Beispiel wäre eine mathematische Prüfung, ob sich ein Punkt in einem Rechteck befindet. So etwas lässt sich gut auslagern und später an anderer Stelle wiederverwenden.
  • Lege dir einen Programmablaufplan an (alternativ ein Struktogramm o.ä. Skizzen - hauptsache es gibt nur einfache Bauteile wie if-else, Deklaration/Definition, Anweisung); Operationen, die noch zu abstrakt/komplex sind, werden in weiteren (eigenen) Diagrammen/Skizzen behandelt.
  • Wenn du die Möglichkeit hast, dir Operationen durch Nachstellung bildlich zu machen, dann nutze das (Beispiel: Arrayoperationen wie Tauschen, Sortieren kann man sich mit Karten nachlegen).
  • Löse Probleme nie direkt mit Programmcode. Beginne mit einer Übersetzung in Java-Code erst, sobald der Ablauf des Algorithmus bereits (z.B. als Diagramm) feststeht und getestet werden konnte (nimm dir 1-2 konkrete Anwendungsfälle und versuche mit ihnen deinen Plan einmal durchzuspielen, so fallen frühzeitig Logikfehler auf).
  • Stelle (Performance-)optimierungen hintenan.
  • Vergib für alle Elemente (Variablen, Funktionen, etc.) immer eindeutige, aussagekräftige Namen.

Dazu gibt es eine große Bandbreite an möglichen Aufgaben, an denen sich das Vorgehen üben lässt. Zum Beispiel:

  • Berechnung des Produkts zweier Faktoren, ohne den Multiplikationsoperator zu nutzen
  • Konversion von Zahlen in unterschiedliche Zahlensysteme (Dezimal-/Oktal-/Hexadezimal-/Binärsystem)
  • Addition und Subtraktion beliebiger Brüche
  • Berechnung des größten/kleinsten gemeinsamen Teilers zweier Zahlen
  • Berechnung der Quersumme einer dreistelligen Zahl
  • Berechnung und Ausgabe der ersten zehn Ziffern der Fibonacci-Reihenfolge
  • Die Lösung von Problemen gezielt mit Rekursion (Test ob ein Wort einem Palindrom entspricht, Rückwärtsausgabe einer Zeichenfolge, Berechnung der Werte für ein Pascal'sches Dreieck)
  • Viele mathematische Rätsel findest du auf Projekt Euler
  • Zahlen-raten (eine Zahl zwischen 0 und 1000 wird berechnet, in Folge soll versucht werden, mit möglichst wenigen Arbeitsschritten diese Zahl zu erraten)
  • Eigenimplementation von bekannten String-Methoden (z.B. indexOf, replace und replaceAll für einfache Zeichenfolgen, substring)
  • Die Implementation von Sortierverfahren (Bubblesort, Selectionsort, Insertionsort, Quicksort) - schau für die jeweiligen Beschreibungen auf Wikipedia
  • Überlege dir Methoden, wie man in einer Liste beliebiger Zahlen eine bestimmte Zahl suchen könnte
  • Entwicklung eigener Datenstrukturen (ohne dafür die List-Implementationen der Standard-API zu nutzen): Stack (mit peek, pop und push), doppelt verkettete Liste (mit add, insert, remove), eine Queue (mit add, remove), AVL-Baum (mit add, insert, remove), Graph (mit add, insert, remove)
  • Binäre Suche für einen binären Baum
  • Traversionsverfahren für einen binären Baum (pre-order, in-order, post-order)
  • Suche nach dem kürzesten Weg von einem Knoten eines Graph zu einem anderen (die Kanten, die die Knoten verbinden, geben die Entfernung zwischen zwei verbundenen Knoten vor)
  • Minispiele oder Simulationen wie Conway's Game Of Life, Türme von Hanoi oder Snake (für die grafische Darstellung kannst du Processing nutzen)

Bei der Entwicklung von komplexen Programmen kommt es oft vor, dass man keinen allgemeinen Hauptprogrammablauf hat und stattdessen ein Bündel verschiedener Anwendungsfälle/Funktionen (vgl. mit MSPaint: Der Nutzer kann das Programm öffnen und verschiedene Aktionen in beliebiger Reihenfolge starten). Zudem ist man meist damit konfrontiert, neben der eigentlichen Anwendungslogik noch eine grafische Oberfläche zu haben, die interaktiv sein muss.

Es ist bei so einem Projekt sinnvoll, in der Analysephase das Programm als eigenständiges System auszuarbeiten, welches sich an objektorientierte Konzepte orientiert.

  • Man muss die Anwendungsfälle finden, die in dem System auftreten können (ein use-case-diagram kann hierbei helfen: Erst schaut man, wer das Programm nutzen soll und dann, welche Interessen diese Personengruppe hat bzw. was für Aktionen sie nutzen wird)
  • Anhand einer textuellen Beschreibung des Systems (Was tut es? Wer agiert damit?) kann man einmal wieder herausfinden, welcher Objekte es braucht und wie sie miteinander agieren. Ich habe das in diesem Beitrag einmal an dem Spiel Pac-Man ansatzweise gezeigt. Letztendlich lässt sich damit ein Objektdiagramm und anschließend ein Klassendiagramm kreieren (Stichwort: UML)

In der Projektstrukturierung wiederum sollte es klare Aufteilungen geben. Funktionsbündel kann man als eigene Module definieren (Beispiel MSPaint: Es gibt ein Modul zur Speicherung von Bildformaten, ein Modul für Zeichenoperationen, usw.). Die Anwendungslogik sollte generell von der Formulierung der grafischen Oberfläche getrennt sein. Architekturmuster wie MVC, MVP oder MVVM sind dabei ziemlich hilfreich. Generell macht es Sinn, sich zu diesem Thema (Architektur- und Entwurfsmuster) genauer zu belesen.

Hilfreich könnte zudem eine testgesteuerte Entwicklung (test-driven-development/TDD) sein, da sie dich unter anderem stärker dazu drängt, modular zu denken. Recherchiere zu dem Thema einfach einmal.

...zur Antwort

Trimming ist bei Anwendungen, die mit Reflection oder COM-Marshalling arbeiten, problematisch, denn während des Analyseprozesses kann nur schwer beurteilt werden, was denn raus darf oder nicht. Windows Forms ist an der Stelle besonders betroffen, denn es baut unter Haube wesentlich auf COM-Marshalling. Eine mögliche Lösung an der Stelle ist die Nutzung von COM-Wrappern (siehe z.B. WinFormsComInterop).

Zusätzlich solltest du den Microsoft-Artikel Prepare libraries for trimming durcharbeiten.

Eine Garantie dafür, dass du es schaffst, gibt es aber nicht. Seitens des .NET-Teams (lies hier) gibt es jedenfalls noch keinen offiziellen Support. Einen Überblick über den aktuellen Entwicklungsstatus liefert dieses Epic: #4649 Make WinForms trim compatible.

Noch ein paar andere Optionen, die du ausprobieren/angehen könntest:

  • Deploye die App im Release-Modus.
  • Gehe diese Liste an Features durch. Sicherlich kannst du einige von ihnen ausschließen.
  • Schau, ob es im Projekt Dateien gibt, die explizit exkludiert werden können und markiere sie entsprechend.
  • Komprimiere Mediendateien (u.ä. externe Ressourcen), die du möglicherweise nutzt.
  • Mit einem Packer/Kompressor kannst du deine Executable nochmals komprimieren (siehe bspw. NeoLite oder UPX).
  • Etwas, was man fallbedingt einfach einmal testen müsste: Eine Aufteilung in Assemblies und dazu ein partielles Trimming.
...zur Antwort

Überlege dir zuerst, welche tatsächlichen Vorteile für dich entstehen bzw. welche Features denn nun fehlen würden, die bestehende Ticketsysteme nicht bieten. Schau dabei auch, ob deine Anforderungen nicht via Nachkonfiguration oder mittels Erweiterungen eines existierenden Systems erfüllbar sind. In der Regel sind solche Anwendungen ziemlich anpassbar und verfügen über eine API zur Automatisierung.

Für das Anlegen von Tickets aus der App heraus, kannst du dir beispielsweise auch ein einfaches Formular anlegen, welches notwendige Daten (Titel, Beschreibung, ...) an ein bestehendes System schickt.

Meines Erachtens dürfte es kaum Gründe geben, das Rad an der Stelle neu erfinden zu müssen. Zumal du an der Stelle ein zweites Softwareprojekt starten würdest und den Fokus vom wesentlichen Projekt nimmst. Das wird dich definitiv hemmen, egal ob du das Projekt nun als einfach oder schwer einschätzt.

Ein zusätzlicher Vorteil, den dir Plattformen wie Atlassian, DevOps oder GitHub bieten können, ist ein komplettes Board rund um deine Software drumherum, welches neben dem Ticketsystem noch weitere Aspekte (Repository, Wiki, Release-Pipelines) verknüpfen kann.

...zur Antwort
Fehler bei password verify php?

Ich habe ein Testprogramm geschrieben, in dem man ein Passwort eingibt, dass dann gehasht in einer Datenbank gespeichert wird. Wenn ich mit dem Passwort vergleiche kommt aber nicht true sondern false raus. Das ganze habe ich in WebFTP gemacht.

Als Ausgabe bekomme ich:

123456789 $2y$10$4TMgUO3xGJMCy5iZnd6Be.TBRkIO2Z55GGwgQ5oeToD.ryJZAvvte Richtig In Datenbank übertragen $2y$10$4TMgUO3xGJMCy5iZnd6Be.TBRkIO2Z55GGwgQ5oeToD.ryJZAvvte Falsch Richtig übertragen

Bedeutet das gehashte Passwort wurde richtig gespeichert, aber passwort verify hat beim zweiten mal false zurück gegeben.

Hier ist der php Teil dazu:

<?php
if (isset($_POST["start"])) {
    $password = $_POST["password"];
    $email = $_POST["email"];
    echo $password . " ";
    $passwordHash = password_hash($password, PASSWORD_DEFAULT);
    echo $passwordHash . " ";
    if (password_verify($password, $passwordHash)){
        echo "Richtig ";
    }else{
        echo "Falsch ";
    }
    require_once "data.php"; //Hier wird die Datenbankverbindung gespeichert
    $statement = $pdo->prepare("INSERT INTO tab (email, password) VALUES (?, ?)");
    $statement->execute(array($email, $passwordHash));
    if ($statement){
        echo "In Datenbank übertragen ";
        $sql = "SELECT * FROM tab WHERE email='$email'";
        $user = $pdo->query($sql)->fetch();
        $passwordTest = $user["password"];
        echo $passwordTest . " ";
        if (password_verify($password, $passwordTest)){
            echo "Richtig ";
        }else{
            echo "Falsch ";
            if ($passwordHash == $passwordTest){
                echo "Richtig übertragen ";
            }else{
                echo "Falsch übertragen ";
            }
        }
        die();
    }else{
        die("Es ist etwas schief gelaufen");
    }
}
?>
...zum Beitrag

Vorweg: Ich kann dein Problem nicht reproduzieren.

Ein häufiger Grund, wenn ein Vergleich mittels password_verify fehlschlägt, liegt allerdings in intern unterschiedlich genutzten Zeichenkodierungen. Stelle daher sicher, dass du für die Datenkommunikation überall eine einheitliche Kodierung verwendest.

1) Gib dem Browser in dem HTML-Dokument, welches das Formular beinhaltet, eine Zeichenkodierung vor:

<meta charset="utf-8">

2) Deine Datenbank/-tabelle sollte die Daten in utf8mb4-Kodierung (= UTF-8) speichern.

3) Gib in deinem Connectionstring eine eindeutige Kodierung vor:

$connectionString = 'mysql:host=...;dbname=...;port=...;charset=utf8mb4';
...zur Antwort

Ein Weg wäre die Installation des DuckDB CLI. Lade die passende Version für dich herunter und entpacke sie. Die Datenbankdatei würde ich im Anschluss (der Einfachheit halber) direkt mit in das Verzeichnis kopieren.

Öffne im Anschluss die Kommandozeile deines Betriebssystems (meine folgenden Code-Snippets beziehen sich auf Windows OS) und navigiere zu dem entpackten Ordner, in dem die duckdb.exe liegt.

cd "c:/path/to/duckdb/folder"

Dann kannst du auch schon eine Verbindung herstellen:

duckdb hotelkette.db

Sollte deine Datenbankdatei doch noch in einem anderen Pfad liegen, gib stattdessen den absoluten Dateipfad an. Am besten umklammert von Anführungszeichen, falls einer der Verzeichnisnamen ein Leerzeichen enthalten sollte.

duckdb "c:/path/to/hotelkette.db"

Sobald sich der Client mit der Datenbank verbunden hat, solltest du via SQL Daten auslesen oder schreiben können. Der beste Startpunkt wäre wohl, erst einmal in Erfahrung zu bringen, was für Tabellen überhaupt in der Datenbank liegen und wie sie strukturiert sind.

Die information_schema_tables-View beinhaltet bspw. Informationen über alle verfügbaren Tabellen in der Datenbank:

SELECT table_name FROM information_schema.tables

Die Struktur einer bestimmten Tabelle kannst du in Erfahrung bringen, indem du in der information_schema.columns-View nach der Tabelle suchst:

SELECT * FROM information_schema.columns WHERE table_name = 'name of a table'

Mehr zu den information_schema-Views kannst du in der Dokumentation nachschlagen.

Alternativ zu diesem Weg macht es dir DBeaver an der Stelle natürlich deutlich einfacher. Auf deinem ersten Screenshot hast du die Datenbank ja bereits geöffnet. Wenn du im linken Dialog (Datenbanknavigator) die Knoten von beispielsweise main oder pg_catalog einmal aufklappen würdest, solltest du ebenso die Tabellen finden, die in der Datenbank so vorliegen.

Explizit relevant für dich sind natürlich nur die Tabellen, die irgendetwas mit Hotels zutun haben.

Sollte dir nun aber noch Wissen zu dem Aufbau von Datenbanktabellen fehlen (z.B. Was Constraints oder Datentypen sind), würde ich dir empfehlen, dich dazu erst einmal zu belesen. Hilfreiche Artikel gibt es zum Beispiel auf datenbanken-verstehen.de. Bezüglich der SQL-Syntax solltest du in der DuckDB-Dokumentation nachschlagen.

(...) um an dieser Datei neue Dinge hinzuzufügen (...)

Neue Daten kannst du mittels INSERT INTO zu einer bestehenden Tabelle hinzufügen.

Beispiel:

Angenommen, wir haben eine Tabelle hotelpersonal, die das Hotelpersonal auflisten soll. Es gibt die Spalten vorname (VARCHAR), nachname (VARCHAR), gehalt (DECIMAL) und position (VARCHAR).

Das Hinzufügen eines neuen Datensatzes könnte folgendermaßen aussehen:

INSERT INTO hotelpersonal (vorname, nachname, gehalt, position)
VALUES ('Zéro', 'Moustafa', 2400, 'Page');

Für Weiteres dazu würde ich erneut auf die DuckDB-Dokumentation verweisen.

...zur Antwort

PyCharm verwendet eine eigene Konsolenimplementation, die sich nicht direkt so verhält, wie du es bei der Windows Konsole erwarten könntest. Aufrufe wie cls funktionieren in ihr nicht. Wenn du den Fensterinhalt leeren möchtest, musst du auf die GUI-Funktionalitäten von PyCharm zurückgreifen (z.B. Rechtsklick in das Konsolenfenster > Clear All).

Die IDE stellt allerdings auch eine Einstellung bereit, mit der eine OS-Konsole zumindest emuliert werden kann (siehe: Emulate terminal in output console in den Run/Debug Configurations). Wenn du die aktivierst, sollte ein Aufruf wie

import os
os.system("cls")

die Konsole leeren.

Für eine tatsächliche Sicherheit, dass all deine Anweisungen an die Konsole wie erwartet funktionieren, solltest du dein Python-Skript allerdings in der echten Konsole von Windows ausführen.

...zur Antwort

a) Es gibt Dateiversionierungssyteme wie Git oder Mercurial, deren Repository zentral gehostet werden kann (siehe Bitbucket, GitLab, GitHub, Sourceforge). Das Repository beinhaltet all eure Projektdateien und ebenso eine Verlaufsgeschichte über jegliche Änderungen, die in ihm einmal registriert wurden.

Jeder in eurem Team kann sich folgend dieses (Remote) Repository klonen und in diesem seine Änderungen einfügen (Commits). Später werden diese auf das zentrale Repository geschoben. Sollten zwei Personen zeitgleich an einer Datei gearbeitet haben, ist es notwendig, die Änderungen zusammenzuführen (Merge).

Die Arbeit mit solchen Versionierungssystemen ist gängiger Standard in der Industrie.

b) Für einige Entwicklungsumgebungen/Editoren gibt es Kollaborationssoftware, über die man in Echtzeit gemeinsam an einem Projekt arbeiten kann. Für Eclipse gibt es da z.B. das Saros Plugin oder für Visual Studio und VS Code gibt es Live Share.

c) Zu guter Letzt steht euch natürlich noch offen, via Kommunikationssoftware (Microsoft Teams, Skype, o.ä.) Pair Programming zu organisieren.

...zur Antwort

1) Dein HTML ist an verschiedenen Stellen invalid.

  • select-Elemente kennen kein Attribut test
  • Das erste Anführungszeichen muss raus
  • option-Elemente kennen kein Attribut href

2) Bei nur einer Option in der Auswahlbox hat der Nutzer nicht die Möglichkeit, die Auswahl zu ändern (und somit ein change-Event zu triggern).

3) Da dein option-Element kein value-Attribut definiert, wird das Label (in deinem Fall -test) als Wert verwendet.

Eine korrigierte Fassung könnte folgendermaßen aussehen:

<select name="test" onchange="window.open(this.value, '_self'); return false;">
  <option selected disabled>Please choose a target</option>
  <option value="index.html">-test</option>
</select>
...zur Antwort

1) Du setzt mehrmals die Schriftart für Komponenten falsch.

// falsch
entry= tk.Entry(root, width= 20, font("Arial", 20), bd=20, justify= tk.RIGHT)

// richtig
entry= tk.Entry(root, width=20, font="Arial 20", bd=20, justify=tk.RIGHT)

// auch richtig
entry= tk.Entry(root, width=20, font=("Arial", 20), bd=20, justify=tk.RIGHT) 

Bei font handelt es sich um ein keyword argument. Dieses wird mittels Gleichheitszeichen von seinem Wert getrennt.

2) Hinter dem Kopf einer Kontrollstruktur kommt stets ein Doppelpunkt

// falsch
if column_val> 3

// richtig
if column_val > 3:

Es ist für eine bessere Lesbarkeit im Übrigen sinnvoll, Operatoren und Terme via Leerzeichen zu trennen.

3) Die Einrückungen in deiner vorletzten Schleife sind offensichtlich falsch. Wenn du einen neuen Kontext öffnen möchtest (z.B. if-Körper), dann rücke um vier Leerzeichen nach rechts ein. Soll dieser Kontext wieder geschlossen werden, geht es wieder vier Leerzeichen nach links.

4) Der Aufruf von mainloop sollte insgesamt nur einmal erfolgen. Er gehört also nicht in den Schleifenkörper.

5) Bei entry.grid handelt es sich um einen Methodenaufruf. Folglich ist der Zuweisungsoperator vor der Klammer (Argumentenliste) falsch.

6) Es gibt kein Argument stickx für die grid-Methode.

...zur Antwort