Створіть міні-гру профілю користувача


49

Вчора я натрапив на дуже розумну річ.

Профільна гра minitech на тик-так-носок

Так, це робоча реалізація Tic-Tac-Toe на сторінці профілю користувача від @minitech. Звичайно, щойно я це побачив, мені довелося переробити його ідею і однозначно : P

вежі mellamokb з ханойської профільної гри

Ось мій власний приклад, вбудований безпосередньо в допис. Це невдала помилка через пару деталей щодо впровадження, для яких я не розробив хорошого рішення. Іноді після натискання на кілочок він не оновлюється належним чином, поки інша сторінка не оновиться:

Вежі Ханої

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

Скидання

Чи можете ви зробити краще?

  • Створіть робочу гру в опублікованій відповіді (або на сторінці свого профілю користувача). Це робиться за допомогою відповідного налаштування власного веб-сервера (або написання програми, яка виступає як веб-сервер), та вбудовування вмісту з нього в допис, використовуючи реферер, щоб визначити, які команди користувач дає гру.
  • Найкрутіша ідея (більшість голосів) перемагає у конкурсі від дня Канади (неділя, 1 липня 2012 р., 23:59 EST)
  • У разі вирівнювання виграє старша відповідь.

1
+1 Проста, але геніальна ідея! BTW - на кінцевий термін, я думаю, ви маєте на увазі 2 червня 2012.
Крістіан Лупаску

Дерп, так, я зробив, спасибі :)
mellamokb

1
@boothby: Я насправді думав над тим, щоб видалити свою відповідь. Намір був навести конкретний приклад, щоб не виграти конкурс (або голоси, я не дуже переймаюся реп.). Чи можете ви надати якісь конструктивні пропозиції до змагань? Яким би ви хотіли, щоб цей термін був? Як слід змінити специфікацію, щоб мотивувати вас до участі?
mellamokb

4
Я щойно помітив, що AI мінітек не може грати в ідеальну гру в тик-так. Грайте центр, ліворуч знизу, верхній центр, правий центр, лівий центр.
PhiNotPi

1
@ Mr.Wizard: тут добре працює FF 12.0 та Windows 7, чи можете ви опублікувати більше деталей про те, що не працює?
ChristopheD

Відповіді:


27

Гра життя Конвея

+1 покоління - +5 поколінь - збільшення - зменшення

Шаблон навантаження: випадковий - планер - вогнепальна зірка - равлик - lwss - lightpeedoscillator1 - tumbler

Використовується вихід Python та SVG. Я спробував використовувати спочатку окремі пікселі (щоб ви могли перемикати одиничні комірки), але це не вийшло, оскільки браузер не завантажує зображення по порядку. Крім того, можливі набагато більші шаблони, подібні до цього, без збою мого веб-сервера.

Оновлення:

Я повеселився з python та додав кілька функцій та вдосконалень:

  • Додано HUD з кількістю населення, збільшенням та назвою
  • Шаблони у форматі rle тепер можна завантажувати ( довгий список , через ) за допомогою patternпараметра (наприклад ?pattern=glider). Розмір файлів обмежений 1,5 кБ
  • Може передати n поколінь, обмежених 5 за один раз, використовуючи nextпараметр
  • Трохи вдосконалений алгоритм. Хоча це не дуже швидко, я хочу, щоб це залишалося простим
  • Він також працює автономно (використовує референт або власну рядок запитів): 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()

Ви можете взяти мій код як шаблон для подальших подань python fastcgi.


+1 Дивовижно! Один із пропозицій: додайте #5946до своїх посилань, і воно повернеться до вашої публікації після кожного оновлення.
mellamokb

хм .. принаймні це спрацювало, коли я спробував це ... ах. тому що в Ханойських вежах ти завжди натискаєш на різні кілочки. хм
mellamokb

@mellamokb працює, але ви не можете двічі натиснути одне посилання
скопіюйте

Так, я щойно зрозумів, що це хаха. Здогадується, ви можете надати відмову від того, що, роблячи наступне покоління, просто натисніть F5 для майбутніх ітерацій, а не клацніть nextпосилання знову і знову після першого разу.
mellamokb

1
@mellamokb дякую. На мою думку, вам не потрібно приймати відповіді на цій платформі, тому що це виглядає так, ніби виклик закритий
скопіюйте

35

C # - обмінник стека

