Montag, 28. Oktober 2013

Konsoleneingabe mit der Klasse Scanner in Java

Wichtig für Smartphonebenutzer

Jetzt wird es etwas kompliziert, ich hoffe ich kann es verständlich erklären, denn Java hat keine einfache Methode um im Konsolenfenster eine Eingabe zu machen. Wir erweitern das Beispiel vom Tutorial "Variablen in Java", es soll natürlich nicht immer der selbe Kreisumfang berechnet werden, der Benutzer soll es im laufenden Programm eingeben. Hier ist einmal das ganze Beispiel:

  1. import java.util.*;
  2. public class Rechner {
  3.         public static void main(String[] args) {
  4.                
  5.                 Scanner eingabe;
  6.                 eingabe = new Scanner(System.in);
  7.                
  8.                 final double PI = 3.141592653589793D;
  9.                 double Radius, Umfang;
  10.                
  11.                 System.out.print("Radius: ");
  12.                 Radius = eingabe.nextDouble();
  13.                                
  14.                 Umfang = PI * Radius * 2;
  15.                
  16.                 System.out.println("Umfang des Kreises: "
  17.                                    + Umfang);
  18.                                        
  19.         }
  20. }

Als erstes sehen wir im Beispiel die import-Anweisung, der Compiler benutzt ein Standartpaket namens java.lang. Einiges ist aber in Pakete (sind mehrere Klassen) ausgelagert wie die Klasse Scanner. Durch die Anweisung

import java.util.*;

teilen wir dem Compiler mit das Paket java.util zu verwenden. Es geht aber auch mit der Anweisung

import java.util.Scanner;

dadurch verwendet der Compiler nur die Klasse Scanner und nicht das gesamte Paket. 

Mit den beiden Zeilen:

Scanner eingabe;
eingabe = new Scanner(System.in);

wird ein Objekt der Klasse Scanner erzeugt, der Operator new reserviert den Speicherplatz dazu. System.in übergibt den Eingabestrom (Tastatureingabe) an das Objekt (eingabe). Mit der Methode nextDouble() aus der Klasse Scanner wird der Eingabestrom als Datentyp double an die Variable Radius übergeben. Achtung, der Eingabewert sollte dem Datentyp entsprechen oder der Compiler gibt einen Fehler zurück.  

Es ist vielleicht etwas schwer zu verstehen, weil ich jetzt Klassen und Methoden im Tutorial habe, die wir noch nicht richtig behandelt haben. Ich musste es jetzt aber machen weil wir die Tastatureingabe für die nächsten Tutorials benötigen. Wer es noch nicht richtig versanden hat macht auch nichts. In späteren Tutorials werde ich es ausführlicher erklären. Die Hauptsache ist jetzt einmal zu wissen wie man eine Tastatureingabe bekommt.


Mittwoch, 23. Oktober 2013

Historyline 14-18

Heute ist es soweit ich stelle mein erstes Retro-Game vor. Für mich ist es jedenfalls ein Meilenstein der Rundenstrategie. Es sagt schon der Name um was es im Spiel geht, nämlich um den 1. Weltkrieg.





Man kann auf deutscher oder französischer Seite spielen, das Ziel ist seinen Gegner zu vernichten oder sein Hauptquartier einzunehmen. Sowas ist leicht gesagt, ist aber auch nicht gerade einfach. Die KI ist zwar nicht schlau und verheizt seine Einheiten regelrecht, aber man merkt schnell dass die KI einen einfach überrent wenn man nicht taktisch geschickt vorgeht.


Depots und Fabriken sollten so schnell es geht eingenommen werden. Meistens sind darin Einheiten die man gut brauchen kann. Die schwer beschädigten Einheiten sollten immer wieder mal im Depot oder der Fabrik repariert werden. Einheiten werden pro Kampf erfahrener und können sehr wertvoll werden um den Angriff zu überstehen. Es kommt öfter vor dass eine erfahrene Einheit eine unerfahrene auf einmal vernichtet. Es sind aber auch die Eigenschaften der Umgebung etwas ausschlaggebend wie ein Kampf ausgehen kann.



