Criar um minijogo de perfil de usuário


49

Ontem, me deparei com uma coisa muito inteligente.

jogo do perfil do tic-tac-toe da minitech

Sim, essa é uma implementação funcional do Tic-Tac-Toe em uma página de perfil de usuário, a partir de @minitech. É claro que, no momento em que o vi, tive que fazer engenharia reversa de sua ideia e formar uma dupla : P

jogo de perfil de torres de hanoi de mellamokb

Aqui está o meu próprio exemplo incorporado diretamente no post. É um pouco complicado devido a alguns detalhes de implementação para os quais ainda não encontrei uma boa solução. Às vezes, depois que você clica em um peg, ele não é atualizado corretamente até que outra página seja atualizada:

Torres de Hanói

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

Restabelecer

Você pode fazer melhor?

  • Crie um jogo de trabalho na sua resposta postada (ou na sua página de perfil de usuário). Isso é feito através da configuração adequada de um servidor da web que você possui (ou da criação de um programa que funciona como servidor da web) e da incorporação de conteúdo em uma publicação, usando o referenciador para determinar quais comandos o usuário está dando ao jogo.
  • A ideia mais legal (mais votos) vence a competição, no Canada Day (domingo, 1 de julho de 2012 às 23:59 EST)
  • Em caso de empate, a resposta mais antiga vence.

11
+1 Idéia simples, mas brilhante! BTW - para o prazo, acho que você quer dizer 2 de junho de 2012.
— Cristian Lupascu 23/05/12

Derp, sim eu fiz, graças :)
— mellamokb

11
@ boothby: Na verdade, eu estava pensando em excluir minha resposta. A intenção era fornecer um exemplo concreto, não vencer o concurso (ou votos, não me importo muito com rep). Você pode fornecer algumas sugestões construtivas para a competição? Como você gostaria que fosse o prazo? Como as especificações devem ser alteradas para motivá-lo a participar?
— Mellamokb 23/05

4
Acabei de notar que a IA da minitech não pode jogar um jogo perfeito do jogo da velha. Reproduzir centro, canto inferior esquerdo, centro superior, centro direito, centro esquerda.
— PhiNotPi

11
@ Mr.Wizard: funcionando bem no FF 12.0 e no Windows 7 aqui, você poderia postar mais detalhes sobre o que não está funcionando?
— ChristopheD

Respostas:


27

Jogo da vida de Conway

Geração +1 - +5 gerações - aumentar o zoom - diminuir o zoom

Carga padrão: aleatória - glider - Gunstar - caracol - lwss - lightspeedoscillator1 - tumbler

Saída Python e SVG usada. Tentei usar pixels únicos no início (para que você pudesse alternar células únicas), mas não deu certo, porque o navegador não carrega imagens em ordem. Além disso, padrões muito maiores são possíveis assim sem travar meu servidor da web.

Atualizar:

Eu me diverti um pouco com python e adicionei vários recursos e melhorias:

  • Adicionado HUD com contagem de população, zoom e nome
  • Os padrões no formato rle agora podem ser carregados ( lista longa , via ) usando o patternparâmetro (por exemplo ?pattern=glider). O tamanho do arquivo é limitado a 1,5kB
  • Pode encaminhar n gerações, limitadas a 5 por vez, usando o nextparâmetro
  • Algoritmo ligeiramente aprimorado. Não é muito rápido, quero que seja simples
  • Ele também funciona de forma independente agora (usa o referenciador ou sua própria cadeia de consulta): 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()

Você pode usar meu código como modelo para outros envios de python fastcgi.


+1 impressionante! Uma sugestão: acrescente #5946aos seus links e ele retornará à sua postagem após cada atualização.
— Mellamokb

hmm .. pelo menos funcionou quando eu tentei .. ah. porque em Towers of Hanoi você está sempre clicando em pinos diferentes. hmm
— mellamokb

@mellamokb funciona, mas você não pode clicar no mesmo link duas vezes agora
— copie

Sim, eu acabei de perceber isso lol. Suponha que você pode fornecer um aviso de isenção de responsabilidade de que, ao executar a próxima geração, basta pressionar F5 para iterações futuras em vez de clicar no nextlink novamente e novamente após a primeira vez.
— Mellamokb

11
@mellamokb thanks. Na minha opinião, você realmente não precisa aceitar respostas nesta plataforma, porque parece que o desafio está encerrado
— copie

35

Jogo da forca do Exchange da pilha

Adivinhe os nomes dos sites da Stack Exchange neste jogo da forca:



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


