# Zufällige Zeichenfolge erstellen mit Möglichkeit der Subtraktion



## Java- (22. Nov 2014)

Hallo,

ich bin gerade dabei ein Spiel zu programmieren.

Kurz zur erklärung:

In dem Spiel gibt es 11 Figuren. 10 davon nennen wir mal M und 1 nennen wir mal O

Ziel ist es das O nicht zu bekommen, da man sonst verloren hat

Also sollen sich diese Figuren in zufälliger Reihenfolge nebeneinander stellen

Das es bspw so aussieht : MMMMOMMMMMM

jetzt kann man sagen ich nehme 2 Figuen rechts vom O

Also müssen im nächsten zug rechts 2 figuren fehlen.

Nur wie mache ich zunächst diese Zufällige reihenfolge der zeichen

und wie subtrahiere ich sie dann im nachhinein weg ?

Achtung wir hatten bisher keine Arrays und es sollte am Besten auch ohne gelöst werden.


----------



## Ruzmanz (22. Nov 2014)

In Java gibt es die Klasse "Random" und dein String ist nichts anderes als ein char[]. Mit "MM...OMM".charAt(i) kannst du auf die einzelnen Positionen zugreifen.


----------



## Java- (22. Nov 2014)

ok danke für die Antwort den 2. Teil habe ich verstanden.

Wie ich jetzt diese Reihenfolge zufällig erstelle leider nicht.
Kannst du mir das bitte noch etwas ausführlicher erklären ? Das wäre echt gut


----------



## Gucky (22. Nov 2014)

Das ihr diese Aufgabe ohne Arrays lösen sollt macht das Ganze nur unnötig schwer. Frag noch mal nach, ob das wirklich ohne Arrays gelöst werden soll.

Strings sind in Java immutable, somit kannst du keine Zeichen einfach "wegsubtrahieren". Du müsstest den String neu erstellen. Daher musst du entweder mit 11 Variablen oder einem Array arbeiten.

Ohne Arrays könntest du 11 Variablen f1, f2...f11 erstellen und zum Initialisieren diese Variablen zu einer bestimmten Wahrscheinlichkeit mit O befüllen. Wurde eine Variable mit O befüllt, so wird ein flag (Schalter) gesetzt und sämtliche anderen Variablen werden mit M befüllt. Also in etwa so:


```
char f1;
...
char f11;

Random r = new Random(System.currentTimeMillis()); //Neues Objekt vom Typ Random
boolean schonO = false; //Der Schalter
int randZahl = r.nextInt(2); //Neue Zufallszahl

if (!schonO && randZahl == 1){//Wenn schonO == false und randZahl == 1
  f1 == 'M'
} else if (!schonO && randZahl == 0){ //Sonst wenn schonO == false und randZahl == 0
  f1 == 'O';
  schonO == true;
} else { //Sonst
  f1 = 'M';
}

randZahl = r.nextInt(2);
//Und so weiter...
```

Mit Arrays sähe das Ganze so aus:

```
char figs = new char[11]; //Array vom Typ char
Random rand = new Random(System.currentTimeMillis()); //Neues Objekt vom Typ Random
int randZahl; 
int i; //Schleifenvariable vor der Schleife, da sie in der Nächsten noch gebraucht wird
boolean schonO = false;

for (i = 0; i < figs.length && !schonO; i++){
  randZahl = rand.nextInt(2);//Neue Zufallszahl
  if (randZahl == 0){//wenn randZahl == 0
    figs[i] = 'O';
    schonO = true;
  } else { 
    figs[i] = 'M';
  }
}

for ( ; i < figs.length; i++){ //verbleibende Einträge werden befüllt
  figs[i] = 'M';
}
```

Das Anzeigen ginge so ohne Arrays:

```
if (f1 != 0){
  System.out.print(f1);
}
...
if (f11 != 0){
  System.out.print(f11);
}
```

und so mit Arrays:


```
for (int i = 0, i < figs.length; i++){
  if (figs[i] != 0){
    System.out.print(figs[i]);
  }
}
```

Und das Wegsubtrahieren will ich gar nicht erst ohne Arrays anfangen, weil du sämtliche Fälle behandeln musst, die auftreten können.


----------



## Java- (22. Nov 2014)

ok danke 

man kann es mit arrays machen, allerdings haben wir diese noch nicht thematisiert.
und beim erstellen der aufgabe hatte er auch geplant das es ohne arrays geht.

ist es eigtl nicht möglich einfach zu sagen man hat einen String "M M M M M M M"
und ein Char 'O'

und man möchte einfach nur das O  in den String an zufälliger position einfügen ?


----------



## Gucky (22. Nov 2014)

Witzig. Diese Frage habe ich gerade hier beantwortet. Ihr beide seid euch ziemlich ähnlich.

Mir fiele kein guter Ansatz ohne Arrays oder StringBuilder ein.


----------



## Java- (22. Nov 2014)