Вгадайте назви веб-сайтів Stack Exchange у цій грі 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


Це було зроблено за допомогою ASP.NET MVC 3.0 . Ось код того, Controllerщо робить трюк:

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

Крім цього коду, є ще три класи, які я не включив, оскільки вони досить довгі та прості:

  • HangmanGame - ось де реалізовані правила ігрового бізнесу
  • HangmanImageRenderer - клас, який інкапсулює все неподобство GDI
  • ImageResult- звичай, ActionResultякий використовується для повернення динамічно генерованого зображення

Весь перелік коду доступний на веб-сайті http://pastebin.com/ccwZLknX


+1 Вау, ви, хлопці, приголомшливі :). Як ідеї поки що!
mellamokb

Класно, ніколи не чув про appharbor.com. Ви справді платите, щоб прийняти свою відповідь?
mellamokb

@mellamokb ні, я використовую план безкоштовного хостингу Appharbor. Якщо на це багато натискають, я думаю, що мені доведеться заплатити, хоча ... :)
Крістіан Лупаску

2
Я збирався зазначити, якщо потрібно, я можу надати хостинг для субдомену та FTP доступ до свого хостинг-сайту.
mellamokb

@mellamokb дякую, але я думаю, що цей хостинг зробить. Я просто жартував про багато кліків. :)
Крістіан Лупаску

19

Clojoban! [WIP]

Я хотів зробити з цього більшу гру, щоб навчитися Clojure , тому це зайняло деякий час, щоб витягнути (і отримало досить велику кількість).

Clojoban! Restart levelNew game

. .

- No-op*

. .

** (натисніть тут, якщо гра не реагує) *

Інструкції

Ви - Робі Робі, працьовитий робот. Ви працюєте FlipCo Industriesяк вантажник великого вантажу. Ваше завдання - перевести кожен box Коробкана goal Метавитрату якомога менше кроків. FlipCoоб'єкти небезпечні . Є багато викликів та спеціальних місць, які потрібно відкрити.

Якщо ви застрягли, натисніть Restart level(але кількість кроків не скинеться!)


Ви також можете грати на титульній сторінці Clojoban (хоча це щось руйнує мету виклику.) Це виправляє сумнозвісну проблему з якорями, не вимагає міжбіркових файлів cookie, і ви можете грати за допомогою клавіш зі стрілками клавіатури! Ви також можете грати на моїй сторінці профілю користувача без набридливої ​​проблеми з якорями.

У Firefox зображення не мерехтить під час завантаження, тому грати трохи зручніше.

Ця гра далека від завершення, Clojoban все ще триває . Повний вихідний код ви можете побачити на сторінці проекту Gjoth на Clojoban . У README є деяка інформація про внесок . Мені потрібні рівні! Дивіться формат рівня на прикладних рівнях . Ви можете заглянути в трекер програми Clojoban і подивитися, що буде далі!


Тепер ваша репутація 11 :)
mellamokb

@mellamokb дякую! Гра вбудована зараз :)
Альваро Куеста

Мабуть, це не приділяло великої уваги. Якісь поради щодо покращення?
Альваро Куеста,

Ваша відповідь хороша, я думаю, що це питання загалом застоюється. Останні кілька днів я не бачив активності та голосів.
mellamokb

Це чудова гра! Я думаю, вам слід скласти окрему версію; Я дійшов до третього рівня і позбувся натискання кнопки No-op. :) У всякому разі, чудова робота!
Крістіан Лупаску

17

Лабіринт

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

Я почав з генератора лабіринтів PHP, якого я знайшов тут: http://dev.horemag.net/2008/03/01/php-maze-generation-class/ .

EDIT : змінив вихід на PNG замість SVG (для кращої сумісності браузера).

EDIT 2: додано заголовок для фіксації сумісності файлів cookie IE. Зараз слід правильно працювати у всіх основних браузерах.

Зображення не оновлюється, якщо ви двічі проходите в одному напрямку (через якірні посилання). Натисніть F5 вдруге або відіграйте лабіринт у моєму профілі stackoverflow .

EDIT 3: Додана кнопка без відключення для легкого ведення того ж напрямку двічі (див. Коментарі нижче).

<?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 Приємно! для кращого досвіду додайте #answer-6171в кінці своїх посилань. Інакше нікому не вистачить терпіння, щоб розгадати лабіринт.
Крістіан Лупаску

