Utwórz minigrę z profilem użytkownika


49

Wczoraj natknąłem się na bardzo sprytną rzecz.

gra profilowa minitech w kółko i krzyżyk

Tak, to działająca implementacja kółko i krzyżyk na stronie profilu użytkownika, od @minitech. Oczywiście w momencie, gdy go zobaczyłem, musiałem dokonać inżynierii wstecznej jego pomysłu i poprawić go : P

mellamokb's towers of hanoi profile game

Oto mój przykład osadzony bezpośrednio w poście. Jest to trochę błędne z powodu kilku szczegółów implementacyjnych, dla których nie opracowałem dobrego rozwiązania. Czasami po kliknięciu kołka nie aktualizuje się on poprawnie, dopóki nie odświeży się kolejna strona:

Wieże Hanoi

http://hanoi.kurtbachtold.com/hanoi.php/text

http://hanoi.kurtbachtold.com/hanoi.php/1 http://hanoi.kurtbachtold.com/hanoi.php/2 http://hanoi.kurtbachtold.com/hanoi.php/3

Resetowanie

Czy potrafisz lepiej?

  • Utwórz działającą grę w opublikowanej odpowiedzi (lub na stronie profilu użytkownika). Odbywa się to poprzez odpowiednie skonfigurowanie własnego serwera WWW (lub napisanie programu, który działa jak serwer) i osadzenie zawartości w poście, używając odsyłacza do określenia poleceń wydawanych przez użytkownika do gry.
  • Najfajniejszy pomysł (najwięcej głosów) wygrywa konkurs, według Dnia Kanady (niedziela, 1 lipca 2012 o 23:59 EST)
  • W przypadku remisu wygrywa starsza odpowiedź.

1
+1 Prosty, ale genialny pomysł! BTW - w terminie myślę, że masz na myśli 2 czerwca 2012 r.
Cristian Lupascu

Derp, tak zrobiłem, dziękuję :)
mellamokb

1
@boothby: Właściwie to myślałem o usunięciu mojej odpowiedzi. Chodziło o to, aby podać konkretny przykład, a nie wygrać konkurs (lub głosować, nie dbam o przedstawicieli). Czy możesz przedstawić konstruktywne sugestie konkurencji? Jaki byłby termin? Jak zmienić specyfikację, aby zmotywować Cię do uczestnictwa?
mellamokb

4
Właśnie zauważyłem, że AI minitecha nie może zagrać w doskonałą grę w kółko i krzyżyk. Graj w centrum, u dołu po lewej, u góry w środku, w środku po prawej, w środku po lewej.
PhiNotPi

1
@ Mr.Wizard: działa dobrze na FF 12.0 i Windows 7 tutaj, czy możesz opublikować więcej szczegółów na temat tego, co nie działa?
ChristopheD

Odpowiedzi:


27

Gra życia Conwaya

Pokolenie +1 - +5 pokoleń - powiększ - pomniejsz

Wzór obciążenie: random - szybowiec - gunstar - ślimak - lwss - lightspeedoscillator1 - tumbler

Wykorzystano dane wyjściowe w języku Python i SVG. Na początku próbowałem używać pojedynczych pikseli (aby można było przełączać pojedyncze komórki), ale to nie zadziałało, ponieważ przeglądarka nie ładuje obrazów w kolejności. Możliwe są także znacznie większe wzorce bez awarii mojego serwera.

Aktualizacja:

Bawiłem się trochę z Pythonem i dodałem kilka funkcji i ulepszeń:

  • Dodano HUD z liczbą ludności, powiększeniem i nazwą
  • Wzory w formacie rle można teraz ładować ( długa lista , via ) za pomocą patternparametru (np ?pattern=glider.). Rozmiar pliku jest ograniczony do 1,5 kB
  • Może przekazywać n pokoleń, ograniczonych jednocześnie do 5, za pomocą nextparametru
  • Nieznacznie ulepszony algorytm. Nie jest to jednak naprawdę szybkie, chcę, aby pozostało to proste
  • Działa również teraz samodzielnie (używa odsyłacza lub własnego ciągu zapytania): https://copy.sh/fcgi-bin/life2.py?pattern=gosperglidergun


sessions = {}

WIDTH = 130
HEIGHT = 130
RULE = (3,), (2, 3)

def read_pattern(filename, offset_x, offset_y):

    filename = PATH + filename + '.rle.gz'

    try:
        if os.stat(filename).st_size > 1500:
            return ['pattern too big', set()]
    except OSError as e:
        return ['could not find pattern', set()]

    file = gzip.open(filename)

    x, y = offset_x, offset_y
    name = ''
    pattern_string = ''
    field = []

    for line in file:
        if line[0:2] == '#N':
            name = line[2:-1]
        elif line[0] != '#' and line[0] != 'x':
            pattern_string += line[:-1]

    for count, chr in re.findall('(\d*)(b|o|\$|!)', pattern_string):
        count = int(count) if count else 1

        if chr == 'o':
            for i in range(x, x + count):
                field.append( (i, y) )
            x += count
        elif chr == 'b':
            x += count
        elif chr == '$':
            y += count
            x = offset_x
        elif chr == '!':
            break

    file.close()

    return [name, set(field)]



