プログラミング

ポケモン預かりシステム編 ボックスの作成 PHPポケモン 86

PHP PHPポケモン ポケモン
ポケモン預かりシステム編 ボックスの作成 PHPポケモン 86

ポケモン預かりシステムの実装

今回は、前回ざっくりと仕様決めをした「ポケモン預かりシステム」を実装していきます。ボックス内では操作する項目が多いため、ボックス自体に1つの画面を用意して、できる限りPHPによる制御だけで完結できるように作成していきます。

 

ボックスクラスの作成

それではまず、今回の主軸となるボックスクラスを作成しましょう。以下、文中でのポケモン預かりシステムについては「ポケボックス」と表記していきます。

 

ポケモン預かりシステム(/Classes/Pokebox.php
<?php
// ポケモンボックス
class Pokebox
{
    /**
    * ポケモンの格納ボックス
    * @var array
    */
    protected $pokebox = [];
 
    /**
    * 選択中のボックス番号
    * @var integer|null
    */
    protected $selected = null;
 
    /**
    * @return void
    */
    public function __construct()
    {
        //
    }
 
    /**
    * 全ボックスの取得(暗号化状態で返却)
    * @return array
    */
    public function getPokebox(): array
    {
        return $this->pokebox;
    }
 
    /**
    * ボックスが選択状態になっているかの確認
    * @return boolean
    */
    public function isSelected(): bool
    {
        if(is_null($this->selected)){
            return false;
        }else{
            return true;
        }
    }
 
}

 

プロパティとして用意したのは、ボックスを管理するためのpokeboxと、現在選択中のボックスを判定するためのselectedの2つです。

メソッドには、ボックス内の情報をそのまま返却するgetPokeboxと、現在ボックスが選択された状態になっているかを確認するためのisSelectedの2つです。

 

起動

ポケボックスのクラスの役割についてですが、パソコンをイメージしてみるとわかりやすいでしょう。通常時は余計な処理を省くためにも停止状態としておき、必要な際に起動します

起動処理についてですが、ボックスを選択する(selectedプロパティへ値をセット)することが、起動状態かどうかの判定となります。なので、こちらをセットするためのメソッドをトレイトを作成して追加しましょう。

 

ポケボックスのボックス操作トレイト(/App/Traits/Class/Pokebox/ClassPokeboxTrait.php
<?php
trait ClassPokeBoxBoxTrait
{
 
    /**
    * ボックスを選択状態にする(起動)
    * @param box_number:integer
    * @return boolean
    */
    public function selectBox(int $box_number): bool
    {
        if(isset($this->pokebox[$box_number])){
            $this->selected = $box_number;
            return true;
        }else{
            return false;
        }
    }

 

ボックス自体は配列による添字管理のため、引数ではボックス番号を受け取ります。もしそそのボックスが存在していれば、selectedプロパティに値をセットしてtrueを返却、見つからなければfalseを返却します。

単純ですが、これが擬似的な起動処理となります。

 

終了

次にボックスの終了処理についてです。ボックス操作が終われば、原則としてボックスの選択状態は解除します。あくまで「起動」→「操作」→「終了」という一連の流れをルール付しておくことが目的の1つです。ボックス操作では、ポケモンオブジェクトの移動が伴うため、些細なエラーでもデータの消失に繋がります。それを回避するためにも、手順はある程度ルール化しています。

/**
* ボックスの選択を解除する
* @return void
*/
public function shutdown(): void
{
    $this->selected = null;
}

 

終了用のメソッド自体は単純で、selectedのプロパティに対してnullをセットするだけです。これで、起動・終了の基本的な処理が準備できました。

 

ボックスへのアクセス

次に、ボックスへのアクセス方法について見ていきましょう。まずはボックスを追加するためのメソッドです。

/**
* ボックスの追加
* @return integer
*/
protected function addBox(): int
{
    $this->pokebox[] = [];
    // 追加したボックス番号を返却
    return array_key_last($this->pokebox);
}

 

pokeboxのプロパティの最後に、新しい空の配列を追加しています。このとき、追加したボックスの番号をそのまま使用する可能性があるので、返り値ではpokeboxの最終キーを返却しています。

 

ボックスへのアクセスで最初に行われる処理は「ポケモンを預ける」です。なので、まずはボックスにポケモンを格納するためのメソッドを作成しましょう。

 

ポケボックスのポケモン管理用トレイト(/App/Traits/Class/Pokebox/ClassPokeboxPokemonTrait.php
<?php
trait ClassPokeboxPokemonTrait
{
    /**
    * ポケモンの追加
    * @param pokemon:object::Pokemon
    * @return boolean
    */
    public function addPokemon(object $pokemon): bool
    {
        // 引数の値を確認(ポケモンクラス、立場の確認)
        if(
            !is_a($pokemon, 'Pokemon') ||
            $pokemon->getPosition() !== 'friend'
        ){
            return false;
        }
        // ボックス番号の取得
        if(is_null($this->selected)){
            // 空きボックスの取得
            $free_box = array_fileter($this->pokebox, function($box){
                return count($box) < config('pokebox.max');
            });
            if(empty($free_box)){
                // ボックスに空きが無ければ新しくボックスを追加
                $box_number = $this->addBox();
            }else{
                // 空きボックスの先頭を取得
                $box_number = array_key_first($free_box);
            }
        }else{
            // 選択中のボックスに空きがあるかの確認
            if($this->pokebox[$this->selected] >= config('pokebox.max')){
                return false;
            }
            $box_number = $this->selected;
        }
        // 格納前に全回復させる
        $pokemon->recovery();
        // シリアライズして配列で格納(負荷軽減)
        $this->pokebox[$box_number][] = [
            'class' => get_class($pokemon),
            'name' => $pokemon->getNickname(),
            'level' => $pokemon->getLevel(),
            'object' => serializeObject($pokemon),
        ];
        // 格納完了
        return true;
    }
 
}

 

ポケモンを預ける際には比較的厳重なチェックを入れました。まずポケモンクラスであるかどうかの確認、ポケモンの立場の確認を行い、格納する値自体が正常なものかどうかを判断しています。

次に、ボックスの起動状態を確認して、起動状態であればその対象ボックスへの格納、そうでなければ最初の空きボックスを判定して格納します。

ボックスが起動状態でない場合の預け入れは、基本的に野生のポケモンを捕まえてパーティーへ追加できなかった際の処理です。ポケボックスへアクセスして預ける際には、現ソックとしてボックスを選択してからの預け入れとなります。

 

上記の条件がクリアできれば、ポケモンの体力を全回復させて、オブジェクトをシリアライズしてから配列として格納しました。アンシリアライズしなくても、一覧で最低情報が確認できるように、ポケモンクラス名、名前、レベルにはそれぞれキーを割り振って格納しています。

 

格納する形式が固まったので、次は預けたポケモンへアクセスするためのメソッドを用意しましょう。

/**
* 選択中のボックスへアクセス(復号化して返却)
* @return array
*/
public function accessBox(): array
{
    return array_map(function($pokemon){
        // オブジェクトを復号化して返却
        return unserializeObject($pokemon['object']);
    }, $this->pokebox[$this->selected] ?? []);
}

 

ポケモンの格納とは逆に、array_mapを使ってアンシリアライズ化して配列で返却しています。ボックスへのアクセスは、外部からの侵入を制限するためにもselectedプロパティのボックスに対してarray_mapをかけるようにしています。

 

以上で、ボックス操作に必要な基本的なメソッドが揃いました。

 

グローバルによる管理

ボックス自体、毎画面移管でアンシリアライズする必要がありません。ボックスクラスが必要なタイミングは、ボックス操作中またはポケモンを捕まえて手持ちがいっぱいの状態のみです。

なので、ボックスクラス自体のシリアライズ化はグローバル関数により必要な画面でのみ呼び出すようにしておきましょう。

<?php
$global_pokebox = $_SESSION['__pokebox'] ?? null;
// クラス読み込み
require_once($root_path.'/Classes/Pokebox.php');
 
/**
* ボックスの取得
* @return object::Pokebox
*/
function pokebox()
{
    global $global_pokebox;
    return $global_pokebox;
}
 
/**
* ボックスの初期化
* @return void
*/
function initPokebox()
{
    global $global_pokebox;
    $_SESSION['__pokebox'] = serializeObject(new Pokebox);
    $global_pokebox = $_SESSION['__pokebox'];
}
 
/**
* ボックスの起動
* @return void
*/
function startPokebox()
{
    global $global_pokebox;
    if($global_pokebox){
        // 復号化(オブジェクト状態でなければ)
        if(!is_object($global_pokebox)){
            $global_pokebox = unserializeObject($global_pokebox);
        }
    }else{
        // 初期化されていなければ新規作成
        $global_pokebox = new Pokebox;
    }
}
 
/**
* ボックスの終了
* @return void
*/
function shutdownPokebox()
{
    global $global_pokebox;
    // ボックスをシャットダウン状態にする
    if(is_object($global_pokebox)){
        $global_pokebox->shutdown();
    }else{
        $global_pokebox = unserializeObject($global_pokebox)->shutdown();
    }
    // 暗号化して格納
    $_SESSION['__pokebox'] = serializeObject($global_pokebox);
}
 
/**
* ボックスの保存
* @return void
*/
function savePokebox()
{
    global $global_pokebox;
    // 暗号化して格納
    $_SESSION['__pokebox'] = serializeObject($global_pokebox);
}

 

毎画面で行う処理は、セッション内のポケボックスをグローバル変数へ格納するだけです。ボックス操作が必要になる際はstartPokeboxでクラスそのものをアンシリアライズ、終了時にはクラスの状態をセッションに保存してからポケボックスのクラスをシリアライズします(shutdownPokebox)。

ポケモンの移管などを行えばボックス終了をせずに保存する必要があるので、保存単体の処理用の関数(savePokebox)も用意しています。

 

これで、ポケモン預かりシステムの根幹処理が揃いました。

 

まとめ

いかがだったでしょうか。

今回のPHPポケモンでは、ポケモン預かりシステムにおけるボックスの作成方法についてご紹介しました。

ポケモンに興味がある方、プログラミング学習に取り組んでいる方は、ぜひ参考にしてみてくださいね。

 

注目の記事

飲食店がホームページを作る5つのメリット 〜デメリットについても解説します〜
マーケティング
Google AdSense,SEO
飲食店がホームページを作る5つのメリット 〜デメリットについても解説します〜

  お店のホームページを作りたい   そういった飲食店の方は意外にも多く、イタリアンや居酒屋、日本料理店など種類も様々です。   今回のテーマは「飲食店がホームページを作る上で知っておきたいメリットとデメリットについて」です。   食べログやホットペッパーなどといったグルメサイトが主流とな...

トレーナー戦編 トレーナー情報の作成 PHPポケモン 97
プログラミング
PHP,PHPポケモン,ポケモン
トレーナー戦編 トレーナー情報の作成 PHPポケモン 97

トレーナー戦 いよいよPHPポケモンでもトレーナー戦の実装に取り掛かっていきます。バトルシステム自体は野生ポケモンと同じですが、トレーナーバトルでは以下の項目が追加、または制限を設けることになります。 複数匹のポケモン 逃げられない 捕まえられない 賞金   複数匹のポケモン ざっくり...

PHPポケモン「バトルシステム実装編〜補正値計算・乱数・急所〜」21
プログラミング
PHP,PHPポケモン,ポケモン
PHPポケモン「バトルシステム実装編〜補正値計算・乱数・急所〜」21

バトルシステムの実装  今回は「急所」と「乱数」と「タイプ一致」の判定と補正を実装していきます。 ちなみにですが、ポケモンwikiを熟読したところ、補正値の計算にも順番があり、計算後に小数点の切り捨てや五捨五超入をするなど、そこそこ複雑な計算順序がありましたが、今回はそこまで精密に再現せず、補正値(...

PHPポケモン「オートロード編(修正版)」17 おまけ:日本語化
プログラミング
PHP,PHPポケモン,ポケモン
PHPポケモン「オートロード編(修正版)」17 おまけ:日本語化

  前回実装したオートローダーの使い方が盛大に間違っていたので、今回その間違いの説明をしながら、正しい実装方法をご紹介します。 申し訳ありません。(誠意)    オートロードについて(再)  必要なタイミングで必要なファイルをrequireまたはincludeするあれです。   前回spl_autoload_reg...

独立してから心がけていること【社会人時代と比較して】
フリーランス
フリーランス,独立
独立してから心がけていること【社会人時代と比較して】

  今回は自分が独立してから心がけていることの中から、ある程度上手くいっていることや、オススメできるようなことを簡単に感想付きでまとめてみました。 社会人時代と比較しながらの内容なので、これからフリーランスで生きていこうと思っている人や、社会人という生活にストレスを感じている人は是非参考に...

スキル習得で挫折しないための3ステップ
雑記
デザイン,ブログ,プログラミング
スキル習得で挫折しないための3ステップ

  せっかく高い教材を買ったのに、気づいたら積んでしまっている・・・   そんな悩み、あなたには有りませんか? 今回は、そんな方のための勉強方法をテーマに説明していきます。 正しい勉強方法を身に着けていれば、どういったメリットがあるのでしょうか? 三日坊主になりにくい いざという...

ポケモンセンター編 PHPポケモン 37
プログラミング
PHP,PHPポケモン,ポケモン
ポケモンセンター編 PHPポケモン 37

ポケモンセンター  バトルシステムを作る関係上、どうしてもダメージを受けることが多くなってきたので、そろそろポケモンセンターを建設(作成)します。 とは言っても、ポケモンセンターに行って交換やらボックス整理などができるわけではなく、ただ回復ポイントを設置するだけの簡単な処理です。   HPの回復 ...

フリーランス必見!良質案件を獲得するための3つのプロセス
フリーランス
フリーランス必見!良質案件を獲得するための3つのプロセス

  「良い案件に巡り会えない」 「なかなか仕事が受注できない」   駆け出しフリーランスや、これから独立しようと考えている人が直面する大きな悩みの1つですね。 ですが、意外にも自分でその案件自体を制限していたり、良質だった案件を自らで質を下げてしまっているというケースは少なくありません。...

カテゴリ

SEO対策 イベント デザイン ネットワーク ビジネスモデル フリーランス プログラミング マーケティング ライティング 動画編集 雑記

タグ

5G Adobe AfterEffects AI ajax amazon Animate api artisan atom Automator AWS Bluetooth CSS CVR description EC-CUBE4 ECショップ ESLint Facebook feedly foreach function Google Google AdSense Honeycode htaccess HTML IEEE 802.11ax Illustrator Instagram IoT JavaScript jQuery jQuery UI keyword LAN Laravel Linux MacBook MAMP meta MLM MySQL NoCode note OS OSI参照モデル Paypal Photoshop PHP phpMyAdmin PHPポケモン PremierePro rss SEO SEO対策 Sequel Pro Skype SNS SSH Symfony TCP/IP title Toastr Trait Twig Twitter UCC V系 WAN WebSub Wi-Fi wiki Windows WordPress XAMPP xml Xserver YouTube YouTuber Zoom アーティスト アウトプット アクセス層 アニメーション アフィリエイト イーブイ インターネット インプット エンジニア オブジェクト指向 お金配り クリック単価 クリック数 コミュニケーション能力 コロナ コンサルティング サムネイル システムエンジニア スタートアップ スタイルシート スパム データベース ディープフェイク デザイナー デザイン テレワーク ナンパ ニュース ネットワークモデル ノマドワーク バナー ピカチュウ ビジネス フィード フリーランス ブロガー ブログ プログラマー プログラミング プログラミング学習 プログラミング教育 プロトコル ホームページ制作 ポケモン マークアップ マーケティング メール リモートワーク レンダリング 三井住友 三宮 仕事依頼 児童デイ 児童デイサービス 児童発達支援 公開鍵 初心者 助成金 勉強法 営業 広告 広告収入 必勝マニュアル 放課後等デイサービス 朝活 楽天 深層学習 無線LAN 独立 神戸 福祉 秘密鍵 翻訳 自己啓発 英語 見積書 計算機 読書 起業 迷惑メール 配列 銀の弾丸 集客 雑学力