ユーザープロファイルミニゲームを作成する


49

昨日、私は非常に賢いことにつまずいた。

ミニテックの三目並べプロファイルゲーム

はい、それはユーザープロファイルページでの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

リセットする

もっと良くできますか?

  • 投稿された回答(またはユーザープロフィールページ)で実用的なゲームを作成します。これは、所有するWebサーバーを適切に構成する(またはWebサーバーとして機能するプログラムを作成する)ことで行われ、リファラーを使用してユーザーがゲームに与えるコマンドを決定することで、コンテンツをポストに埋め込みます。
  • 最もクールなアイデア(ほとんどの票)がカナダの日(2012年7月1日日曜日午後11時59分EST)までに競争に勝ちます
  • 同点の場合、古い回答が優先されます。

1
+1シンプルだが素晴らしいアイデア!ところで-締め切りのために私はあなたが意味を考える年6月 2 2012年
クリスティアンLupascu

Derp、はい、私はそうしました、ありがとう:)
mellamokb

1
@boothby:私は実際に答えを削除することを考えていました。意図は、コンテストに勝つためではなく、具体的な例を提供することでした(または投票、私は担当者をあまり気にしません)。競争に対して建設的な提案を提供できますか?締め切りは何になりますか?参加する意欲を高めるために、仕様をどのように変更すべきですか?
mellamokb

4
ミニテックのAIが三目並べの完璧なゲームをプレイできないことに気付いたのです。中央、左下、上中央、右中央、左中央を再生します。
PhiNotPi

1
@ Mr.Wizard:FF 12.0とWindows 7で正常に動作していますが、動作していないものに関する詳細を投稿できますか?
クリストフ

回答:


27

コンウェイのゲームオブライフ

+1世代 - +5世代 - ズームイン - ズームアウト

負荷パターン: ランダム - グライダー - gunstar - カタツムリ - lwss - lightspeedoscillator1 - タンブラー

PythonおよびSVG出力を使用しました。最初は単一のピクセルを使用しようとしました(したがって、単一のセルを切り替えることができます)が、ブラウザは画像を順番に読み込まないため、うまくいきませんでした。また、私のようなWebサーバーをクラッシュさせることなく、このような非常に大きなパターンを作成できます。

更新:

私はPythonでいくつかの楽しみを持ち、いくつかの機能と改善を追加しました:

  • 人口カウント、ズーム、名前を含むHUDを追加しました
  • パラメータ(例)を使用して、rle形式のパターンを(長いリスト経由で)ロードできるようになりました。ファイルサイズは1.5kBに制限されていますpattern?pattern=glider
  • nextパラメータを使用して、一度に5世代に制限されたn世代を転送できます
  • アルゴリズムが少し改善されました。それは本当に速いわけではありません、私はこれをシンプルに保ちたい
  • また、スタンドアロンで動作するようになりました(リファラーまたは独自のクエリ文字列を使用):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素晴らしい!1つの提案:#5946リンクに追加すると、更新のたびに投稿にジャンプして戻ります。
mellamokb

うーん、少なくとも試してみたらうまくいった..ああ。ハノイの塔では、常に異なるペグをクリックしているためです。うーん
mellamokb

@mellamokbは動作しますが、同じリンクを今すぐ2回クリックすることはできません。
コピーして

ああ、私はその笑に気付いた。次世代を行うときnext、最初の後に何度も何度もリンクをクリックするのではなく、将来の反復のためにF5を押すだけという免責事項を提供できると思います。
mellamokb

1
@mellamokbありがとう。私の意見では、このプラットフォームで回答を受け入れる必要はありません。チャレンジが終了したように見えるためです。
コピー

35

C#-Stack Exchange Hangman

このハングマンゲームのStack Exchange Webサイトの名前を推測します。



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

このコード以外に、3つのクラスがありますが、それらは非常に長く単純であるため、含まれていません。

  • HangmanGame -ゲームのビジネスルールが実装される場所
  • HangmanImageRenderer -すべてのGDIのugさをカプセル化するクラス
  • ImageResult- ActionResult動的に生成された画像を返すために使用されるカスタム

コードリスト全体は、http://pastebin.com/ccwZLknXで入手できます。


+1うわー、あなたたちは素晴らしいです:)。これまでのアイデアが好きです!
mellamokb

クール、appharbor.comのことは聞いたことがない。答えをホストするために本当にお金を払っていますか?
mellamokb

@mellamokbいいえ、私はAppharborの無料ホスティングプランを使用しています。これが
頻繁に

2
必要に応じて、カスタムサブドメインホスティングとホスティングサイトへのFTPアクセスを提供できます。
mellamokb

@mellamokbに感謝しますが、このホスティングはうまくいくと思います。多くのクリックについて冗談を言っていました。:)
クリスチャンルパスク

19

クロホバン![WIP]

Clojureを習得するためにこれからより大きなゲームを作りたいと思ったので、これには成功するまでに時間がかかりました(そしてかなり大きくなりました)。

クロホバン! Restart levelNew game

。。

- No-op*

。。

**(ゲームが応答しなくなった場合はここをクリック)*

説明書

あなたは頑固ロビーなロボット、ロビーです。あなたFlipCo Industriesはヘビーロードキャリアとして働いています。あなたの仕事は、それぞれを移動させることであるbox 箱goal ゴールできるだけ少数のステップとして支出。FlipCoの施設は危険です。たくさんの挑戦と発見すべき特別な場所があります。

動けなくなる場合は、クリックしますRestart level(ただし、歩数はリセットされません!)


また、Clojobanのフロントページでプレイすることもできます(ただし、チャレンジの目的が多少損なわれます)。これは悪名高いアンカーの問題を修正し、クロスサイトCookieを必要とせず、キーボードの矢印キーでプレイできます。私のユーザープロフィールでもプレイできます迷惑なアンカーの問題もなく、ページます。