def next_generation(field, n):

    for _ in range(n):

        map = {}

        for (x, y) in field:
            for (i, j) in ( (x-1, y-1), (x, y-1), (x+1, y-1), (x-1, y), (x+1, y), (x-1, y+1), (x, y+1), (x+1, y+1) ):
                map[i, j] = map[i, j] + 1 if (i, j) in map else 1

        field = [
            (x, y)
            for x in range(0, WIDTH)
            for y in range(0, HEIGHT)
            if (x, y) in map
            if ( (map[x, y] in RULE[1]) if (x, y) in field else (map[x, y] in RULE[0]) )
        ]

    return field


def life(env, start):


    if 'REMOTE_ADDR' in env:
        client_ip = env['REMOTE_ADDR']
    else:
        client_ip = '0'

    if not client_ip in sessions:
        sessions[client_ip] = read_pattern('trueperiod22gun', 10, 10) + [2]

    session = sessions[client_ip]

    if 'HTTP_REFERER' in env:
        query = urlparse.parse_qs(urlparse.urlparse(env['HTTP_REFERER']).query, True)
    elif 'QUERY_STRING' in env:
        query = urlparse.parse_qs(env['QUERY_STRING'], True)
    else:
        query = None

    timing = time.time()

    if query:
        if 'next' in query:
            try:
                count = min(5, int(query['next'][0]))
            except ValueError as e:
                count = 1
            session[1] = set( next_generation(session[1], count) )
        elif 'random' in query:
            session[0:2] = 'random', set([ (random.randint(0, WIDTH), random.randint(0, HEIGHT)) for _ in range(800) ])
        elif 'pattern' in query:
            filename = query['pattern'][0]
            if filename.isalnum():
                session[0:2] = read_pattern(filename, 10, 10)
        elif 'zoomin' in query:
            session[2] += 1
        elif 'zoomout' in query and session[2] > 1:
            session[2] -= 1

    timing = time.time() - timing

    start('200 Here you go', [
        ('Content-Type', 'image/svg+xml'), 
        ('Cache-Control', 'no-store, no-cache, must-revalidate, post-check=0, pre-check=0'), 
        ('Expires', 'Tue, 01 Jan 2000 12:12:12 GMT')
    ])

    pattern_name, field, zoom = session

    yield '<?xml version="1.0" encoding="UTF-8"?>'
    yield '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">'
    yield '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" baseProfile="full" width="400px" height="200px">'
    yield '<!-- finished in %f -->' % timing
    yield '<text x="0" y="10" style="font-size:10px">Population: %d</text>' % len(field)
    yield '<text x="100" y="10" style="font-size:10px">Zoom: %d</text>' % zoom
    yield '<text x="180" y="10" style="font-size:10px; font-weight:700">%s</text>' % pattern_name
    yield '<line x1="0" y1="15" x2="666" y2="15" style="stroke:#000; stroke-width:1px" />'

    for (x, y) in field:
        yield '<rect x="%d" y="%d" width="%d" height="%d"/>' % (zoom * x, zoom * y + 20, zoom, zoom)

    yield '</svg>'


from flup.server.fcgi import WSGIServer
import random
import re
import gzip
import os
import urlparse
import time

WSGIServer(life).run()

Możesz wziąć mój kod jako szablon do dalszych zgłoszeń w Pythonie fastcgi.


+1 Świetnie! Jedna sugestia: dołącz #5946do swoich linków, a po każdej aktualizacji wróci do twojego postu.
mellamokb

hmm .. przynajmniej zadziałało, kiedy spróbowałem .. ah. ponieważ w Towers of Hanoi zawsze klikasz różne kołki. hmm
mellamokb

@mellamokb działa, ale nie możesz teraz kliknąć dwukrotnie tego samego linku
skopiuj

Tak, właśnie zdałem sobie sprawę, że lol. Zgadnij, że możesz podać zastrzeżenie, że robiąc następną generację, po prostu naciśnij F5, aby przejść do kolejnych iteracji, zamiast klikać nextlink raz za razem po raz pierwszy.
mellamokb

1
@mellamokb dzięki. Moim zdaniem tak naprawdę nie musisz akceptować odpowiedzi na tej platformie, ponieważ wygląda na to, że wyzwanie zostało zamknięte
skopiuj

35

C # - Stack Exchange Hangman

Odgadnij nazwy stron Stack Exchange w tej grze Hangman:



A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
New game


Dokonano tego przy użyciu ASP.NET MVC 3.0 . Oto kod, Controllerktóry rozwiązuje problem:

public class HangmanController : Controller
{
    public ActionResult Index()
    {
        var game = Session["hangman"] as HangmanGame ?? HangmanGame.New();

        game = ExecuteGameCommand(game);

        Session["hangman"] = game;

        var imageRenderer = new HangmanImageRenderer(game);
        return new ImageResult(imageRenderer.Render());
    }

    private HangmanGame ExecuteGameCommand(HangmanGame game)
    {
        var referrerQuery = Request.UrlReferrer != null ? Request.UrlReferrer.Query : string.Empty;

        if (referrerQuery.Contains("_new_hangman_"))
            return HangmanGame.New();

        if(game.IsOver())
            return game;

        var chosenLetter = HangmanGame.ValidLetters
            .FirstOrDefault(letter => referrerQuery.Contains(String.Format("_hangman_{0}_", letter)));

        if (chosenLetter != default(char))
            game.RegisterGuess(chosenLetter);

        return game;
    }
}

