• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

[JAVA] Problem z generatorem r.nextInt(int n);

Object Storage Arubacloud
+1 głos
308 wizyt
pytanie zadane 20 czerwca 2017 w Java przez embid123 Użytkownik (630 p.)
edycja 20 czerwca 2017 przez embid123

Witam, dziś napotkałem dosć dziwny błąd... Mianowicie generator pseudolosowy losuje mi lekko poza przedziałem. Przykładowo mam tablice o długości 11, i chcę by losowało do niej numerek od 1 do 11. Stwarzam obiekt klasy random i metodą nextInt losuję. r.nextInt(długość-1)+1;
Tu zamieszczę kod, wyszczególnię linijki, w których moim zdaniem coś nie gra. 

public void okretyCPU(String[][] poleCPU, int[] iloscStatkow) {
		Random r = new Random();

		do {
			for (int n = 1; n < iloscStatkow.length; n++) { // różne statki
				for (int m = 1; m <= iloscStatkow[n]; m++) { // te same statki
					for (int k = 1; k <= n; k++) { // po ilości masztów

						do {
							sprawdz = false;
							warunek = true;
							
							a = r.nextInt(poleCPU.length-1)+1; //<----------------------------
							b = r.nextInt(poleCPU[0].length-1)+1; //<-----------------------------------
							
							if (k != 1) {
								konwersja(propozycje2.get(r.nextInt(propozycje2.size())));
							}

							if ((!uzyte2.contains(konwersja2(a, b)) && propozycje2.contains(konwersja2(a, b)))
									|| (k == 1 && !(uzyte2.contains(konwersja2(a, b))))) {
								outerLoop: for (int i = a - 1; i <= a + 1; i++) {
									for (int j = b - 1; j <= b + 1; j++) {

										if ((i >= 1 && i <= (poleCPU.length - 1)) && j >= 1
												&& j <= (poleCPU[0].length - 1)) {
											if (poleCPU[i][j].equals(" ")) {
												sprawdz = true;
											} else if (poleCPU[i][j].equals("X")
													&& !(uzyte2.contains(konwersja2(i, j)))) {
												sprawdz = false;
												warunek = false;
												break outerLoop;
											}
										}
									}
								}
							} else if (uzyte2.contains(konwersja2(a, b))) {
								//System.out.println("Na tej pozycji znajduje sie już statek!");
								warunek = false;
							} else if (!uzyte2.contains(konwersja2(a, b)) && !(propozycje2.contains(konwersja2(a, b)))
									&& k != 1) {
								//System.out.println("Maszty statku muszą znajdować sie koło siebie!");
								warunek = false;
							}
							
							
						} while (sprawdz == false);
						System.out.println(a);
						System.out.println(b);
						poleCPU[a][b] = postawMaszt();//<-----------indeks za duży 
						uzyte2.add(konwersja2(a, b));
						propozycje2.remove(tekst);
						for (int l = -1; l <= 1; l += 2) {
							if (!(propozycje2.contains(konwersja2(a + l, b)))
									&& !(uzyte2.contains(konwersja2(a + l, b))))
								propozycje2.add(konwersja2(a + l, b));
							if (!(propozycje2.contains(konwersja2(a, b + l)))
									&& !(uzyte2.contains(konwersja2(a, b + l))))
								propozycje2.add(konwersja2(a, b + l));
						}

						if (propozycje2.isEmpty() && k != iloscMasztow) {
							for (int i = (3 - 2); i < poleCPU.length; i++) {
								for (int j = 1; j < poleCPU.length; j++) {
									poleCPU[i][j] = " ";
									sprawdz3 = false;
								}
							}
						}

					}
					propozycje2.clear();
				}
			}
			
			if (sprawdz == false){
				for(int i=1; i<poleCPU.length; i++){
					for(int j=0; j<poleCPU[i].length; j++){
						poleCPU[i][j] = " ";
					}
				}
				uzyte.clear();
			}
				
			
		} while (sprawdz3 == false);
		
	}

Obiekt klasy Random losuje mi o 1 za dużo i próbuje wcisnąć indeks 11 do tablicy i wszystko się sypie. 

3 odpowiedzi

+1 głos
odpowiedź 20 czerwca 2017 przez adas94 Nałogowiec (29,200 p.)
Jeżeli masz tablicę o długości 11 tzn, że posiada ona indeksy od 0 do 10.

Używając funkcji nextInt(dlugosc-1)+1; - podajesz właściwie przedział od 0 do 9 i do wyniku dodajesz 1, a więc od 1 do 10.

Jeżeli chcesz, aby losowało w przedziale tablicy to : nextInt(dlugoscTablicy);

Natomiast jeżeli chcesz, aby z jakichś względów losowało przedział 1 do 11 przy 11 elementowej tablicy to : nextInt(długoscTablicy)+1;
komentarz 20 czerwca 2017 przez embid123 Użytkownik (630 p.)
Po prostu chcę, by losowało od 1 do 10. czyli robię r.nextInt(dlugosc-1)+1; A co mi konsola wypluje jak tak zrobie:

10
1
10
1
9
2
6
1
6
2
5
4
6
3
6
3
5
3
4
5
10
5
11
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 11
    at RozmieszczenieStatkow.okretyCPU(RozmieszczenieStatkow.java:167)
    at graWStatki.main(graWStatki.java:40)

(te randomowe cyferki to właśnie wrzutka na konsole wartości  a i b)
+1 głos
odpowiedź 20 czerwca 2017 przez Aisekai Nałogowiec (42,190 p.)
Tak jak Ci adas94 napisał. Indeksowanie tablic zaczyna się od 0.

Jeżeli będziesz chciał wylosowac liczbę, to losujesz ja z zakresu [0,dlugoscTablicy). Jeżeli chcesz pokazać, ew. zrobić żeby użytkownik wprowadzał 1, a program by Ci sprawdzał dla 0 czy jest tam statek czy cokolwiek to odejmij 1 od tej jedynki.

Btw w code istnieje coś takiego jak Java. W dodatku (przynajmniej dla mnie) wrzucasz w cholerę niepotrzebnego kodu, a nie wrzucasz kodu z  funkcji. Co robi konwersja2()? Itd
komentarz 20 czerwca 2017 przez embid123 Użytkownik (630 p.)
edycja 20 czerwca 2017 przez embid123

1. Pole do gry w statki zorganizowałem tak, by w 1 rzędzie były wypisane 1, 2, 3, 4, 5, ... a w 1 kolumnie a b c d e ...    Chcąc zrobić pole do gry 10x10 używam tablicy 11x11 by nagłówki mieć. No i wiem, ze indeksowane od 0 są. Powiem Ci że to moje rozwiązanie nawet wygodne jest. Indeksy z zerami są nagłówkami i ich nie ruszam. A chcąc uderzyć w pole A1, odwołuje się do komórki 1,1

2. Umknęło mi wrzucenie tej javy, poprawione.

3. konwersja2(a, b) zmienia mi wartości a, b (czyli powiedzmy 1, 1) ciąg znaków String (na A1).
postawMaszt() stawia mi na macierzy X w miejscu o kordach a, b, czyli robię tab[a][b] = postawMaszt();

private String konwersja2(int a, int b) {
		return tekst2 = Character.toString((char)(a+64)) + Integer.toString(b);
	}

	private String postawMaszt() {
		return "X";
	}


4. Co do ilości kodu... według mnie również za dużo, jednak pisząc niejedno pytanie, proszono mnie o załączanie całości kodu a nie urywków.

1
komentarz 20 czerwca 2017 przez Aisekai Nałogowiec (42,190 p.)
Sam generator powinien działać ok. Możesz jeszcze dac żeby pokazywał a i b, n m k  po wylosowaniu b. Wtedy będziemy wiedzieć czy ten błąd występuje zawsze w tym samym miejscu, czy generator dobrze losuje i czy nigdzie nie jest modyfikowana wartość a albo b. Bo jeszcze zakładam możliwość że a lub b są gdzieś modyfikowane przez przypadek.
komentarz 20 czerwca 2017 przez embid123 Użytkownik (630 p.)
edycja 20 czerwca 2017 przez embid123
to zaraz wrzuce na wklejke zawartość konsoli

 

@Edit: zły trop. Wystarczyło że ledwo 2x puściłem i widac różnicę:

http://www.wklejto.pl/286249

http://www.wklejto.pl/286252

 

Może jakiś składnik mojego kodu coś miesza z a  i b nim dochodzi do wstawienia X?

 

Mam tu głównego podejrzanego:

 outerLoop: for (int i = a - 1; i <= a + 1; i++) {

czy to nie zmienia wartości zarówno i jak i a?

http://www.wklejto.pl/286278 coś mi jednak podmienia, no ale dziwne że aż o 6 zmienia.
0 głosów
odpowiedź 20 czerwca 2017 przez embid123 Użytkownik (630 p.)
Tam ma być numerek od 1 do 10 - chodziło o przedział [1,11). Co do metod typu konwersja2(), postawMaszt() to działają na 100% prawidłowo- mam napisaną bliźniaczą metodę dla gracza i działa jak należy.

Podobne pytania

0 głosów
1 odpowiedź 253 wizyt
pytanie zadane 21 maja 2021 w Java przez Fishu Nowicjusz (150 p.)
0 głosów
1 odpowiedź 445 wizyt
pytanie zadane 15 listopada 2018 w Java przez allenkun Początkujący (400 p.)
0 głosów
1 odpowiedź 230 wizyt
pytanie zadane 14 lutego 2018 w Java przez kingkushlee Gaduła (3,960 p.)

92,576 zapytań

141,426 odpowiedzi

319,652 komentarzy

61,961 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...