Firefoxでは、読み込み中に画像がちらつきません。そのため、再生が少し快適になります。

このゲームは完成から遠いですがクロホバンはまだ進行中の作業です。ClojobanのGitHubプロジェクトページで完全なソースコードを見ることができますREADME貢献に関する情報があります。レベルも必要です!例のレベルでレベル形式を参照してください。Clojobanの課題トラッカーを覗いて、次の予定を確認できます!


今、あなたの評判は11です:)
mellamokb

@mellamokbありがとう!ゲームは現在埋め込まれています:)
アルバロクエスタ

どうやらこれはあまり注目されなかったようだ。改善するためのヒントはありますか?
アルバロクエスタ

あなたの答えは良いです、この質問は全体的に停滞していると思います。過去数日間、あまり活動や投票がありませんでした。
mellamokb

それは素晴らしいゲームです!スタンドアロンバージョンを作成する必要があると思います。私は第3レベルに到達し、No-opボタンを押すのをやめました。:)とにかく、素晴らしい仕事です!
クリスチャンルパスク

17

迷路

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

http://dev.horemag.net/2008/03/01/php-maze-generation-class/にあるPHP迷路ジェネレーターから始めました。

編集:出力をSVGではなくPNGに変更しました(クロスブラウザの互換性を向上させるため)。

編集2: IE Cookieの互換性を修正するためのヘッダーを追加しました。これで、すべての主要なブラウザーで正常に動作するはずです。

アンカーリンクのために同じ方向を2回取ると、画像は更新されません。2度目にF5を押すか、stackoverflowプロファイルで迷路再生します

編集3:簡単に同じ方向を2回取ることができるようにノーオペレーションボタンを追加しました(下記のコメントを参照)。

<?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:ありがとう。#リンクを含めることを考えましたが、問題は同じ方向を2回取るとページが更新されないことです(迷路で発生する可能性があります;-)。人々が同じ方向を取りたい場合は、もう一度F5キーを押す必要があるので、それらを追加しました。別のオプションは、ここで再生することです(私のSOプロファイル:stackoverflow.com/users/81179/christophed
ChristopheD

同じ方向に2回移動しようとすると、更新が簡単になるように、単純な操作なしのリンク(更新?)が必要です。
kaoD12年

@kaoD:#質問に対する正しい答えにジャンプするアンカー部分()がなければ(内部的に、ページを更新せずに)、単純なページの更新はうまく機能します(同じ迷路も利用できるリンクされたプロファイルで見ることができます) 。しかし、問題は、更新するたびにページの上部にいることです。本当の問題は、ここでStackOverflowの回答に含めることができるものが本当に限られていることです(当然の理由で)。たとえば、任意のJavascriptを使用することはできません。簡単な方法についてはわかりません。
クリストフ

あなたはまだアンカーを持っていて、投稿にまっすぐに行くことができますが、異なるURLで(正しいゲームプレイを可能にします。)F5メソッドは不格好です。
kaoD

14

2プレイヤーポケモンチェス[進行中]

こうすればもっと楽しくなるからです。いつか登場:AI、等尺性グリッド、影!

http://minite.ch/chess/?i=1 http://minite.ch/chess/?i=2 http://minite.ch/chess/?i=3 http://minite.ch/ chess /?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/ chess /?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/ chess /?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では、PHPゲームの+1:p
Event_Horizo​​n

1
@hhh:いいえ、同じページにパラメーターを追加し、Refererヘッダーを確認してサーバー上に画像を生成します。
-Ry-

5
。:-(あなたのスプライトが死亡している。
ジャスティン

10

「サイモンは言う」ゲーム

残念ながら、(ややarbitrary意的な)期限までにこの提出物を期限内に受け取ることはできませんでしたが、このようなユーザープロファイルゲームでアニメーションを実際にデモしたかったため、以前の提出物はアニメーション化されませんでした。このゲームは、古典的なMilton BradleyゲームSimonのクローンであり、プレイヤーはますます長い信号のシーケンスを繰り返します。

ソースコードを含むこのゲームに関する情報は、GitHubページで入手できます。グラフィック描画ライブラリの必要性を回避するハック的な「パレットアニメーション」に起因するグラフィカルな不具合(特にWindowsコンピューター)が発生する場合があります。これらのグリッチの存在は、ひどい記憶のためにこのゲームをすぐに失うための便利な言い訳として役立ちます。

さらに、高いレイテンシと限られた帯域幅の影響により、このゲームは元のゲームよりもはるかに難しくなります。5つ以上のポイントを獲得するには(ゲームが最初にスピードアップするとき)、正しいシーケンスに依存するのではなく、前のラウンドよりも1回多く点滅するライトを決定する必要があると思います(非常に難しい行う)。

このゲームが機能しない場合(ボタンをクリックするたびに再起動します)、ブラウザがCookieをブロックしている可能性があります。まだ回避策を追加していませんので、当面の間、Chrome、Opera、Firefoxを使用するか、Internet ExplorerまたはSafariのCookie設定を一時的に変更してください。

編集2018-05-24:現時点では、このアプリの公開アクセス可能なHerokuインスタンスを削除しました。後日、アプリをオンラインに戻す場合としない場合があります。アプリのコードは GitHubの上でまだ利用可能であるので、あなたはどちらかそれをローカルに実行するか、またはあなたがゲームをプレイしたい場合は、独自のHerokuのアプリインスタンスを作成することができます。


+1それは絶対に素晴らしいです!動的に生成されたアニメーションgifを実行することを考えたことがありません
。P– mellamokb

2

最初はグー、じゃんけん

すべてのリンクは、速度のために私のプロフィールページに移動します。

ゲーム

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.