Oprócz tego kodu istnieją jeszcze trzy klasy, których nie uwzględniłem, ponieważ są one dość długie i proste:

  • HangmanGame - tutaj są wdrażane reguły biznesowe gry
  • HangmanImageRenderer - klasa obejmująca całą brzydotę GDI
  • ImageResult- niestandardowy ActionResultużywany do zwracania dynamicznie generowanego obrazu

Cała lista kodów jest dostępna na stronie http://pastebin.com/ccwZLknX


+1 Wow, jesteście niesamowici :). Jak dotychczasowe pomysły!
mellamokb

Fajnie, nigdy nie słyszałem o appharbor.com. Czy naprawdę płacisz za hosting swojej odpowiedzi?
mellamokb

@mellamokb nie, korzystam z bezpłatnego planu hostingowego Appharbor. Jeśli to się często kliknie, chyba będę musiał zapłacić ... :)
Cristian Lupascu

2
Chciałem wspomnieć, jeśli to konieczne, mogę zapewnić niestandardowy hosting subdomen i dostęp FTP do mojej witryny hostingowej.
mellamokb

@mellamokb dzięki, ale myślę, że ten hosting zrobi. Żartowałem tylko o wielu kliknięciach. :)
Cristian Lupascu

19

Clojoban! [WIP]

Chciałem stworzyć z tego większą grę, aby nauczyć się Clojure , więc zajęło mi to trochę czasu (i stało się całkiem duże.) Miałem dużo zabawy, robiąc to, btw!

Clojoban! Restart levelNew game

. .

- No-op*

. .

** (kliknij tutaj, jeśli gra przestanie odpowiadać) *

Instrukcje

Jesteś Robby Robby, pracowity robot. Pracujesz FlipCo Industriesjako nośnik ciężkiego ładunku. Twoim zadaniem jest przesunięcie każdego box Pudełkoz nich na goal Celjak najmniejszą liczbę kroków. FlipCoUdogodnienia są NIEBEZPIECZNE . Istnieje wiele wyzwań i specjalnych miejsc do odkrycia.

Jeśli utkniesz, kliknij Restart level(ale liczba kroków nie zostanie zresetowana!)


Możesz także zagrać na stronie głównej Clojoban (chociaż to rujnuje cel wyzwania). Naprawia niesławny problem z kotwicą, nie wymaga plików cookie między witrynami i możesz grać za pomocą klawiszy strzałek na klawiaturze! Możesz także grać na mojej stronie profilu użytkownika bez irytującego problemu z kotwicą.

W przeglądarce Firefox obraz nie miga podczas ładowania, więc gra jest wygodniejsza.

Ta gra jest DALEKO od zakończenia, Clojoban jest wciąż w toku . Pełny kod źródłowy można zobaczyć na stronie projektu GitHub Clojoban . W pliku README znajduje się kilka informacji o współudziale . Potrzebuję też poziomów! Zobacz format poziomu na przykładowych poziomach . Możesz zajrzeć do narzędzia do śledzenia problemów Clojoban i zobaczyć, co będzie dalej!


Teraz twoja reputacja to 11 :)
mellamokb

@mellamokb dzięki! Gra jest teraz osadzona :)
Álvaro Cuesta

Najwyraźniej nie zwróciło to uwagi. Wszelkie wskazówki dotyczące poprawy?
Álvaro Cuesta

Twoja odpowiedź jest dobra, myślę, że ogólnie to pytanie uległo stagnacji. Przez ostatnie kilka dni nie widziałem wiele aktywności ani głosów.
mellamokb

To świetna gra! Myślę, że powinieneś stworzyć samodzielną wersję; Dotarłem do trzeciego poziomu i pozbyłem się wciskania przycisku No-op. :) W każdym razie świetna robota!
Cristian Lupascu

17

Labirynt

http://phpshizzle.t15.org/sogolf_maze/maze.php -
New Noop button

Zacząłem od generatora labiryntów PHP, który znalazłem tutaj: http://dev.horemag.net/2008/03/01/php-maze-generation-class/ .

EDYCJA : zmieniono wyjście na PNG zamiast SVG (dla lepszej kompatybilności między przeglądarkami).

EDYCJA 2: dodano nagłówek do ustalenia zgodności plików cookie IE. Powinien teraz działać poprawnie we wszystkich głównych przeglądarkach.

Obraz nie jest odświeżany, jeśli dwukrotnie podążysz w tym samym kierunku (ze względu na linki kotwiczące). Naciśnij F5 po raz drugi lub zagraj w labirynt na moim profilu przepełnienia stosu .

EDYCJA 3: Dodano przycisk no-op, aby łatwo móc dwukrotnie obrać ten sam kierunek (patrz komentarze poniżej).

<?php
// based upon the maze generator by Evgeni Vasilev (PHP Adaptation)
// see http://dev.horemag.net/2008/03/01/php-maze-generation-class/
class Maze
{
  var $maze = array();
  var $mx = 0;
  var $my = 0;
  var $xplayer = 1;
  var $yplayer = 1;