Isso foi feito usando o ASP.NET MVC 3.0 . Aqui está o código do Controllerque faz o truque:

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;
    }
}

Além deste código, há mais três classes que não incluí, pois são bastante longas e diretas:

  • HangmanGame - é aqui que as regras de negócios do jogo são implementadas
  • HangmanImageRenderer - a classe que encapsula toda a feiura do GDI
  • ImageResult- um costume ActionResultusado para retornar uma imagem gerada dinamicamente

A listagem completa do código está disponível em http://pastebin.com/ccwZLknX


+1 Uau, vocês são incríveis :). Como as idéias até agora!
— Mellamokb

Legal, nunca ouvi falar de appharbor.com. Você realmente está pagando para hospedar sua resposta?
— Mellamokb

@mellamokb não, estou usando o plano de hospedagem gratuita do Appharbor. Se isso fica clicado muito Eu acho que vou ter que pagar embora ... :)
— Cristian Lupascu

2
Eu mencionaria, se necessário, posso fornecer hospedagem de subdomínio personalizada e acesso FTP ao meu site de hospedagem.
— Mellamokb

@mellamokb obrigado, mas acho que essa hospedagem servirá. Eu estava apenas brincando sobre muitos cliques. :)
— Cristian Lupascu

19

Clojoban! [WIP]

Eu queria fazer um jogo maior com isso para aprender Clojure , então demorou um pouco para começar (e ficou bem grande.) Eu me diverti muito fazendo isso, btw!

Clojoban! Restart levelNew game

. .↑

← → - No-op*

. .↓

** (clique aqui se o jogo não responder) *

Instruções

Você é Robby Robby, um robô trabalhador. Você trabalha FlipCo Industriescomo transportador de carga pesada. Seu trabalho é mover cada box Uma caixaum para goal Um objetivogastar o menor número possível de etapas. FlipCoAs instalações da empresa são PERIGOSAS . Existem muitos desafios e lugares especiais para descobrir.

Se você ficar preso, clique Restart level(mas sua contagem de etapas não será redefinida!)


Você também pode jogar na primeira página do Clojoban (embora isso arruine o objetivo do desafio.) Ele corrige o famoso problema da âncora, não requer cookies entre sites e você pode brincar com as teclas de seta do teclado! Você também pode jogar na minha página de perfil de usuário sem o problema irritante da âncora.

No Firefox, a imagem não pisca enquanto carrega, por isso é um pouco mais confortável de reproduzir.

Este jogo está MUITO longe da conclusão, o Clojoban ainda está em andamento . Você pode ver o código fonte completo na página do projeto GitHub do Clojoban . Há algumas informações no README sobre como contribuir . Eu preciso de níveis também! Veja o formato do nível nos níveis de exemplo . Você pode espiar o rastreador de problemas do Clojoban e ver o que está por vir!


Agora, sua reputação é 11 :)
— mellamokb

@mellamokb thanks! Jogo é incorporado agora :)
— Álvaro Cuesta

Aparentemente, isso não recebeu muita atenção. Alguma dica para melhorar?
— Álvaro Cuesta

Sua resposta é boa, acho que esta questão estagnou. Não tenho visto muita atividade ou votos nos últimos dias.
— precisa saber é o seguinte

Esse é um ótimo jogo! Eu acho que você deveria fazer uma versão autônoma; Cheguei ao terceiro nível e me livrei de pressionar o botão No-op. :) Enfim, ótimo trabalho!
— Cristian Lupascu

17

Labirinto

http://phpshizzle.t15.org/sogolf_maze/maze.php -
New ← ↑ ↓ →Noop button

Comecei a partir do gerador de labirinto PHP que encontrei aqui: http://dev.horemag.net/2008/03/01/php-maze-generation-class/ .

EDIT : alterou a saída para PNG em vez de SVG (para melhor compatibilidade entre navegadores).

EDIT 2: adicionado um cabeçalho para corrigir a compatibilidade de cookies do IE. Agora deve funcionar corretamente em todos os principais navegadores.

A imagem não será atualizada se você seguir a mesma direção duas vezes (devido aos links de ancoragem). Pressione F5 pela segunda vez ou toque o labirinto no meu perfil de stackoverflow .

EDIT 3: Adicionado um botão no-op para poder facilmente tomar a mesma direção duas vezes (veja os comentários abaixo).

<?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);
?>

11
+1 Bom! para uma melhor experiência, adicione #answer-6171no final dos seus links. Caso contrário, ninguém terá paciência suficiente para resolver o labirinto.
— Cristian Lupascu

