Olen tekemässä peliä jossa kaikilla pelaajilla on rankki. Kun pelaaja painaa play nappia niin se hakee tietokannasta kaikki pelaamattomat pelit ja vaitsee sieltä itselleen lähimpänä rankkia olevan vastustajan. Tässä on kaksi ongelmaa. Ensimmäinen on se että en tiedä miten pystyn hakemaan lähellä olevan muuten kuin että käyn koko listan läpi ja katson yksitellen kenellä on yksi piste vähemmän tai enemmän ja jatkan niin pitkään kunnes joku löytyy. Toinen ongelma on se että jos pelissäni olisikin vaikka 1,000,000 pelaamatonta peliä niin kaikkien niiden hakeminen serveriltä varmasti hidastaisi sitä ja kestäisi pelaajaltakin kauan. Ajattelin että voisinko jollain sql komennolla hakea suoraan tietokannasta pelaajan joka on lähellä omaa rankia.
esim.
Oma rank: 1000
Etsii pelin jossa vastustajan rankki on mahdollisimman lähellä omaa.
Löytää pelaajan jonka rank on 1025
Monessa tietokannassa on itseisarvon laskentaan joku ABS-funktio tai vastaava. Siten voit koettaa jotain tyyliin
SELECT TOP 1 FROM TAULU WHERE hakuehdot ORDER BY ABS( rankki - omarankki )
Kokeilin osoitteessa https://www.w3schools.com/sql/trymysql.asp?
SELECT * FROM Customers WHERE ABS(postalcode - 13000) < 1000 ORDER BY ABS(postalcode - 13000)
Sori mutta en ihan viellä ymmärtänyt. Jos minulla on esim. tietokanta jossa on nimi, salasana ja rank. Sitten katson että oma rank on 10 ja yritän etsiä mahdollisimman lähellä olevan (ylös ja alas päin) rankin.
SELECT * FROM Customers WHERE ABS(postalcode - 10) < 1000 ORDER BY ABS(postalcode - 10)
Mitä sijoitan tuon tuhannen paikalle vai menikö tämä edes oikein? Onko tuossa ideana että tuo hakee kaikki joilla rank on tuhat yli 10 tai alle 10 vai mitä se tarkoittaa?
E1ss kirjoitti:
SELECT * FROM Customers WHERE ABS(postalcode - 10) < 1000 ORDER BY ABS(postalcode - 10)Mitä sijoitan tuon tuhannen paikalle vai menikö tämä edes oikein? Onko tuossa ideana että tuo hakee kaikki joilla rank on tuhat yli 10 tai alle 10 vai mitä se tarkoittaa?
Tuo koodi etsii kaikki postalcodet, jotka eroavat kympistä alle tuhannella. Kannattaa kerrata itseisarvon käsite. Lauseke |a-b| < c tarkoittaa, että a:n ja b:n etäisyys lukusuoralla on alle c:n päässä toisistaan. Itseisarvoa käytetään mittaamaan juuri haluamaasi asiaa eli arvoa, joka on mahdollisimman lähellä haluamaasi rankkia.
Katsotaanpa sitten koodia
SELECT TOP 1 FROM TAULU WHERE hakuehdot ORDER BY ABS( rankki - omarankki )
Jos sinulla on siis rank = 10 ja kannassa vaikkapa rankit 7, 8, 9, 11, 12, 14, niin abs(rankki-omarankki) saa arvot |7-10|=3, |8-10|=2, |9-10|=1, |11-10|=1, |12-10|=2 ja |14-10|=4. Sitten erotukset järjestetään: 1, 1, 2, 2, 3, 4 ja valitaan pienin.
Tuohon kyselyyn pitäisi lisätä joku tarkastus, että ei valita itseä vastustajaksi, eli siihen pitäisi laittaa joku id-tarkastus vielä. En tiedä, miten olet kannassasi yksilöinyt eri pelaajat.
Käytännössä MySQL:llä kysely voisi näyttää tältä (kunhan sijoitat siihen arvot oma_id ja oma_rankki):
SELECT * FROM pelaaja WHERE pelaaja.id != oma_id ORDER BY ABS(pelaaja.rankki - oma_rankki) ASC LIMIT 1
Jos haluat mukaan satunnaisuutta, voit valita kyselyllä monta riviä (vaikka LIMIT 10) ja arpoa sitten koodissa niistä.
En tiedä miksi tämä ei toimi
$kysely = $yhteys->prepare("SELECT * FROM games WHERE id != ? ORDER BY ABS(? - ?)"); $kysely->execute(array(1, 10, 1500));
Eli haarukka on 10 ja oma rankki 1500 mutta se vain tulostaa koko listan id:n perusteella (eli 1,2,3...) läpi vaikka listalla ei ole yhtäkään sellaista joka olisi 10 päässä 1500. Mitä teen väärin?
Koska sinun pitää järjestyskriteeriossa aina olla ABS(rankki-omarankki) eli muuttujien nimet. Yrität järjestää kriteerin ABS(10-1500)=1490 mukaan. Mutta ei kuulosta kovin järkevältä, että sinulla olisi järjestyskriteerinä joku vakio.
Aihe on jo aika vanha, joten et voi enää vastata siihen.