  function Maze($mx, $my)
  {
    $mx +=2;
    $my +=2;
    $this->mx = $mx;
    $this->my = $my;
    $dx = array( 0, 0, -1, 1 );
    $dy = array( -1, 1, 0, 0 );
    $todo = array(); 
    $todonum = 0;

    for ($x = 0; $x < $mx; ++$x){
      for ($y = 0; $y < $my; ++$y){
        if ($x == 0 || $x == $mx-1 || $y == 0 || $y == $my-1) {
          $this->maze[$x][$y] = 32;
        } else {
          $this->maze[$x][$y] = 63;
        }
      }
    }
    $x = rand(1, $mx-2); $y = rand(1, $my-2);
    $x = 1; $y = 1;
    $this->maze[$x][$y] &= ~48;
    for ($d = 0; $d < 4; ++$d){
      if (($this->maze[$x + $dx[$d]][$y + $dy[$d]] & 16) != 0) {
        $todo[$todonum++] = (($x + $dx[$d]) << 16) | ($y + $dy[$d]);
        $this->maze[$x + $dx[$d]][$y + $dy[$d]] &= ~16;
      }
    }

    while ($todonum > 0) {
      $n = rand(0, $todonum-1);
      $x = $todo[$n] >> 16;
      $y = $todo[$n] & 65535;
      $todo[$n] = $todo[--$todonum];
      do {
        $d = rand(0, 3);
      } while (($this->maze[$x + $dx[$d]][$y + $dy[$d]] & 32) != 0);
      $this->maze[$x][$y] &= ~((1 << $d) | 32);
      $this->maze[$x + $dx[$d]][$y + $dy[$d]] &= ~(1 << ($d ^ 1));
      for ($d = 0; $d < 4; ++$d){
        if (($this->maze[$x + $dx[$d]][$y + $dy[$d]] & 16) != 0) {
          $todo[$todonum++] = (($x + $dx[$d]) << 16) | ($y + $dy[$d]);
          $this->maze[$x + $dx[$d]][$y + $dy[$d]] &= ~16;
        }
      }
    }
    $this->maze[1][1] &= ~1;
    $this->maze[$mx-2][$my-2] &= ~2;
  }

  function _drawLine($img,$color, $x1, $y1, $x2, $y2)
  {
    imageline($img, $x1, $y1, $x2, $y2, $color);
  }

  function _drawPlayer($img, $x, $y, $r, $colorborder, $colorfill)
  {
    imagefilledellipse($img, $x, $y, $r, $r, $colorfill);
    imageellipse($img, $x, $y, $r, $r, $colorborder);
  }

  function _drawWin($img, $color)
  {
    imagestring($img, 5, 170, 90, "YOU WIN!", $color);
  }

  function movePlayerDown()
  {
    if ($this->yplayer+1 < $this->my-1 && ($this->maze[$this->xplayer][$this->yplayer] & 2) == 0)
    $this->yplayer++;
  }

  function movePlayerUp()
  {
    if ($this->yplayer-1 > 0 && ($this->maze[$this->xplayer][$this->yplayer] & 1) == 0)
      $this->yplayer--;
  }

  function movePlayerRight()
  {
    if ($this->xplayer+1 < $this->mx-1 && ($this->maze[$this->xplayer][$this->yplayer] & 8) == 0)
      $this->xplayer++;
  }  

  function movePlayerLeft()
  {
    if ($this->xplayer-1 > 0 && ($this->maze[$this->xplayer][$this->yplayer] & 4) == 0)
      $this->xplayer--;
  }  

  function renderImage($xs, $ys)
  {
    $off = 0;
    $w = ($this->mx*$xs)+($off*2); $h = ($this->my*$ys)+($off*2);
    $img = imagecreatetruecolor($w, $h);
    imagesetthickness($img, 2);
    $fg = imagecolorallocate($img, 0, 0, 0);
    $bg = imagecolorallocate($img, 248, 248, 248);
    $red = imagecolorallocate($img, 255, 0, 0);
    imagefill($img, 0, 0, $bg);
    if (($this->xplayer == $this->mx-2) && ($this->yplayer == $this->my-2)) {
      $this->_drawWin($img, $red);
      return $img;
    }

    for ($y = 1; $y < $this->my-1; ++$y) {
      for ($x = 1; $x < $this->mx-1; ++$x){
        if (($this->maze[$x][$y] & 1) != 0)
          $this->_drawLine ($img, $fg, $x * $xs + $off, $y * $ys + $off, $x * $xs + $xs + $off, $y * $ys + $off);
        if (($this->maze[$x][$y] & 2) != 0)
          $this->_drawLine ($img, $fg, $x * $xs + $off, $y * $ys + $ys + $off, $x * $xs + $xs + $off, $y * $ys + $ys + $off);
        if (($this->maze[$x][$y] & 4) != 0)
          $this->_drawLine ($img, $fg, $x * $xs + $off, $y * $ys + $off, $x * $xs + $off, $y * $ys + $ys + $off);
        if (($this->maze[$x][$y] & 8) != 0)
          $this->_drawLine ($img, $fg, $x * $xs + $xs + $off, $y * $ys + $off, $x * $xs + $xs + $off, $y * $ys + $ys + $off);
        if ($x == $this->xplayer && $y == $this->yplayer) {
          $this->_drawPlayer ($img, $x * $xs + ($xs/2), $y * $ys + ($ys/2), 14, $fg, $red);
        }
      }
    }
    return $img;
  }
}
header('P3P: CP="CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR"');
session_start();
$orig_url = $_SERVER['HTTP_REFERER'];
if (!isset($_SESSION['maze']) || strpos($orig_url, 'resetmaze')){
    $_SESSION['maze'] = new Maze(25,10);
}
$maze = $_SESSION['maze'];
if (strpos($orig_url, 'playerdown')) { $maze->movePlayerDown(); }
if (strpos($orig_url, 'playerup')) { $maze->movePlayerUp(); }
if (strpos($orig_url, 'playerright')) { $maze->movePlayerRight(); }
if (strpos($orig_url, 'playerleft')) { $maze->movePlayerLeft(); }
$img = $maze->renderImage(16,16);
header("Content-Type: image/png");
imagepng($img);
imagedestroy($img);
?>