@ W0lf: Obrigado. Pensei em incluir os #links, mas o problema é que eles não atualizam a página quando você toma a mesma direção duas vezes (o que pode acontecer em um labirinto ;-). Eu os adicionei agora para que as pessoas tenham que pressionar F5 na segunda vez que quiserem seguir a mesma direção. Outra opção é reproduzi-lo aqui (meu perfil SO: stackoverflow.com/users/81179/christophed ) #
— ChristopheD

Eu faria uma fantasia simples ligação não-operação (atualização?) Para fazer a atualização mais fácil quando se tenta mover duas vezes na mesma direção :)
— kaoD

@kaoD: Sem as partes âncora ( #) que pulam para a resposta correta para a pergunta (internamente, sem atualização de página), uma simples atualização de página funcionaria bem (como você pode ver no meu perfil vinculado, onde o mesmo labirinto também está disponível) . Mas o problema seria que você se encontraria no topo da página após cada atualização. O verdadeiro problema é que somos realmente limitados no que podemos incluir em uma resposta aqui no StackOverflow (por uma boa razão, é claro), não podemos usar Javascript arbitrário, por exemplo. Não faço ideia de uma saída fácil.
— ChristopheD

Você ainda pode ter a âncora e ela vai direto para o seu post, mas com um URL diferente (que permitirá a jogabilidade correta). Acho o método F5 desajeitado.
— kaoD

14

Xadrez Pokémon para 2 jogadores [Trabalho em andamento]

Porque é mais divertido assim. Em breve: AI, grade isométrica e sombras!

http://minite.ch/chess/?i=1 http://minite.ch/chess/?i=2 http://minite.ch/chess/?i=3 http://minite.ch/ xadrez /? 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/ xadrez /? 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/ xadrez /? 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

Não en passant ou roque, desculpe. Detecção de xeque-mate / cheque / impasse a ser implementada. Sprites a partir daqui: http://floatzel.net/pokemon/black-white/sprites/

Aqui está a fonte:

<?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;
?>

Eu amo isso, mas os dois lados devem ser Pokemon diferentes!
— MrZander

Muito agradável. Eu gosto que a mesa vire sempre que a virada mudar.
— Cristian Lupascu

11
E no PHP, +1 nos jogos PHP: p
— Event_Horizon

11
@hhh: Não, você adiciona parâmetros à mesma página e gera as imagens no servidor verificando o Referercabeçalho.
— precisa saber é

5
. :-( seus sprites morreram.
— Justin

10

Jogo "Simon diz"

Infelizmente, não pude chegar a esse envio dentro do prazo (um tanto arbitrário), mas eu realmente queria demonstrar animação em um jogo de perfil de usuário e nenhum dos envios anteriores é animado. Este jogo é um clone do clássico jogo de Milton Bradley, Simon , no qual o jogador tenta repetir uma sequência cada vez maior de sinais.

Informações sobre este jogo, incluindo seu código fonte, estão disponíveis na página do GitHub . Pode haver falhas gráficas ocasionais (especialmente em computadores Windows) decorrentes da "animação da paleta" hackeada que evita a necessidade de uma biblioteca de desenhos gráficos. A existência dessas falhas pode servir como uma desculpa útil para perder rapidamente este jogo por causa da memória terrível.

Além disso, os efeitos de alta latência e largura de banda limitada podem tornar esse jogo muito mais desafiador do que o original. Eu acho que, para conseguir muito mais do que cinco pontos (quando o jogo acelerar), você precisará determinar qual luz pisca mais uma vez do que na rodada anterior, em vez de depender da sequência correta (o que é muito difícil de definir). Faz).

Se este jogo não funcionar para você (ele é reiniciado toda vez que você clica em um botão), seu navegador pode estar bloqueando o cookie. Ainda não adicionei uma solução alternativa, portanto, por enquanto, use o Chrome, Opera ou Firefox ou altere temporariamente as configurações de cookies do Internet Explorer ou Safari.

Editar 2018-05-24: neste momento, excluí a instância Heroku acessível ao público deste aplicativo. Posso ou não colocar o aplicativo online novamente em uma data posterior. O código do aplicativo ainda está disponível no GitHub, portanto, você pode executá-lo localmente ou criar sua própria instância do aplicativo Heroku, se desejar jogar o jogo.


+1 Isso é absolutamente brilhante! Nunca pensei em fazer gifs animados gerados dinamicamente: P
— mellamokb

2

Pedra Papel Tesoura

Todos os links vão para a minha página de perfil para maior velocidade.

O jogo

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.