@ W0lf: Дякую Я думав про включення #посилань, але проблема полягає в тому, що вони не оновлюють сторінку, коли ви переходите в той самий напрямок двічі (що може статися в лабіринті ;-). Я додав їх зараз, тому людям доведеться натискати F5 вдруге, коли вони захочуть піти в той же напрямок. Ще один варіант - відтворити його тут (мій профіль SO: stackoverflow.com/users/81179/christophed )
ChristopheD

Я б хотів просте посилання без операцій (оновити?), Щоб зробити оновлення простішим при спробі переміщення двічі в одному напрямку :)
kaoD

@kaoD: Без якірних частин ( #), які переходять до правильної відповіді на питання (внутрішньо, без оновлення сторінки), просте оновлення сторінки спрацювало б добре (як ви бачите на моєму пов'язаному профілі, де також доступний той самий лабіринт) . Але проблема тоді полягатиме в тому, що ви опинитесь у верхній частині сторінки після кожного оновлення. Справжня проблема полягає в тому, що ми насправді обмежені тим, що можемо включити у відповідь тут на StackOverflow (з незрозумілої причини поза курсом). Я не маю уявлення про простий вихід.
ChristopheD

Ви можете все ще мати якір, і він піде прямо на ваш пост, але з іншою URL-адресою (що дозволить правильно грати.) Я вважаю метод F5 незграбним.
якDD

14

Шахи з покемоном для двох гравців [Робота триває]

Тому що так веселіше. Деякий день: AI, ізометрична сітка та тіні!

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

Немає жодних пасажирів та вигуків, вибачте. Виявлення контрольних / контрольних / тупикових подій, які потрібно здійснити. Спрати звідси: http://floatzel.net/pokemon/black-white/sprites/

Ось джерело:

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

Я люблю це, але обидві сторони повинні бути різними Покемонами!
MrZander

Дуже хороша. Мені подобається, що таблиця повертається кожного разу, коли змінюється черга.
Крістіан Лупаску

1
А в PHP +1 для ігор PHP: p
Event_Horizon

1
@hhh: Ні, ви додаєте параметри на ту саму сторінку і генеруєте зображення (зображення) на сервері, перевіряючи Refererзаголовок.
Ри-

5
:-(. Ваші спрайти померли.
Джастін

10

Гра "Саймон каже"

На жаль, я не зміг отримати своє подання вчасно (дещо довільно), але я дуже хотів продемонструвати анімацію в такій грі профілю користувача, і жодне з попередніх матеріалів не анімоване. Ця гра є клоном класичної гри Мілтона Бредлі Саймона , в якій гравець намагається повторити все більш довгу послідовність сигналів.

Інформація про цю гру, включаючи її вихідний код, розміщена на її сторінці GitHub . Можуть виникати випадкові графічні глюки (особливо на комп’ютерах Windows), що виникають внаслідок шахрайської «палітри анімації», що дозволяє уникнути необхідності в бібліотеці графічних малюнків. Наявність цих глюків може послужити корисним приводом для швидкої втрати цієї гри через жахливу пам’ять.

Крім того, ефекти високої затримки та обмеженої пропускної здатності можуть зробити цю гру набагато складнішою, ніж оригінал. Я думаю, що для того, щоб отримати набагато більше п'яти очок (коли гра вперше прискориться), вам потрібно буде визначити, яке світло блимає один раз, ніж у попередньому раунді, а не залежно від правильної послідовності (що дуже важко робити).

Якщо ця гра не працює для вас (вона перезапускається кожного разу, коли ви натискаєте кнопку), ваш веб-переглядач може блокувати файл cookie. Я ще не додав рішення, тому наразі скористайтеся Chrome, Opera або Firefox або тимчасово змінивши налаштування файлів cookie Internet Explorer або Safari.

Редагувати 2018-05-24: На цей час я видалив загальнодоступний примірник Heroku цього додатка. Я можу або не можу пізніше відкладати додаток в Інтернеті. Код програми все ще доступний на GitHub, тому ви можете або запустити його локально, або створити власний екземпляр програми Heroku, якщо хочете пограти в цю гру.


+1 Це абсолютно геніально! Ніколи не думав робити динамічно генеровані анімовані gif: P
mellamokb

2

Рок, папір, ножиці

Усі посилання на швидкість переходять на мою сторінку профілю.

Гра

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.