1
+1 fajnie! dla lepszego doświadczenia dodaj #answer-6171na końcu swoich linków. W przeciwnym razie nikt nie będzie miał dość cierpliwości, aby rozwiązać labirynt.
Cristian Lupascu

@ W0lf: Dzięki. Myślałem o dołączeniu #linków, ale problem polega na tym, że nie odświeżają strony, gdy dwa razy podążysz w tym samym kierunku (co może się zdarzyć w labiryncie ;-). Dodałem je teraz, aby ludzie musieli nacisnąć klawisz F5 za drugim razem, gdy chcą obrać ten sam kierunek. Inną opcją jest zagranie tutaj (mój profil SO: stackoverflow.com/users/81179/christophed )
ChristopheD

Chciałbym mieć prosty link bez operacji (odświeżanie?), Aby ułatwić aktualizację, gdy próbujesz przejść dwa razy w tym samym kierunku :)
kaoD

@kaoD: Bez części kotwiczących ( #), które skaczą do właściwej odpowiedzi na pytanie (wewnętrznie, bez odświeżania strony), proste odświeżanie strony działałoby dobrze (jak widać na moim połączonym profilu, w którym dostępny jest również ten sam labirynt) . Problem polega na tym, że po każdym odświeżeniu znajdziesz się u góry strony. Prawdziwy problem polega na tym, że jesteśmy naprawdę ograniczeni w tym, co możemy zawrzeć w odpowiedzi tutaj na StackOverflow (nie bez powodu), nie możemy na przykład używać arbitralnego Javascript. Nie mam pojęcia o łatwym wyjściu.
ChristopheD

Nadal możesz mieć kotwicę, która przejdzie bezpośrednio do Twojego posta, ale z innym adresem URL (co pozwoli na prawidłową rozgrywkę). Metoda F5 jest niezręczna.
kaoD

14

Pokémon 2-Player Chess [Prace w toku]

Ponieważ w ten sposób jest fajniej. Już wkrótce: AI, siatka izometryczna i cienie!

http://minite.ch/chess/?i=1 http://minite.ch/chess/?i=2 http://minite.ch/chess/?i=3 http://minite.ch/ szachy /? i = 4 http://minite.ch/chess/?i=5 http://minite.ch/chess/?i=6 http://minite.ch/chess/?i=7 http: //minite.ch/chess/?i=8 
http://minite.ch/chess/?i=9 http://minite.ch/chess/?i=10 http://minite.ch/chess/ ? i = 11 http://minite.ch/chess/?i=12 http://minite.ch/chess/?i=13 http://minite.ch/chess/?i=14 http: // minite.ch/chess/?i=15 http://minite.ch/chess/?i=16 
http://minite.ch/chess/?i=17 http://minite.ch/chess/?i = 18 http://minite.ch/chess/?i=19 http://minite.ch/chess/?i=20 http://minite.ch/chess/?i=21http://minite.ch/chess/?i=22 http://minite.ch/chess/?i=23 http://minite.ch/chess/?i=24 
http://minite.ch/ szachy /? i = 25 http://minite.ch/chess/?i=26 http://minite.ch/chess/?i=27 http://minite.ch/chess/?i=28 http: //minite.ch/chess/?i=29 http://minite.ch/chess/?i=30 http://minite.ch/chess/?i=31 http://minite.ch/chess/ ? i = 32 
http://minite.ch/chess/?i=33 http://minite.ch/chess/?i=34 http://minite.ch/chess/?i=35 http: // minite.ch/chess/?i=36 http://minite.ch/chess/?i=37 http://minite.ch/chess/?i=38 http://minite.ch/chess/?i = 39 http://minite.ch/chess/?i=40 
http://minite.ch/chess/?i=41http://minite.ch/chess/?i=42 http://minite.ch/chess/?i=43 http://minite.ch/chess/?i=44 http://minite.ch/ szachy /? i = 45 http://minite.ch/chess/?i=46 http://minite.ch/chess/?i=47 http://minite.ch/chess/?i=48 
http: //minite.ch/chess/?i=49 http://minite.ch/chess/?i=50 http://minite.ch/chess/?i=51 http://minite.ch/chess/ ? i = 52 http://minite.ch/chess/?i=53 http://minite.ch/chess/?i=54 http://minite.ch/chess/?i=55 http: // minite.ch/chess/?i=56 
http://minite.ch/chess/?i=57 http://minite.ch/chess/?i=58 http://minite.ch/chess/?i = 59 http://minite.ch/chess/?i=60 http://minite.ch/chess/?i=61http://minite.ch/chess/?i=62 http://minite.ch/chess/?i=63 http://minite.ch/chess/?i=64

Przepraszam, bez en passant i castlingu. Detekcja matematyczna / czekowa / patowa do wdrożenia. Duszki stąd: http://floatzel.net/pokemon/black-white/sprites/

Oto źródło:

<?php
session_start();

function kick() {
    header("Status: Forbidden\r\n", true, 403);
    header("Content-Type: text/plain\r\n");
    die('Go away.');
}

function isEnemy($item) {
    return $item !== -1 && $item & 8;
}

function iValidMoves($board, $type, $x, $y) {
    $results = array();

    switch($type) {
        case 0:
            # Pawn
            if($board[$y - 1][$x] === -1) {
                $results[] = array($x, $y - 1);

                if($y == 6 && $board[$y - 2][$x] === -1) $results[] = array($x, $y - 2);
            }

            if($x > 0 && isEnemy($board[$y - 1][$x - 1])) $results[] = array($x - 1, $y - 1);
            if($x < 7 && isEnemy($board[$y - 1][$x + 1])) $results[] = array($x + 1, $y - 1);

            break;
        case 1:
            # King
            if($x > 0 && $board[$y][$x - 1] & 8) $results[] = array($x - 1, $y);
            if($x > 0 && $y > 0 && $board[$y - 1][$x - 1] & 8) $results[] = array($x - 1, $y - 1);
            if($x > 0 && $y < 7 && $board[$y + 1][$x - 1] & 8) $results[] = array($x - 1, $y + 1);
            if($x < 7 && $board[$y][$x + 1] & 8) $results[] = array($x + 1, $y);
            if($x < 7 && $y > 0 && $board[$y - 1][$x + 1] & 8) $results[] = array($x + 1, $y - 1);
            if($x < 7 && $y < 7 && $board[$y + 1][$x + 1] & 8) $results[] = array($x + 1, $y + 1);
            if($y > 0 && $board[$y - 1][$x] & 8) $results[] = array($x, $y - 1);
            if($y < 7 && $board[$y + 1][$x] & 8) $results[] = array($x, $y + 1);

            break;
        case 2:
            # Queen
            # Downwards diagonal
            for($d = 1; $x + $d < 8 && $y + $d < 8; $d++) {
                if($board[$y + $d][$x + $d] & 8) {
                    $results[] = array($x + $d, $y + $d);

                    if($board[$y + $d][$x + $d] !== -1) break;
                } else {
                    break;
                }
            }

            for($d = -1; $x + $d >= 0 && $y + $d >= 0; $d--) {
                if($board[$y + $d][$x + $d] & 8) {
                    $results[] = array($x + $d, $y + $d);

                    if($board[$y + $d][$x + $d] !== -1) break;
                } else {
                    break;
                }
            }

            # Upwards diagonal
            for($d = 1; $x + $d < 8 && $y - $d >= 0; $d++) {
                if($board[$y - $d][$x + $d] & 8) {
                    $results[] = array($x + $d, $y - $d);

                    if($board[$y - $d][$x + $d] !== -1) break;
                } else {
                    break;
                }
            }

            for($d = -1; $x + $d >= 0 && $y - $d < 8; $d--) {
                if($board[$y - $d][$x + $d] & 8) {
                    $results[] = array($x + $d, $y - $d);

                    if($board[$y - $d][$x + $d] !== -1) break;
                } else {
                    break;
                }
            }

            # Horizontal
            for($d = 1; $x + $d < 8; $d++) {
                if($board[$y][$x + $d] & 8) {
                    $results[] = array($x + $d, $y);

                    if($board[$y][$x + $d] !== -1) break;
                } else {
                    break;
                }
            }

            for($d = -1; $x + $d >= 0; $d--) {
                if($board[$y][$x + $d] & 8) {
                    $results[] = array($x + $d, $y);

                    if($board[$y][$x + $d] !== -1) break;
                } else {
                    break;
                }
            }

            # Vertical
            for($d = 1; $y + $d < 8; $d++) {
                if($board[$y + $d][$x] & 8) {
                    $results[] = array($x, $y + $d);

                    if($board[$y + $d][$x] !== -1) break;
                } else {
                    break;
                }
            }

            for($d = -1; $y + $d >= 0; $d--) {
                if($board[$y + $d][$x] & 8) {
                    $results[] = array($x, $y + $d);

                    if($board[$y + $d][$x] !== -1) break;
                } else {
                    break;
                }
            }

            break;
        case 3:
            # Bishop
            # Downwards diagonal
            for($d = 1; $x + $d < 8 && $y + $d < 8; $d++) {
                if($board[$y + $d][$x + $d] & 8) {
                    $results[] = array($x + $d, $y + $d);

                    if($board[$y + $d][$x + $d] !== -1) break;
                } else {
                    break;
                }
            }

            for($d = -1; $x + $d >= 0 && $y + $d >= 0; $d--) {
                if($board[$y + $d][$x + $d] & 8) {
                    $results[] = array($x + $d, $y + $d);

                    if($board[$y + $d][$x + $d] !== -1) break;
                } else {
                    break;
                }
            }

            # Upwards diagonal
            for($d = 1; $x + $d < 8 && $y - $d >= 0; $d++) {
                if($board[$y - $d][$x + $d] & 8) {
                    $results[] = array($x + $d, $y - $d);

                    if($board[$y - $d][$x + $d] !== -1) break;
                } else {
                    break;
                }
            }

            for($d = -1; $x + $d >= 0 && $y - $d < 8; $d--) {
                if($board[$y - $d][$x + $d] & 8) {
                    $results[] = array($x + $d, $y - $d);

                    if($board[$y - $d][$x + $d] !== -1) break;
                } else {
                    break;
                }
            }

            break;
        case 4:
            # Knight
            if($x > 1 && $y > 0 && $board[$y - 1][$x - 2] & 8) $results[] = array($x - 2, $y - 1);
            if($x > 0 && $y > 1 && $board[$y - 2][$x - 1] & 8) $results[] = array($x - 1, $y - 2);
            if($x < 7 && $y > 1 && $board[$y - 2][$x + 1] & 8) $results[] = array($x + 1, $y - 2);
            if($x < 6 && $y > 0 && $board[$y - 1][$x + 2] & 8) $results[] = array($x + 2, $y - 1);
            if($x < 6 && $y < 7 && $board[$y + 1][$x + 2] & 8) $results[] = array($x + 2, $y + 1);
            if($x < 7 && $y < 6 && $board[$y + 2][$x + 1] & 8) $results[] = array($x + 1, $y + 2);
            if($x > 0 && $y < 6 && $board[$y + 2][$x - 1] & 8) $results[] = array($x - 1, $y + 2);
            if($x > 1 && $y < 7 && $board[$y + 1][$x - 2] & 8) $results[] = array($x - 2, $y + 1);

            break;
        case 5:
            # Rook
            # Horizontal
            for($d = 1; $x + $d < 8; $d++) {
                if($board[$y][$x + $d] & 8) {
                    $results[] = array($x + $d, $y);

                    if($board[$y][$x + $d] !== -1) break;
                } else {
                    break;
                }
            }

            for($d = -1; $x + $d >= 0; $d--) {
                if($board[$y][$x + $d] & 8) {
                    $results[] = array($x + $d, $y);

                    if($board[$y][$x + $d] !== -1) break;
                } else {
                    break;
                }
            }

            # Vertical
            for($d = 1; $y + $d < 8; $d++) {
                if($board[$y + $d][$x] & 8) {
                    $results[] = array($x, $y + $d);

                    if($board[$y + $d][$x] !== -1) break;
                } else {
                    break;
                }
            }

            for($d = -1; $y + $d >= 0; $d--) {
                if($board[$y + $d][$x] & 8) {
                    $results[] = array($x, $y + $d);

                    if($board[$y + $d][$x] !== -1) break;
                } else {
                    break;
                }
            }

            break;
    }

    return $results;
}

function invertRelationship($piece) {
    return $piece === -1 ? -1 : $piece ^ 8;
}

function invertPosition($position) {
    return array($position[0], 7 - $position[1]);
}

function invertBoard($board) {
    $invertedBoard = array();

    for($i = 7; $i > -1; $i--) {
        $invertedBoard[] = array_map('invertRelationship', $board[$i]);
    }

    return $invertedBoard;
}

function validMoves($x, $y) {
    global $board;

    $type = $board[$y][$x];

    if($type & 8) {
        return array_map('invertPosition', iValidMoves(invertBoard($board), $type & ~8, $x, 7 - $y));
    } else {
        return iValidMoves($board, $type, $x, $y);
    }
}

function shouldHighlight($x, $y) {
    global $highlight;

    foreach($highlight as $position) {
        if($position[0] == $x && $position[1] == $y) {
            return true;
        }
    }

    return false;
}

if(isset($_SESSION['board'])) {
    $board = $_SESSION['board'];
} else {
    $board = array(
        array(5 | 8, 4 | 8, 3 | 8, 1 | 8, 2 | 8, 3 | 8, 4 | 8, 5 | 8),
        array(0 | 8, 0 | 8, 0 | 8, 0 | 8, 0 | 8, 0 | 8, 0 | 8, 0 | 8),
        array(-1, -1, -1, -1, -1, -1, -1, -1),
        array(-1, -1, -1, -1, -1, -1, -1, -1),
        array(-1, -1, -1, -1, -1, -1, -1, -1),
        array(-1, -1, -1, -1, -1, -1, -1, -1),
        array(0, 0, 0, 0, 0, 0, 0, 0),
        array(5, 4, 3, 1, 2, 3, 4, 5)
    );
}

$back = array(
    imagecreatefrompng('back/16.png'),  # pawn
    imagecreatefrompng('back/6.png'),   # king
    imagecreatefrompng('back/149.png'), # queen
    imagecreatefrompng('back/37.png'),  # bishop
    imagecreatefrompng('back/25.png'),  # knight
    imagecreatefrompng('back/75.png')   # rook
);

$front = array(
    imagecreatefrompng('front/16.png'),     # pawn
    imagecreatefrompng('front/6.png'),      # king
    imagecreatefrompng('front/149.png'),    # queen
    imagecreatefrompng('front/37.png'),     # bishop
    imagecreatefrompng('front/25.png'),     # knight
    imagecreatefrompng('front/75.png')      # rook
);

$image = $_GET['i'];

if(ctype_digit($image)) {
    $image = (int)$image;
} else {
    kick();
}

if($image < 1 || $image > 64) {
    kick();
}

$highlight = array();

$referrer = $_SERVER['HTTP_REFERER'];
$action = null;

if(strpos($referrer, '?a=') > -1) {
    $action = substr($referrer, strpos($referrer, '?a=') + 3);
}

if($action !== null && $image === 1) { # Only do this once!
    if(!ctype_digit($action)) kick();
    $action = (int)$action;

    if($action < 1 || $action > 64) kick();

    $aX = ($action - 1) % 8;
    $aY = floor(($action - 1) / 8);

    if(isset($_SESSION['selected'])) {
        if($_SESSION['selected'] !== $action) {
            # Make sure the piece can actually move there.
            # If it can, move.
            # "Highlight" the places that the piece can move:
            $highlight = validMoves(($_SESSION['selected'] - 1) % 8, floor(($_SESSION['selected'] - 1) / 8));

            if(shouldHighlight($aX, $aY)) {
                # The move is good!
                $sX = ($_SESSION['selected'] - 1) % 8;
                $sY = floor(($_SESSION['selected'] - 1) / 8);
                $board[$aY][$aX] = $board[$sY][$sX];
                $board[$sY][$sX] = -1;

                # Now, rotate the board for the next person to play:
                $invertedBoard = invertBoard($board);
                $rotatedBoard = array();

                foreach($invertedBoard as $row) {
                    for($i = 0; $i < 4; $i++) {
                        $row[$i] ^= $row[7 - $i];
                        $row[7 - $i] ^= $row[$i];
                        $row[$i] ^= $row[7 - $i];
                    }

                    $rotatedBoard[] = $row;
                }

                $board = $rotatedBoard;
            }
        }

        unset($_SESSION['selected']);
    } elseif(($board[$aY][$aX] & 8) === 0) {
        # Select a piece:
        $_SESSION['selected'] = $action;
    }
}

if(isset($_SESSION['selected'])) {
    # Highlight the places that the piece can move:
    $highlight = validMoves(($_SESSION['selected'] - 1) % 8, floor(($_SESSION['selected'] - 1) / 8));
}

# Draw the background:
$background = imagecreatetruecolor(96, 96);
$black = imagecolorallocate($background, 0, 0, 0);
$white = imagecolorallocate($background, 255, 255, 255);
$red = imagecolorallocatealpha($background, 255, 0, 0, 100);

if(($image + floor(($image - 1) / 8)) % 2) {
    imagefilledrectangle($background, 0, 0, 96, 96, $black);
} else {
    imagefilledrectangle($background, 0, 0, 96, 96, $white);
}

# Draw a piece, if there is one:
$piece = $board[floor(($image - 1) / 8)][($image - 1) % 8];

if($piece > -1) {
    if($piece & 8) {
        $piece &= ~8;
        $draw = $front[$piece];
    } else {
        $draw = $back[$piece];
    }

    imagecopy($background, $draw, 0, 0, 0, 0, 96, 96);
}

# Should we highlight this place?
if(shouldHighlight(($image - 1) % 8, floor(($image - 1) / 8))) {
    imagefilledrectangle($background, 0, 0, 96, 96, $red);
}

header("Content-Type: image/png\r\n");

imagepng($background);

$_SESSION['board'] = $board;
?>

Uwielbiam to, ale dwie strony powinny być różnymi Pokemonami!
MrZander

Bardzo dobrze. Podoba mi się, że stół się zmienia, gdy zmienia się zwrot.
Cristian Lupascu,

1
A w PHP +1 za gry PHP: p
Event_Horizon

1
@ hhh: Nie, dodajesz parametry do tej samej strony i generujesz obrazy na serwerze, sprawdzając Referernagłówek.
Ry-

5
:-(. Twoje duszki nie żyją.
Justin

10

Gra „Simon mówi”

Niestety nie udało mi się przesłać tego zgłoszenia w terminie (nieco arbitralnym), ale naprawdę chciałem zademonstrować animację w takiej grze profilowej użytkownika i żadne z poprzednich zgłoszeń nie jest animowane. Ta gra jest klonem klasycznej gry Simona Miltona Bradleya , w której gracz próbuje powtórzyć coraz dłuższą sekwencję sygnałów.

Informacje o tej grze, w tym jej kod źródłowy, są dostępne na stronie GitHub . Od czasu do czasu mogą występować usterki graficzne (szczególnie na komputerach z systemem Windows) wynikające z hackerskiej „animacji palet”, która eliminuje potrzebę biblioteki rysunków graficznych. Istnienie tych usterek może być użyteczną wymówką do szybkiego przegrania tej gry z powodu strasznej pamięci.

Dodatkowo efekty dużego opóźnienia i ograniczonej przepustowości mogą sprawić, że ta gra będzie o wiele trudniejsza niż wersja oryginalna. Myślę, że aby uzyskać znacznie więcej niż pięć punktów (gdy gra przyspiesza po raz pierwszy), musisz określić, które światło mruga jeszcze raz niż w poprzedniej rundzie, a nie w zależności od prawidłowej sekwencji (co jest bardzo trudne zrobić).

Jeśli ta gra nie działa dla Ciebie (uruchamia się ponownie za każdym razem, gdy klikniesz przycisk), przeglądarka może blokować pliki cookie. Nie dodałem jeszcze obejścia, więc na razie skorzystaj z przeglądarki Chrome, Opera lub Firefox lub tymczasowo zmień ustawienia plików cookie przeglądarki Internet Explorer lub Safari.

Edytuj 2018-05-24: W tej chwili usunąłem publicznie dostępne wystąpienie Heroku tej aplikacji. Mogę przywrócić aplikację do trybu online w późniejszym terminie. Kod aplikacji jest nadal dostępny na GitHub, więc możesz uruchomić go lokalnie lub utworzyć własną instancję aplikacji Heroku, jeśli chcesz grać.


+1 To jest absolutnie genialne! Nigdy nie myślałem o tworzeniu dynamicznie generowanych animowanych
gifów

2

Kamień, papier, nożyczki

Wszystkie linki prowadzą do mojej strony profilu dla prędkości.

Gra

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.