Haha danke, hatte das vorher dort gefragt aber bisher keine Antwort bekommen ^^

ich denke ich werde mir die Arrays einfach selbst aneignen und diese dann dafür verwenden .

vielen dank für die Hilfe


----------



## Ruzmanz (22. Nov 2014)

Java- hat gesagt.:


> und man möchte einfach nur das O  in den String an zufälliger position einfügen ?



Zuerst füllst du deinen String mit deinen 'M's:

String s = "MMMMMMMMM"
Dann suchst du eine zufällige Zahl "int zahl = new Random().nextInt(s.length()-1)"
Mit s = s.substring(0, zahl) + "O" + s.substring(zahl, s.length()); baust du dir einen neuen String zusammen.
Sofern du ein "M" rechts entfernen willst: s = s.substring(s.length()-1)
Sofern du ein "M" links entfernen willst: s = s.substring(1);



Gucky hat gesagt.:


> ...



Nein.


----------



## Gucky (22. Nov 2014)

Das ginge auch aber ob das so schön ist...

Da muss er ständig neue Strings allozieren, die zwar wieder entfernt werden aber erzeugt wurden sie trotzdem. Das wären allein zum Initalisieren 5 Strings. Wird ein M entfernt, so ist es noch einmal einer mehr. Das sind insgesamt, wenn alle Ms weg sind 5 + 10 = 15 Strings.


Aber ich lasse mich gerne vom Gegenteil überzeugen.


----------



## Ruzmanz (22. Nov 2014)

Wenn du "new Random(123).nextInt(2)" aufrufst, dann bekommst du immer den selben Wert zurück. Nehmen wir an du loggst dich bei deiner Bank um 14:05 ein. Dann könnte ich mit Bruteforce deine Zufallszahl locker erraten und deinen Schlüssel knacken ... belasse es bei new Random().

Habe eine nette Applikation gebastelt. Immer wenn die Konstelation "MMMMMMMMMMO" auftritt bekommst du 100(!!!)€ andernfalls zahlst du nur einen Euro. 


```
public class Spiel {
	public static void main(String[] args) {
		new Spiel(100, 2000);
	}
	
	public Spiel(int runden, int vermögen) {
		if(runden < 1) throw new IllegalArgumentException();
		
		while(runden > 0) {
			if("MMMMMMMMMMO".equals(glücksrad())) {
				vermögen += 100;
			} else {
				vermögen -= 1;
			}
			
			runden--;
		}
		
		System.out.println("Dein Vermögen: " + vermögen);
	}
	
	public String glücksrad() {
		char[] figs = new char[11]; //Array vom Typ char
		Random rand = new Random(); //Neues Objekt vom Typ Random
		int randZahl;
		int i; //Schleifenvariable vor der Schleife, da sie in der Nächsten noch gebraucht wird
		boolean schonO = false;
		 
		for (i = 0; i < figs.length && !schonO; i++){
		randZahl = rand.nextInt(2);//Neue Zufallszahl
		if (randZahl == 0){//wenn randZahl == 0
		figs[i] = 'O';
		schonO = true;
		} else {
		figs[i] = 'M';
		}
		}
		 
		for ( ; i < figs.length; i++){ //verbleibende Einträge werden befüllt
		figs[i] = 'M';
		}
		
		return new String(figs);
	}
}
```

PS: Keine Sorge. Das ist wie im Casino. Du darfst so oft spielen wie du willst und wenn es mal eng wird kann ich dir auch einen Kredit anbieten.


----------



## Gucky (22. Nov 2014)

System.currentTimeMillis() liefert die seit dem 1.1.1970 vergangenen Millisekunden in einem long. Die werden, glaube ich, 17 mal die Sekunde aktualisiert und dadurch verändert.

Da mein Guthaben immer wieder auf 2000 gesetzt wird, brauche ich keinen Kredit. Vielleicht sollte ich das Spiel spielen, alles ausgeben und es erneut spielen. Alle meine Geldprobleme wären gelöst.



Ich bin auch nicht Gott und selbst ich mache mal einen Fehler oder schlage etwas vor, was zu kompliziert ist.
Anderer Vorschlag, ebenfalls mit Arrays:


```
char[] figs = new char[11];
for (int i = 0; i < figs.length; i++){
  figs[i] = 'M';
}
figs[new Random().nextInt(figs.length)] = 'O';
```

Damit brauchst du keine 15 Strings mehr und das Entfernen ist auch relativ einfach. Du läufst mit einer Schleife von "unten" oder von "oben" durch das Array, suchst nach dem ersten Eintrag, der nicht 0 ist und setzt ihn auf 0 (, was einem entfernten Zeichen entspricht).


----------



## JCODA (22. Nov 2014)

