ポンクソフト

jQuery UI Sortableで1ラインオセロゲーム - jQuery入門

前ページ jQuery入門 TOP 次ページ

目次

  1. jQuery入門
  2. jQueryのインストール・簡単な使い方
  3. クイズゲームの作り方
  4. 秘密の暗号を作ってみよう(たぬき暗号)
  5. アクションゲームを作ってみよう(ぬりかべ)
  6. 画像を使ったジグソーパズルを作ってみよう
  7. もぐらたたきっぽいゲーム
  8. ドラッグ可能なポップアップウインドウを作ろう
  9. jQuery UI Sortableで1ラインオセロゲーム
  10. ブラウザ全体をブロックしてみる
  11. Geolocation APIを使って都道府県のセレクトボックスを現在地に近い順にソートする
  12. 発生したイベントの状態を保持・保存する6つのパターン
  13. Ajaxを利用したシンプルなイメージギャラリーを作ってみる
  14. テーブルにページ送り(ページング)を実装してみる
  15. jQuery UI Draggableを使って付箋(sticky)を作ってみる
  16. カラムでソートできるテーブルを自作してみる
  17. テーブルを使ったシンプルなドット絵エディタを作ってみる
  18. iPhoneのようにマウスではじいてスクロール(フリックスクロール)を実装してみる
  19. テキストフィールドの数値をマウスの上下移動で増減する
  20. iPhoneのように大きい画像の表示領域をマウスのドラッグで移動してみる
  21. iPhoneのように画像をダブルクリックした地点を中心に拡大縮小する
  22. リアルタイムプレビュー付きのHTMLエディタを作ろう
  23. 保存できる付箋を作ってみる(Cookie、localStorage)

1ラインオセロ

jQuery入門の第9回目は、jQuery UIを使ってみます。jQuery UIは、jQuery要素に対してドラッグ&ドロップ・リサイズ・選択などの基本機能、さらにダイアログ・タブ・スライダーと言った多様なUIを追加してくれるプラグインです。その中で今回は、要素をドラッグして並び替えを可能にする「Sortable」の機能を使ってみましょう。作るものはオセロ・・・はソースが長くなるので1行だけのオセロゲームです。

実行結果

コマをドラッグして移動すると、普通のオセロのようにコマが裏返ります。決められた手数以内で全てのコマを黒くするとクリアです。全5面でだんだん難しくなります。

1ラインオセロのソース

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.0/jquery.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/jquery-ui.min.js"></script>
<title>1ラインオセロ</title>
<script>
$(function() {
  var round = 0;
  var remain;
  var field = [
    [1, "●○●○○"],
    [1, "●○○○●○●"],
    [2, "●○●○●○●○●"],
    [2, "●○●●○●●●○"],
    [2, "●●○●●○○●●●○●○●●"]
  ];

  // 面の開始
  function start() {
    remain = field[round][0];
    $('#field')
    .html($.map(field[round][1].split(''), function(i) {
      return '<div>' + i + '</div>';
    }).join(''));

    $('#round').text(round + 1);
    $('#remain').text(remain);
  }
  start();

  $('#field').sortable({
    axis: 'x',
    update: function(e, u) {
      // 裏返す
      var color = u.item.text();
      $.each(['prev', 'next'], function(i, dir) {
        var rev = false;
        (function (item) {
          if (item.length < 1) return;
          if (item.text() == color) rev = true;
          else arguments.callee(item[dir]());
          if (rev) item.text(color);
        })(u.item[dir]());
      });

      // クリアチェック
      $('#remain').text(--remain);
      if (!$('#field div').is(':contains("○")')) {
        if (++round >= field.length) {
          alert("オールクリア!");
        } else {
          alert("クリア!");
          start();
        }
      }

      // ゲームオーバーチェック
      if (remain <= 0) {
        $('#field').sortable('destroy');
        alert("ゲームオーバー");
      }
    }
  });
});
</script>
<style>
div {
  float: left;
  cursor: pointer;
}
</style>
</head>
<body>
<p>全て●にせよ! 第<span id="round"></span>面 残り<span id="remain"></span>手</p>
<div id="field"></div>
</body>
</html>

プログラムの解説

<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/jquery-ui.min.js"></script>
GoogleでホスティングされているjQuery UIのバージョン1.7.1を読み込んでいます。

変数定義

var round = 0;
現在の面数です(実際の面数は+1される)。
var remain;
残り手数です。これが0になるとゲームオーバーです。
var field = [
  [1, "●○●○○"],
  [1, "●○○○●○●"],
  [2, "●○●○●○●○●"],
  [2, "●○●●○●●●○"],
  [2, "●●○●●○○●●●○●○●●"]
];
各面の配置データ配列です。上から順に1~5面のデータで、それぞれの要素がさらに配列になっており、最初の要素が手数、次の要素が実際の配置データです。

コマ表示