Das Spiel macht immer noch sehr viel Spaß, wer Rundenstrategie mag hat hier ein richtige Juwel. Historyline 14-18 lässt sich am flüssigsten mit der Tastatur spielen, mit der Maus ist es einfach zu fummelig. Wer es richtig raus hat mit der Tastatur ist sehr schnell beim ziehen seiner Truppen.


Wie man schon erkennen kann, ist es auch möglich zu zweit gegeneinander an einem PC zu spielen. 







Dienstag, 22. Oktober 2013

Blöcke in Java

Die Anweisungen, die zwischen { und } stehen werden als Block bezeichnet. Ein Block kann bei jeder einzelnen Anweisung verwendet werden. Der Block ist eigentlich eine Anweisung die mehrere zusammengesetzte Anweisungen darstellt. Blöcke können auch ineinander verschachtelt sein. Hier ein kleines Beispiel:


Es ist zu beachten, dass die Variablen außerhalb ihres Blockes in dem sie deklariert wurden nicht gültig sind. Uns ist es also nicht möglich die Variable y und z zu addieren.

Montag, 7. Oktober 2013

Variablen in Java

Eine Variable hat eine Speicheradresse auf einen Speicherort zeigt in der der Inhalt steht, der in der Variable initialisiert wird. Die Größe des Speicherorts entspricht der Größe des angegebenen Datentypes.

Besser kann man es sich so vorstellen. Man steht vor einem Schrank (Arbeitsspeicher)  mit lauter verschieden große Schubläden. Jeder Schubladen hat eine Nummer (Speicheradresse). Wenn wir jetzt etwas darin verstauen wollen, wollen wir natürlich so wenig Platz wie möglich verbrauchen, weil nur ein Gegenstand (Variableninhalt) in eine Schublade darf. Wir suchen sich also die passende Schublade (Größe des Datentyps) aus und legen den Inhalt rein. Natürlich müssen wir uns jetzt die Nummer des Schubladen irgendwie merken, damit wir schnell den richtigen Schubladen wieder finden. Deshalb schreiben wir eine Kurze Notiz (Bezeichner) in der unsere Nummer (Speicheradresse) des Schubladens  steht. Wenn wir jetzt einen Gegenstand suchen Schauen wir unsere Notizen durch und wissen genau in welcher Schublade unser gesuchter Inhalt ist.

Durch dieses Beispiel kann man sich auch viel einfacher vorstellen wie die Typumwandlung geht, die schon im vorherigen Tutorial "Einfache Datentypen in Java" angesprochen wurde. Ein kleiner Inhalt kann in einen grösseren Schubladen ohne Probleme vom Compiler automatisch umgewandelt werden, dies ist die Implizite Datenumwandlung. Wenn aber ein größerer Inhalt in einen kleineren Schubladen soll muss man den Compiler erst angeben, dass man es will und er es einfach sozusagen reinquetschen soll ohne Rücksicht auf Verluste (Rundungsfehler), das ist die Explizite Datenumwandlung.

Jetzt schauen wir uns mal ein Beispiel an:


Wie wir sehen wird hier die Summe von 6 + 8 ausgegeben. Wenn wir jetzt andere Zahlen addieren wollen müssen wir 4 Werte korrigieren (In der Zeichenkette müssen ja auch die passenden Zahlen stehen). Bei großen Programmen kann es dann sehr umfangreich werden wenn man einen Wert ändern möchte. Deshalb deklarieren und initialisieren wir zwei Datentypen. Für den Anfang schaut es nach mehr Arbeit aus, aber dieses bisschen mehr Aufwand ist bei größeren Programmen vorteilhaft und man will auch nicht immer den gleichen Wert berechnen.