Man benötigt doch gar keine Arrays hierfür. 
1) Man würfle sich eine zufällige Zahl in einem Intervall. 
2) Man legt sich eine untere Schranke ( init = 0) und eine obere Schranke (init = Intervalllänge) an. 
3) Sollte man rechts entfernen, verringert man die obere schranke, falls links, erhöht man die untere schranke. 
4) Das Ganze läuft dann solange, wie gilt: untere Schranke < zufällige Zahl < obere Schranke.


----------



## Ruzmanz (22. Nov 2014)

> Ich bin auch nicht Gott und selbst ich mache mal einen Fehler oder schlage etwas vor, was zu kompliziert ist.



Das was du gemacht hast ist / war kompliziert und daraus resultieren die Fehler. Das kann man einfacher lösen, indem man z.B. auf Performance verzichtet. Einfacher bedeutet, dass der Quellcode Lesbarer / Wartbarer ist und man weniger Fehler macht, bzw. diese leicht identifizieren kann.



> Damit brauchst du keine 15 Strings mehr und das Entfernen ist auch relativ einfach.



Wegen den 15 Strings (habe nicht nahgezählt) werde ich sicherlich nicht schlecht schlafen und sehe auch überhaupt keinen Grund zu "optimieren" und dabei die Aufgabenstellung (-> keine Arrays) zu missachten. Evtl. fällt dir jetzt auf, dass dein neuer Code nicht mehr mit 11 char-Variablen funktioniert, außer du baust so tolle Konstrukte:


```
int randomInt = ...
switch(randomInt) {
  case 0: c1 = 'O' break;
  case 1: c2 = 'O' break;
  ...
}
```


----------



## Gucky (23. Nov 2014)

Das war ja nicht die Aufgabenstellung, wie der TO herausgefunden hat. 
Solche ein Konstrukt hatte ich nicht vor. Das ist mehr als hässlig. Aber das ist sowieso hinfällig, da JCODA eine Möglichkeit gepostet hat, die besser ist, als unsere beiden zusammen.


----------



## Java- (25. Nov 2014)

Vielen dank für die vielen antworten.

Nur komme ich jetzt nicht mehr so ganz mit, bei den vielen möglichkeiten/versuchen die gepostet wurden.
Das von JCODA klingt schonmal gut, nur soll sobald ein Buchstabe von einer Seite gewählt wurde dort ein "-" anstelle des Buchstaben erscheinen.

Leider habe ich immernoch nicht verstanden, wie ich jetzt am Besten die Anfangskonstellation mit dem "O" an zufälliger Stelle mache :S

Sorry dafür, ich weiß dass ihr euch schon viel Mühe gegeben habt, bin nur Leider noch ein Anfänger in Sachen Java


----------



## Gucky (25. Nov 2014)

Das geht trotzdem.
Du kennst die Grenzen (0;11) und wenn die untere Grenze 3 ist, gibst du eben 3 mal "-" aus.


----------



## Java- (25. Nov 2014)

ok und wie konstruiere ich jetzt am besten die Anfangskonstellation ?
kannst du mir da bitte ein code beispiel geben


----------



## Gucky (25. Nov 2014)

Ein bisschen Eigeninitiative würde ich mir schon wünschen. Ich werde dir nicht alles vorkauen.




Spoiler: Wenn du es nicht abwarten kannst



Du hast drei Variablen. In eine kommt eine 0, in eine Andere kommt eine 11 und in die Dritte kommt zufällig ein ganzzahliger Wert zwischen -1 und 12.


----------



## Java- (30. Nov 2014)

ok ich bin jetzt mit dem Spiel soweit fertig, also läuft alles ohne Probleme.
Nun würde ich den Bot nur etwas intelligenter machen wollen, indem er erst checkt ob er durch seinen (per zufall generierten) Zug verlieren würde und wenn ja er dann einfach noch einen zug generiert.

ich hatte mir überlegt das mit ner if zu machen also sobald der wert für das O < 0 wird => nochmal zufälligen Zug machen.

allerdings ist da das problem, dass er ja dann den bereits gekürzten string nimmt und dann im neuen zug nochmals kürzt.. (Hoffe das war verständlich).

deswegen die Frage, ob es irgendwie möglich ist die Stringkürzung sozusagen rückgängig zu machen ?


----------



## Ruzmanz (30. Nov 2014)

Habe die Frage nicht ganz verstanden. Rückgängig kannst du die Stringkürzung nicht machen. Du bist aber nicht gezwungen deine Änderung zu speichern. Strings sind immutable. D.h. du kannst sie gar nicht verändern. Beispiel:


```
String s = "ABCDF";
s.substring(2); // s wird nicht geändert.

if("ABC".equals(s.substring(2))) { // Vergleich von "ABC" mit "CDF"
  s = s.substring(2); // Zuweisung findet nicht statt, da if-Bedingung nicht erfüllt.
}

System.out.println(s); // Ausgabe: "ABCDEF"
```


----------



## Java- (1. Dez 2014)

hat sich erledigt habe es über eine zusätzliche variable und neue methode gelöst


----------

