[c] gra w węża - problem z generowaniem liczb losowych

0

Zacznę może od tego, że jest to pierwszy w życiu program, który napisałam w jakimkolwiek języku, nie licząc "Hello world"...😕
C nie znam w ogóle (w sumie innych języków też nie), ale stwierdziłam, że ambitnie zabiorę się za napisanie węża samemu na zaliczenie, więc wyszukiwałam sobie różne elementy, żeby jakąś tę grę skonstruować.

Możecie wyśmiać ten pseudo-kod, sama widzę, że można to było napisać o wiele ładniej i prościej, ale już nie mam siły i czasu tego zmieniać :P

Do rzeczy:
wąż chodzi, można nim sterować, powiększa się, kiedy coś zje, umiera kiedy trzeba ;)
Problem jest z jedzeniem. Mimo, że próbowałam już na kilka sposobów wygenerować je losowo, cały czas pojawia się w tym samym punkcie...
Ewentualnie dla skończonej liczby przypadków są to różne punkty.
Co zrobić, żeby tak nie było?

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <termios.h>
#include <unistd.h>
#include "kbhit1.h"
#define SZEROKOSC 70
#define WYSOKOSC 22


struct wezyk {
	int x;
	int y;
};

int dlugosc;
struct wezyk waz[2000];
short koniec, kierunek;
int znak;

int mojgetch(void);

int main() {
	koniec = 0;
	int i,j,k;
	short lub;
	int a=5, b=7;
	kierunek=4;
	dlugosc = 7;
	srand(time(NULL));
	for (i=0;i<dlugosc;i++){
		waz[i].x=13 + dlugosc-i;
		waz[i].y=10;
	}
	while (koniec==0) {
		system("clear");
		for (i=1;i<(WYSOKOSC + 1);i++){ //rysowanie weza + ramki
			for (j=1;j<(SZEROKOSC + 1);j++){
				lub=1;
				if (i==1 || i==WYSOKOSC || j==1 || j==SZEROKOSC)
					printf("#");
				for (k=0;k<dlugosc+1;k++){
					if (waz[k].x==j && waz[k].y==i){
						printf("O");
						lub=0;
						break;
					}
				}
				if (lub==1 && i!=1 && j!=1 && i!=WYSOKOSC && j!=SZEROKOSC) {
					if (i==a && j==b) printf("*");
					else printf(" ");
				}
			}
			printf("\n");
		}
		if (a == waz[0].x && b==waz[0].y){ //wpadanie na jablko
			dlugosc++;
			a = (2 + rand()) / SZEROKOSC - 3;
			b = (2 + rand()) / WYSOKOSC - 3;
		}
	usleep(100000); 
		if (kbhit())
			znak=mojgetch();
	if (znak=='w' && kierunek!=3)
		kierunek=1;

		else if (znak=='a' && kierunek!=4)
			kierunek=2;

		else if (znak=='s' && kierunek!=1)
			kierunek=3;

		else if (znak=='d' && kierunek!=2)
			kierunek=4; 

		for (i=dlugosc;i>0;i--){ //ruch weza
			if (waz[0].x==waz[i].x && waz[0].y==waz[i].y)
				koniec=1;
			waz[i].x=waz[i-1].x;
			waz[i].y=waz[i-1].y;
		}
		if (kierunek==1)
			waz[0].y=waz[0].y - 1;
		else if (kierunek==2)
			waz[0].x=waz[0].x - 1;
		else if (kierunek==3)
			waz[0].y=waz[0].y + 1;
		else if (kierunek==4)
			waz[0].x=waz[0].x + 1;
		if (waz[0].y==WYSOKOSC || waz[0].y==1 || waz[0].x==1 || waz[0].x==SZEROKOSC)
			koniec=1;
	}

}

int mojgetch(void)
{
	struct termios oldt,newt;
	int ch;
	tcgetattr( STDIN_FILENO, &oldt );
	newt = oldt;
	newt.c_lflag &= ~( ICANON | ECHO );
	tcsetattr( STDIN_FILENO, TCSANOW, &newt );
	ch = getchar();
	tcsetattr( STDIN_FILENO, TCSANOW, &oldt );
	return ch;
}

//q: nie zdziwilo Cie, ze po uzyciu taga [ CODE ] kod sie nie pokolorowal????

0
(2 + rand()) / SZEROKOSC - 3

rand zwraca wartosc typu INT, np. 125 albo 30 albo 15
2+rand = 127 albo 32 lub 17
/SZEROKOSC czyli /70 = 1 albo 0 albo 0

jak rozpatrzysz podobne przypadki dla innych wartosci ktore moze rand zwrocic (a jest to 0...RAND_MAX-1) to okaze sie, ze Twoj wypadkowy generator punktow jest dosc ograniczony.

co prawda ciezko mi powiedziec czemu jest malo losowy i czemu najwyrazniej nie pokrywa calego spreadu, ale jest kiepski..

1' uwazaj na dzielenie calkowite.. ono doslownie obcina przypadki i powoduje powstawanie 'blokow' tych samych wartosci
2' zamiast dzielenia, lepiej uzywac reszty: rand() % szerokosc --- w efekcie z definicji od razu masz ograniczenie wynikow do (0...szerokosc-1), a i rozrzut jest minimalnie lepszy niz 1'. teoria jednak mowi, ze przy zlym generatorze bazowym, Twoj generator-modulo moze byc heh, czasem wrecz bezuzytecznie generowac bardzo malo losowe wartosci
3' rozpatrz uzycie zmiennoprzecinkowego: (((double)rand())/RAND_MAX)*SZEROKOSC -- w efekcie NIE tworzysz nowego generatora bazujacego na starym, a jedynie dokonujesz przetlumaczenia jego wynikow na interesujaca Cie postac. operacje sa powolniejsze niz 1' i 2' razem wziete, ale niezauwazalnie w wiekszosci przypadkow i.... nie ryzukujesz popsucia sobie losowosci

  • oczywiscie, pamietaj o dodaniu sobie 1 zeby miec wyniki od 1 a nie od 0..
0

ok, już znalazłam błąd...:P
nie chodziło o losowanie, tylko o warunki współrzędnych przy wyświetlaniu pokarmu...;)
dzięki w każdym razie :)

1 użytkowników online, w tym zalogowanych: 0, gości: 1