Rubikin kuution tietokoneversioita on tehty maailman sivu, harvemmin kuitenkaan PHP:llä. Tässä tulee nettisivulla toimiva hiirellä pyöriteltävä kolmiulotteinen Rubikin kuutio.
Esittelysivu: http://koti.mbnet.fi/pllk/muut/rubik_p.php
Kuution palojen numerointi on:
1. 2. 3. 4. 5. 6. 00 01 02 09 10 11 18 19 20 27 28 29 36 37 38 45 46 47 03 04 05 12 13 14 21 22 23 30 31 32 39 40 41 48 49 50 06 07 08 15 16 17 24 25 26 33 34 35 42 43 44 51 52 53
Sivu 1 on kuvassa oikealla, sivu 2 vasemmalla ja sivu 3 ylhäällä. Sivu 4 on oikean kulman takana, sivu 5 vasemman kulman takana ja sivu 6 on alhaalla. Sivut 1, 3, 5 ja 6 ovat ketjutettuina toisiinsa. Sivut 2 ja 4 ovat vastatusten. Sivu 3 on siis väärinpäin sivuihin 1, 2 ja 4 nähden.
Piirtojärjestys:
1. 2. 3. 00 11 24 03 14 25 06 17 26 01 10 21 04 13 22 07 16 23 02 09 18 05 12 19 08 15 20
Kuutiossa olevat palat on tallennettu yhteen merkkijonoon, jonka pituus on 6 * 9 = 54 merkkiä. Kuution sivuja käsitellään merkkijonoina myös pyörityksissä. Jos vain tiettyä riviä pyöritetään, kuutiota pyöritetään kuitenkin ensin kokonaan ja sitten valitaan uusista paloista pyörivään riviin kuuluvat.
Skriptin monimutkaisimpia osuuksia on oikean palan laskeminen napsautetun kohdan perusteella. Tämä tapahtuu vertaamalla napsautuskohtaa palojen rajojen koordinaatteihin. Erityisen vaikea tapaus on yläsivu, jossa tuloksia saattaa muka olla useampia suorakulmioiden mennessä toistensa päälle. Tällöin oikea tulos saadaan selville laskemalla Pythagoraan lausetta soveltamalla etäisyys palan keskikohtaan ja valitsemalla etäisyyksistä pienin.
Päivitys 6.1.: Kunnollinen sekoitus
rubik_k.php
<?php // piirtää Rubikin kuution parametrina annetuin värein $koko = 200; // kuvan koko $järj = $_SERVER['QUERY_STRING']; $kuva = imagecreate($koko, $koko); // määritetään värit: // 0 valkoinen, taustaväri // 1 - 6 kuutioiden värit // 7 musta, reunusväri for ($i = 7; $i >= 0; $i--) { $väri[] = imagecolorallocate($kuva, ($i & 4) * 255, ($i & 2) * 255, ($i & 1) * 255); } // piirretään kuvan kehykset imagerectangle($kuva, 0, 0, $koko - 1, $koko - 1, $väri[7]); $yx = $koko / 2; // keskikulman x-koordinaatti $yy = $koko / 2.2; // keskikulman y-koordinaatti $kx = .9 * $koko / 3 / 3; // venytys x-suunnassa $ky = .9 * $koko / 5 / 3; // venytys y-suunnassa $ps = .9 * $koko / 2 / 3; // päätysivun pituus for ($i = 0; $i < 3; $i++) { for ($j = 0; $j < 3; $j++) { // kuution oikean sivun koordinaatit $oikea = array($yx + $j * $kx, $yy - $j * $ky + $i * $ps, $yx + $j * $kx, $yy - $j * $ky + ($i + 1) * $ps, $yx + ($j + 1) * $kx, $yy - ($j + 1) * $ky + ($i + 1) * $ps, $yx + ($j + 1) * $kx, $yy - ($j + 1) * $ky + $i * $ps); // kuution vasemman sivun koordinaatit $vasen = array($yx - $j * $kx, $yy - $j * $ky + $i * $ps, $yx - $j * $kx, $yy - $j * $ky + ($i + 1) * $ps, $yx - ($j + 1) * $kx, $yy - ($j + 1) * $ky + ($i + 1) * $ps, $yx - ($j + 1) * $kx, $yy - ($j + 1) * $ky + $i * $ps); // kuution yläsivun koordinaatit $ylä = array($yx - $j * $kx + $i * $kx, $yy - $j * $ky - $i * $ky, $yx - $j * $kx + ($i + 1) * $kx, $yy - $j * $ky - ($i + 1) * $ky, $yx - ($j + 1) * $kx + ($i + 1) * $kx, $yy - ($j + 1) * $ky - ($i + 1) * $ky, $yx - ($j + 1) * $kx + $i * $kx, $yy - ($j + 1) * $ky - $i * $ky); // piirretään kuutioiden värilliset sivut imagefilledpolygon($kuva, $oikea, 4, $väri[$järj[$kohta]]); imagefilledpolygon($kuva, $vasen, 4, $väri[$järj[$kohta + 1]]); imagefilledpolygon($kuva, $ylä, 4, $väri[$järj[$kohta + 2]]); // piirretään vastaavien sivujen reunukset imagepolygon($kuva, $oikea, 4, $väri[7]); imagepolygon($kuva, $vasen, 4, $väri[7]); imagepolygon($kuva, $ylä, 4, $väri[7]); $kohta += 3; } } header("Content-type: image/png"); imagepng($kuva); ?>
rubik_p.php
<?php // näyttää pyöritettävän Rubikin kuution // laskee valitun kuution osan hiiren koordinaateista function laskekohta($x, $y) { // näiden tietojen on oltava samat kuin piirtoskriptissä $koko = 200; $yx = $koko / 2; $yy = $koko / 2.2; $kx = .9 * $koko / 3 / 3; $ky = .9 * $koko / 5 / 3; $ps = .9 * $koko / 2 / 3; $pienin = pow($koko, 2); // pienin etäisyys yläsivun paloissa $py = false; // loppupalautusarvo // tutkitaan kaikki vaihtoehdot for ($i = 0; $i < 3; $i++) { for ($j = 0; $j < 3; $j++) { // kuution oikean sivun tarkistukset if ($yx + $j * $kx <= $x && $yx + ($j + 1) * $kx >= $x && $yy - $j * $ky + $i * $ps <= $y && $yy - ($j + 1) * $ky + ($i + 1) * $ps >= $y) { return array("o", $i, $j); } // kuution vasemman sivun tarkistukset if ($yx - $j * $kx >= $x && $yx - ($j + 1) * $kx <= $x && $yy - $j * $ky + $i * $ps <= $y && $yy - ($j + 1) * $ky + ($i + 1) * $ps >= $y) { return array("v", $i, $j); } // kuution yläsivun tarkistukset if ($yx - ($j + 1) * $kx + $i * $kx <= $x && $yx - $j * $kx + ($i + 1) * $kx >= $x && $yy - $j * $ky - $i * $ky >= $y && $yy - ($j + 1) * $ky - ($i + 1) * $ky <= $y) { // etäisyys palan keskipisteeseen $matka = pow($yx - $j * $kx + $i * $kx - $x, 2) * $kx + pow($yy - $j * $ky - $i * $ky - $ky / 2 - $y, 2) * $ky; // pienin etäisyys hyväksytään if ($matka < $pienin) { $py = array("y", $i, $j); $pienin = $matka; } } } } return $py; } // arpoo kuution palojen järjestyksen function sekoitakuutio() { // aloitustilanne $kuutio = "111111111222222222333333333444444444555555555666666666"; // pyöritysten vaihtoehdot $sivut = array("v", "o", "y"); $akselit = array("x", "y"); $suunnat = array(-1, 1); // pyöritetään sata kertaa satunnaisesta kohdasta for ($i = 0; $i < 100; $i++) { $kuutio = pyöritäriviä($kuutio, $sivut[rand(0, 2)], $akselit[rand(0, 1)], rand(0, 2), $suunnat[rand(0, 1)]); } return $kuutio; } // kiertää yhtä kuution sivua function kierrä($sivu, $suunta) { $kuvio = array("" => array(0, 1, 2, 3, 4, 5, 6, 7, 8), // ei kiertoa "v" => array(2, 5, 8, 1, 4, 7, 0, 3, 6), // vasemmalle "o" => array(6, 3, 0, 7, 4, 1, 8, 5, 2), // oikealle "y" => array(8, 7, 6, 5, 4, 3, 2, 1, 0)); // ylösalaisin foreach($kuvio[$suunta] as $k) { $uusi .= $sivu[$k]; } return $uusi; } // pyörittää koko kuutiota function pyöritäkuutiota($kuutio, $x, $y) { // ilmoittaa, mikä sivu siirretään minne ja onko kiertoa // käännöskohdat: ylävasen, keskivasen, alavasen, // yläoikea, keskioikea, alaoikea $suunnat = array(array(array("", 6, "v", 2, "", 1, "o", 4, "", 3, "", 5), array("", 4, "", 1, "o", 3, "y", 5, "y", 2, "v", 6), array("v", 1, "v", 3, "v", 4, "v", 6, "o", 5, "v", 2)), array(array("o", 1, "o", 6, "o", 2, "o", 3, "v", 5, "o", 4), array("", 2, "y", 5, "v", 3, "", 1, "y", 4, "o", 6), array("", 3, "o", 2, "", 5, "v", 4, "", 6, "", 1))); // merkkijonon aloituskohta on (sivu - 1) * 9 for ($i = 0; $i < 6; $i++) { $uusi .= kierrä(substr($kuutio, ($suunnat[$x][$y][$i * 2 + 1] - 1) * 9, 9), $suunnat[$x][$y][$i * 2]); } return $uusi; } // ilmoittaa luvun merkin (-1, 0 tai 1) function merkki($luku) { if ($luku != 0) { return $luku / abs($luku); } return 0; } // pyörittää valittua riviä function pyöritäriviä($kuutio, $sivu, $akseli, $rivi, $suunta) { // kussakin pyörityksessä muuttuvat palat $vanhat = array(array(0, 1, 2, 9, 10, 11, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 42, 43, 44), array(3, 4, 5, 12, 13, 14, 30, 31, 32, 39, 40, 41), array(6, 7, 8, 15, 16, 17, 45, 46, 47, 48, 49, 50, 51, 52, 53, 33, 34, 35, 36, 37, 38), array(0, 3, 6, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 21, 24, 36, 39, 42, 45, 48, 51), array(1, 4, 7, 19, 22, 25, 37, 40, 43, 46, 49, 52), array(2, 5, 8, 20, 23, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 38, 41, 44, 47, 50, 53), array(0, 1, 2, 3, 4, 5, 6, 7, 8, 11, 14, 17, 24, 25, 26, 27, 30, 33, 45, 46, 47), array(10, 13, 16, 21, 22, 23, 28, 31, 34, 48, 49, 50), array(9, 12, 15, 18, 19, 20, 29, 32, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 51, 52, 53)); // oikean sivun pyöritys if ($sivu == "o") { if ($akseli == "x") { $uusi = pyöritäkuutiota($kuutio, ($suunta == -1) ? 0 : 1, 1); $muutos = $rivi; } elseif ($akseli == "y") { $uusi = pyöritäkuutiota($kuutio, ($suunta == -1) ? 0 : 1, ($suunta == -1) ? 0 : 2); $muutos = 3 + $rivi; } // vasemman sivun pyöritys } elseif ($sivu == "v") { if ($akseli == "x") { $uusi = pyöritäkuutiota($kuutio, ($suunta == -1) ? 1 : 0, 1); $muutos = $rivi; } elseif ($akseli == "y") { $uusi = pyöritäkuutiota($kuutio, ($suunta == -1) ? 1 : 0, ($suunta == -1) ? 0 : 2); $muutos = 6 + $rivi; } // yläsivun pyöritys } elseif ($sivu == "y") { if ($akseli == "x") { $uusi = pyöritäkuutiota($kuutio, ($suunta == -1) ? 1 : 0, ($suunta == -1) ? 2 : 0); $muutos = 3 + $rivi; } elseif ($akseli == "y") { $uusi = pyöritäkuutiota($kuutio, ($suunta == -1) ? 0 : 1, ($suunta == -1) ? 2 : 0); $muutos = 6 + $rivi; } } // muutetaan alkutilanteeseen pyörineet palat for ($i = 0; $i < 54; $i++) { if (in_array($i, $vanhat[$muutos])) { $kuutio[$i] = $uusi[$i]; } } return $kuutio; } $kuutio = isset($_POST['kuutio']) ? $_POST['kuutio'] : sekoitakuutio(); $tila = isset($_POST['tila']) ? intval($_POST['tila']) : 0; $ak = $_POST['ak']; // kuution sekoitus if (isset($_POST['sekoita'])) { $kuutio = sekoitakuutio(); $tila = 0; } // kuvasta on napsautettu if (isset($_POST['kuva_x'])) { // selvitetään painamiskohta $pkohta = laskekohta($_POST['kuva_x'], $_POST['kuva_y']); // tila 0 = tavallinen if ($tila == 0) { // pannaan talteen aloituskohta if ($pkohta) { $ak = implode($pkohta, " "); $tila = 1; // pyöritetään koko kuutiota } else { $kuutio = pyöritäkuutiota($kuutio, intval($_POST['kuva_x'] / (200 / 2)), intval($_POST['kuva_y'] / (200 / 3))); } // tila 1 = pyörityksen aloituskohta valittu } elseif ($tila == 1) { // pyöritetään yhtä kuution riviä if ($pkohta) { $vkohta = explode(" ", $ak); if ($vkohta[0] == $pkohta[0]) { if ($vkohta[1] == $pkohta[1]) { $kuutio = pyöritäriviä($kuutio, $pkohta[0], "x", $pkohta[1], merkki($pkohta[2] - $vkohta[2])); } if ($vkohta[2] == $pkohta[2]) { $kuutio = pyöritäriviä($kuutio, $pkohta[0], "y", $pkohta[2], merkki($pkohta[1] - $vkohta[1])); } } } $tila = 0; } } // piirtoskriptin vaatima kuution osien järjestys $kuvajärj = array(0, 11, 24, 1, 10, 21, 2, 9, 18, 3, 14, 25, 4, 13, 22, 5, 12, 19, 6, 17, 26, 7, 16, 23, 8, 15, 20); foreach($kuvajärj as $k) { $kuvadata .= $kuutio[$k]; } ?> <html> <head> <title>Rubikin kuutio PHP:llä</title> </head> <body> <form action="rubik_p.php" method="post"> <table border width="500"> <tr> <td colspan="2"><h1>Rubikin kuutio</h1></td> </tr> <tr valign="top"> <td> <input type="image" name="kuva" src="rubik_k.php?<?php echo $kuvadata; ?>" </td> <td> <p>Voit pyörittää kuutiota hiirellä. Jos napsautat kuution ulkopuolelta, koko kuutio pyörii valittuun suuntaan. Kuutiossa oleva rivi pyörii napsauttamalla kahta riviin kuuluvaa palaa pyörityssuunnan mukaisesti.</p> <input type="submit" name="sekoita" value="Sekoita"> </td> </tr> </table> <input type="hidden" name="kuutio" value="<?php echo $kuutio; ?>"> <input type="hidden" name="tila" value="<?php echo $tila; ?>"> <input type="hidden" name="ak" value="<?php echo $ak; ?>"> </form> </body> </html>
Hyvä, mutta aika outo tuo rivin liikuttaminen, mutta paremminhan tuota ei voi tehdä.
Mielenkiintoinen.
Mielenkiintoinen, mutta käyttökelvoton hitaalla yhteydellä :/
Kyllä Antti osaa :)
Joko mun silmät harittaa, tai tuon kuution perspektiivissä on jotain vialla :)
Ei ole oikein käyttökelpoinen tuollaisena... Menee into :)
Kädessä pyöritellessä on paljon helpompi
Kuution mittoja voi hienosäätää mm. $ps-muuttujan avulla. :)
Sekoitukseen on tainnut eksyä bugi: kaikkia värivaihtoehtoja ei saakaan takaisin alkutilanteeseen (korjaus tulossa).
Hauska...
(mutta käyttö kelvoton hitailla aivoilla ;)
Ehkäpä siihen on syynsä, että tuo on harvemmin toteutettu PHP:lla. Pahin puute tässä versiossa on rajoittunut näkökenttä ja varsin hitaasti tapahtuva kuution kääntely. Rivien kääntely on tehty melko intuitiivisesti, mutta undo toiminto olisi varsin tarpeellinen virhesiirtojen peruutukseen.
EDIT: Hmm. back-nappi taitaa kyllä toimia undo-toimintona, joten unohda koko juttu :)
Kokeilin tehdä tuota kuutiota, mutta en päässyt kuin puoleen väliin, jonka jälkeen tein pari siirtoa, jotka tulkittiin väärin ja onnistuin sekoittamaan kuution niin pahasti, että olisi pitänyt aloittaa alusta.
lainaus:
Hauska...
(mutta käyttö kelvoton hitailla aivoilla ;)
Siispä täysin käyttökelvoton koodinpätkä. ;)
Omituinen perspektiivi ärsyttää...
Ratkaisin ton kuution ( ~ 45 min), mutta käytin oikean kuution mukana tulevia ohjeita :P
Pari kertaa tuo sekosi (tulkitsi väärin painalluksen), mutta onneksi back auttaa
On joo ihan hauska :D
Nämä hiirellä pyöritettävät eivät toimi mac:koneiden kanssa... Kun nämä tunnistavat tämänkin kuvaksi ja aina kun siitä ottaa kiinni kone meinaa tallentaa kuvan rubiikinkuutiosta siirrettyyn paikkaan esim. työpöydälle :)
Suunnilleen 5 minuuttia meni ensimmäisellä yrityksellä. Toteutuksen voisi tehdä paljon yksinkertaisemmin ja välillä klikkailut tulkitaan väärin, mutta ihan hauska esimerkki.
Aihe on jo aika vanha, joten et voi enää vastata siihen.