$('#field')
.html($.map(field[round][1].split(''), function(i) {
  return '<div>' + i + '</div>';
}).join(''));
配列fieldから画面にコマを書き出している部分です。コマの並びの文字列を1文字ずつdivで囲っています。$.mapはオブジェクトや配列の要素それぞれについて指定した関数を実行するjQueryのユーティリティ関数です。

並び替え関数

$('#field').sortable({・・・});
この部分で要素の並び替えを設定しています。並び替えの対象になる要素は#field以下の要素全て、つまり先ほどdivで囲った○,●文字全てです。引数のハッシュで並び替え動作の設定を行ないます。
axis: 'x',
ドラッグを横方向のみに制限しています。
update: function(e, u) {・・・}
ドラッグが完了して、実際に要素が並び替えられたときに呼ばれる関数を設定します。要素が並び替えられないときは関数が呼ばれないので注意してください。引数のeはイベントオブジェクト、uは各種オプションですが、今回使っているのはドラッグされた要素を表すu.itemだけです。

コマを裏返す

コマをドラッグしてボタンを離したときにコマを裏返す処理が実行されるわけですが、結構面倒な処理なので今回は再帰を使ってなるべくシンプルに実装してみました。
var color = u.item.text();
まず最初に裏返すときのチェック用に、ドラッグされた要素のテキスト(●か○)を保存します。
$.each(['prev', 'next'], function(i, dir) {・・・}
$.eachもjQueryのユーティリティ関数で、第1引数で指定したオブジェクトや配列のそれぞれの要素に対して関数を実行します。引数iには配列のインデックス、dirには値が入ります。
(function (item) {・・・})(u.item[dir]());
JavaScriptの独特な書き方です。「function(i) {・・・}(x)」という書き方で、匿名関数を定義して、さらに実引数xで実行までを行なうのです。ここでは実引数「u.item[dir]()」が「item」に代入されて実行されます。「u.item[dir]()」の部分ですが、dirには先ほどの$.eachによって「prev」もしくは「next」の文字が入るので、「u.item['prev']()」か「u.item['next']()」となりますが、JavaScriptのオブジェクトの各メンバはハッシュとしてアクセスすることができます。つまり「u.item.prev()」か「u.item.next()」となるわけです。prev()は要素のひとつ前の兄弟要素、nextは要素のひとつ後の兄弟要素を辿るjQueryのメソッドです。
if (item.length < 1) return;
兄弟要素が存在するときは、要素の長さlengthは「●」か「○」で必ず1になるハズなので、ここの条件が満たされるのは先頭か最後にたどり着いたときです。
if (item.text() == color) rev = true;
先頭か最後にたどり着く前に、置いたコマと同じ色のコマが現れたときは、挟める状態となるのでフラグを立てています。
else arguments.callee(item[dir]());
置いたコマと違う色のコマが現れたときは、裏返される可能性のあるコマですが、とりあえず置いておき次の兄弟要素のコマを再帰によって辿ります。
if (rev) item.text(color);
フラグが立っていたならば、さきほどとりあえず置いておいたコマを裏返します。

クリア・ゲームオーバー

if (!$('#field div').is(':contains("○")')) {・・・}
isは、jQueryの要素に対して、引数で指定したセレクタに合致する要素がひとつでもある場合にtrueになるメソッドです。:containsは、要素のテキストに指定した文字列が含まれているものを選択するセレクタです。ここでは、白丸がひとつも含まれていない場合、ifの条件が満たされ、クリアとなります。
$('#field').sortable('destroy');
ゲームオーバーのとき、並び替えを無効にしています。
前ページ jQuery入門 TOP 次ページ
このエントリーをはてなブックマークに追加 そっか0

このページに関するコメントをどうぞ

お名前:



rrrあいうえ
2017/02/22 00:22


あああ
2017/02/12 19:10

名無しのリーク
香川県ルー餃子のフジフーヅはバイトにパワハラの末指切断の重傷を負わせた犯罪企業
2017/01/26 03:04


あああああ
2017/01/20 17:43

カワカワ
ああああああああ
2017/01/16 08:48

fsfさ
dふぁfだs
2017/01/05 19:56

ああ
あああ
2016/11/09 18:25

test
サンプル
2016/11/08 16:42

セレクタの指定方法を返る
HTML部分
~~~~
<div>問題1</div>
<p>
<input type="radio" name="food" value="1">そば
<input type="radio" name="food" value="2">うどん
<input type="radio" name="food" value="3">ラーメン
</p>

<div>問題2</div>
<p>
<input type="radio" name="food01" value="1">いか
<input type="radio" name="food01" value="2">たこ
<input type="radio" name="food01" value="3">えび
<input type="radio" name="food01" value="4">えび
</p>
2016/11/08 14:31

セレクタの指定方法を返る
>教えてくださいさん
セレクタの指定方法をinputからnameに変える方法はいかがでしょうか。

//問題1
$(function() {
$("*[name=food]").click(function() {
if($(this).val()==2)
{
alert('正解');
}
});
});

//問題2
$(function() {
$("*[name=food01]").click(function() {
if($(this).val()==2)
{
alert('正解');
}
});
});
2016/11/08 14:31

残りを読む »