Bei diesen Beispiel müssen wir nur noch die beiden Werte initialisieren, also den Datentypen mit den = Operator zuweisen. Damit ist schon einmal der Aufwand zum korrigieren geringer geworden, wie man bestimmt merkt. Jetzt schauen wir uns mal den Code genauer an.

int a, b;

Hier werden die beiden Variablen a und b erzeugt (deklariert), die Bezeichner  haben eine Größe von 4 Byte. Es wird für die beiden Variablen ein Speicherplatz reserviert und jede der beiden Variablen hat eine Speicheradresse für ihren reservierten Speicherplatz.  Mit der angegebenen Speicheradresse zeigt die Variable auf den Speicherplatz. Variablen kann man wie bei dem Beispiel in einer Zeile deklarieren, aber dann nur mit dem Selben Datentyp.

a = 6;
b = 8; 

In den beiden Zeilen werden die Werte 6 und 8 initialisiert (werden die Variablen a und b mit dem Operator = zugewiesen).  

System.out.println( a + " + " + b " = " + (a + b));

Diese Zeile schaut etwas kompliziert aus, als erstes deklariert der Compiler einen String ohne Bezeichner.
Dann wird der Teil a + " + " + b " + " = " in den String initialisiert jetzt schaut es sozusagen so aus:

System.out.println("a + b = " + (a + b);

Jetzt deklariert der Compiler einen int Variable ohne Bezeichner und initialisiert die Summe von a und b.

System.out.println("a + b = " + 14);

Der Compiler fügt dem String die Variable int dem String hinzu und gibt den kompletten String auf der 
Konsole aus.


Achtung: Wenn (a + b) nicht in Klammern steht werden a und b nicht addiert sondern nur dem String hinzugefügt.

Manchmal ist es sinnvoll eine Variable mit einem Wert zu initialisieren der bei dem Programmablauf gleich bleibt. Dafür gibt es die final-Variable (oder symbolische Konstante). Um so eine Konstante zu deklarieren, muss man der üblichen Deklaration mit der Initialisierung das Schlüsselwort final voranstellen.


Unser Programm ist jetzt etwas umgebaut worden, jetzt kann der Umfang eines Kreises berechnet werden. PI ist eine final-Variable, solche Variablen werden nur mit Großbuchstaben geschrieben und die Initialisierung muss in der selben Zeile der Deklaration gemacht werden. Es kann auch kein neuer Wert initialisiert werden, bei einem Versuch einen neuen Wert zu initialisieren, gibt der Compiler eine Fehlermeldung zurück.

Operatoren
Bei den Operatoren gibt es die einstelligen Operatoren (unär bzw. monadisch), die zweistelligen Operatoren (binär bzw. dyadisch) und die dreistelligen Operatoren (ternär bzw. triadisch).

Einstellige Arithmetische Operatoren:


Zweistellige Arithmetische Operatoren:



Der dreistelligen Bedingungsoperator ?: (wird sehr selten benutzt), er ist eigentlich die verkürzte Schreibweise der if-Entscheidungsanweisung. Wir werden sie mit den Entscheidunsanweisungen behandeln.

Die oben aufgeführten Arithmetischen Operatoren können für die Datentypen : byte, short, int, long, float, double oder char verwendet werden. Der Operator + kann auch dazu verwendet werden Zeichenketten zu verbinden (dies haben wir in den vorherigen Tutorials schon verwendet).

Bitoperatoren
Auf diese Operatoren werde ich jetzt nicht eingehen, sie sind auch für Anfänger sehr uninteressant, eventuell werde ich aber diesen Punkt noch ergänzen und doch noch darüber schreiben.

Zuweisungsoperator
Der Zuweisungsoperator = hat eine Sonderstellung. Mit ihm kann man Variablen Werte zuordnen.

x = 7;

Der Variable x wird der Wert 7 zugeordnet. Es kann aber auch eine Variable anstatt eines Konstanten Werts zugeordnet werden.

x = y = z = 9;

Hier wird der konstante Wert 9 z zugeordnet, dann y und danach x zugeordnet.

x = x + 5

Hier wird die Variable x addiert mit dem konstanten Wert 5 und die Summe x zugeordnet.

Es gibt in Java verkürzte Schreibweisen für binäre Operatoren:


Also ist durch die verkürzte Schreibweise:

x += 5; das Selbe wie x = x + 5;

Vergleichsoperatoren und logische Operatoren
Die Vergleichsoberatoren sind immer binär. Es werden zwei Werte (Operanten) miteinander verglichen und gibt ein Ergebnis vom Typ boolean zurück (entweder true oder false).

Vergleichsoperatoren in Java:


Die logischen Operatoren werden oft mit den Vergleichsoperatoren verwendet um komplexere Ausdrücke zu erstellen. Die logischen Operatoren erwarten immer einen Wert vom Typ boolean und gibt auch solchen zurück.

Logisch Und, Oder und die Negation:


Logische Operatoren:


Bei a & b und a | b werden beide Operanten ausgewertet. Bei a && b wird der zweite Operant nur ausgewertet wenn der erste Operant true ist. Bei a || b wird der zweite Operant nur ausgewertet wenn der erste Operant false ist.

Inkrement- und Dekrementoperatoren
Dies Operatoren sind eigentlich auch nur eine verkürzte Schreibweise. Diese beiden Operatoren können aber nur mit Variablen verwendet werden. Wenn man den Wert nur um 1 erhöhen will ist es mit dem Inkrementoperator möglich:

a++;

oder wenn man den Wert um 1 verringern will mit dem Dekrementoperator:

a--;

Es ist möglich den Operator Präfix (vor der Variable) oder Postfix (nach der Variable) zu verwenden. Es gibt bei dem beiden Schreibweisen Präfix und Postfix einen Unterschied bei der Auswertung.

a = 5;
b = ++a;
x = 8;
y = x--;

Die Variable b hat den Wert 6, aber die Variable y hat den Wert 8. Warum ist das so? Ganz einfach, die Variable x wird erst den Wert an die Variable y zuweisen und dann erst wird x um 1 verringert. 

Jetzt sind wir am Ende des dritten Tutorials, es war nicht gerade einfach soviele Informationen zusammenzufassen, es hat aber auch Spaß gemacht.


Donnerstag, 3. Oktober 2013

DOSBox

DOSBox ist ein kostenloser Emulator für BeOs, LinuxBeOS, Linux, Mac Os X und Windows. Dadurch ist es möglich DOS-Spiele zu spielen, die unter den heutigen Betriebssystemen nicht mehr richtig laufen.

Als erstes geht ihr auf http://www.dosbox.com und ladet euch unter Downloads die DOSBox herunter und installiert sie.

Wen man die DOSBox jetzt startet bekommt man  zwei Fenster zu sehen. Da fühlt man sich gleich wie in den guten alten DOS Zeiten.


Jetzt müssen wir ein DOS-Laufwerk emulieren, das geht mit dem Befehl mount.


Nach mount gibt man den Laufwerksbuchstaben der für das emulierte Laufwerk gültig sein soll. Dann gibt man noch das Verzeichnis an welches als DOS-Laufwerk emuliert werden soll, natürlich müssen in den Unterverzeichnissen unsere DOS-Spiele sein.


Mit c: wechseln wir auf das emulierte DOS-Laufwerk.

/
Mit dir kann man den Inhalt des Verzeichnisses anzeigen lassen es geht auch dir /w und dir /p. Mit cd und dem Verzeichnisnamen gehen wir in das Verzeichnis, hier ist es bei mir hl14-18. Mit cd.. wechselt man in das vorherige Verzeichnis zurück und mit cd\ geht man bis zum Laufwerksbuchstaben zurück.


Jetzt suchen wir uns aus dem Spieleverzeichnis die Startdatei mit der Endung EXE oder BAT heraus und geben sie ein.


Hier ist es z.B. die Datei HL.EXE. 

Mit Alt + Enter wechselt man zwischen Fenster- und Vollbildmodus. 

Wünsche jedenfalls viel Spaß beim spielen. Wenn es Probleme gibt helfe ich gerne weiter.





Dienstag, 1. Oktober 2013

Einfache Datentypen in Java

In diesem Tutorial wird es um einfache Datentypen gehen. Es ist zwar ein etwas trockenes Thema, aber es muss einfach sein, damit man etwas mehr Verständnis dafür bekommt, natürlich muss man es nicht auswendig lernen.

Ganzzahlige Datentypen

Ein Computer speichert die ganzen Zahlen in eine Folge von binären Zeichen, also 1 oder 0. Bei 1 Byte haben wir 8 Bits die uns zur Verfügung stehen, also 8 binäre Stellen. Das erste Bit benötigen wir für das Vorzeichen, uns bleiben also 7 Bits um eine Zahl darstellen zu können. Die negativen Zahlen sind durch die rechnerinternen Darstellungen um 1 größer, in diesen Fall -128. Mit 8 Bits sind also 127(positiv) + 128(negativ) + 1(Null) = 256 verschiedene Zahlen möglich darzustellen.

Der Datentyp byte ist genau 8 Bits groß. Im Allgemeinen ist dieser Zahlenbereich (-128 bis 127) viel zu klein um damit vernünftig arbeiten zu können. Deshalb gibt es in Java die weitere Arten von ganzzahligen Datentypen, die zwei, vier oder acht Byte lang sind.

Hier sind alle ganzzahligen Datentypen die es in Java gibt:


Für ganzzahlige Datentypen sind die Ziffern 0 bis 9 verfügbar. Der Compiler geht immer von einer 4 Byte großen Zahl aus, also int. Wenn man die Zahl 214783649 darstellen will muss man der Zahl ein L anhängen für den Datentyp long, also 214783649L. Ohne das L würde der Compiler einen Fehlermeldung ausgeben.

Hier zwei Beispiele:

Es ist aber auch möglich in Java oktale Zahlen (Zahlen im Achter-System) oder als hexadezimale Zahlen (Zahlen im Sechzehner-System) zu schreiben. Oktale Zahlen beginnen mit einer 0 und sind im Ziffernbereich von 0 bis 7. Hexadezimale Zahlen beginnen mit 0x, die Ziffer sind im Bereich 0 bis 9 und von A bis F.

Zwei Beispiele für Oktale und Hexadezimale Zahlen:


System.out.println ist das Selbe wie System.out.print nur mit einen Zeilenumbruch am Ende

Gleitkommatypen

In Java gibt es noch die Datentypen float und double für Gleitkommazahlen. Diese sind intern aus 32 Bits oder 64 Bits aufgebaut. Das Bitmuster ist aber etwas anders aufgebaut als der von den ganzzahligen Datentypen. Für die Gleitkommazahlen nimmt man einen Punkt (keine Komma sonst gibt der Compiler eine Fehlermeldung zurück). Es kann aber auch ein Exponent (bestehend aus einem e oder einem E sowie eine Endung von f, F, d oder D) verwendet werden. Das E steht für die anschließender Zahl X für die Multiplikation mit 10^X, d.h. die Zahl 1.2E3 steht für 1.5 * 10^3, also den Wert 1500. Bei negativen Zahlen wird vor die entsprechende Zahl ein Minuszeichen gesetzt. Bei den Wert 1500, die Zahl 1.5E-3 für 1.5 * 10^3 ergibt 0.0015. Der Compiler geht bei Gleitkommazahlen von den Typ double aus, man kann aber auch ein d oder D anhängen für den Wert double. Für float  wird ein f oder F angehängt. Es muss dazu gesagt werden bei Gleitkommazahlen kann es zu Rundungsfehlern kommen.

Hier sind die Gleitkommazahlen die es in Java gibt:


Der Datentyp char für Zeichen

In Java gibt es den Datentyp char, manchmal ist es notwendig mit Zeichen oder Buchstaben zu arbeiten. Ein Zeichen übergibt man dem Typ char mit Hochkommata, das Zeichen c wird dann so 'c' dargestellt. Der Datentyp char wird mit 16 Bits (also 2 Bytes dargestellt). Jedes Zeichen hat eine bestimmte Nummer (16 Bit Dualzahl), der sogenannte Unicode, das c hat z.B. die Nummer 99. Den Wert char kann man auch als ganzzahligen Wert auffassen, z.B. mit int i = 'c' wird der Wert 99 zugewiesen.
Der Unicode-Zeichensatz enthält auch Zeichen die nicht mit der Tastatur dargestellt werden können. Um diese in Java anzuzeigen, gibt es die Unicode-Schreibweise die mit \u beginnt und vier hexadezimale Ziffern folgen. Damit ist es möglich alle Unicode-Zeichen von \u0000 bis \uffff darstellen. Der hexadezimale Wert 63 entspricht den dezimalen Wert 99. Für Kommando oder Trennzeichen gibt es auch die Escape-Sequenzen, damit kann man statt '\u0009' auch '\t' für den horizontalen Tabulator schreiben oder für den Zeilenvorschub '\n'. Die Symbole " und ' können  nur in der Form '\"' und '\'' geschrieben werden. Das \-Zeichen kann nur in der Form '\\' geschrieben werden.

Zeichenketten

Der String besteht aus mehreren Zeichen des Datentyps char. Dei Zeichen abc können mit doppelten Hochkommata dargestellt werden "abc". 

Der Datentyp boolen für richtig oder falsch

Es gibt auch noch den Datentyp boolean für Wahrheitswerte. Beim diesen Datentyp gibt es nur wahr(true) oder falsch(false).

Implizite Typumwandlungen

Kleine ganzzahlige Datentypen werden automatisch vom Compiler in den größeren Datentyp umgewandelt, wenn sie ihnen zugewiesen werden. Es können auch Gleitkommazahlen in ganzzahlige Datentypen umgewandelt werden, aber es können Rundungsfehler auftreten. Ein float-Wert wird auch automatisch in einen double-Wert umgewandelt, wenn er den größeren Datentyp zugewiesen wird. Es ist auch eine implizite Umwandlung von char nach int, long, float oder double möglich.

Explizite Typumwandlungen

Bei einer Typumwandlung eines größeren in einen kleineren Datentyp haben wir ein Problem. Der Compiler würde uns einen Fehler ausgeben, da es dabei zu Umwandlungsfehlern kommen kann. Um den Compiler mitzuteilen, dass es die Absicht des Programmierers ist, schreibt man dann z.B. (int) 12.56 mit dem (Datentyp in Klammer)  gibt man dem Compiler an, dass das Umwandeln des nachfolgenden Bezeichners gewollt ist.

Beispiele zur expliziten Typenumwandlung:


Wenn man das Beispiel ausführt wird man bemerken dass zwei verschiedene Ergebnisse gibt. Das kommt von der Klammersetzung. In den beiden Kommentaren wird auch schon angedeutet warum es so ist. Am besten probiert man einfach Verschiedene Klammersetzungen aus um zu sehen was passiert und es auch besser verstehen kann.

Jetzt sind wir an das Ende des zweiten Tutorials angelangt. Hoffe ich konnte es verständlich erklären und dass sich kein Fehler eingeschlichen. Wenn jemand Verbesserungsvorschläge hat, kann er es mir ruhig schreiben. Ich bin schon am überlegen was dass nächste Thema ist.