プログラミング

ピカチュウから学ぶオブジェクト指向 〜レベルシステム導入編〜 3

PHP PHPポケモン オブジェクト指向 ポケモン
ピカチュウから学ぶオブジェクト指向 〜レベルシステム導入編〜 3

 

大人気?シリーズ「ピカチュウから学ぶオブジェクト指向」、今回はレベルシステムの導入編です。

 

第1回(基礎編)第2回(クラス継承編)で作成したPokemonPikachuのクラスを使用するので、最初から学習したい人はぜひご参考ください。

ピカチュウから学ぶオブジェクト指向 〜入門編〜 1 ピカチュウから学ぶオブジェクト指向 〜入門編〜 1

オブジェクト指向とは  オブジェクト指向プログラミング https://ja.wikipedia.org/wiki/オブジェクト指向プログラミング オブジェクト指向プログラミングとは、互いに密接な関連性を持つデータとメソッドをひとつにまとめてオブジェクトとし、それぞれ異なる性質と役割を持たせたオブジェクトの様々な定...

ピカチュウから学ぶオブジェクト指向 〜クラス継承編〜 2 ピカチュウから学ぶオブジェクト指向 〜クラス継承編〜 2

  ピカチュウから学ぶオブジェクト指向の第2弾はオブジェクトの継承についてです。 前回作成したピカチュウクラスを使用するので、もし基礎的な内容を学習したい人は、以下の記事を参考にしてください。 [shortcode_url_og url="https://s-yqual.com/blog/1035" title="" target="yqual_sub"]   オブジェク...

  

 

レベルシステムの導入

 

ポケモンのゲームと言えば、レベルシステムが楽しみの一つです。RPGゲームでは王道とも言えるレベルという概念は、育てることの楽しみや、強くなることで新しい技や変化が起こるという期待感を与えてくれます。

第3回では第1回、第2回で学んだオブジェクト指向の予習をしながら増設していきます。その上で、レベルという概念の初期準備をしていきましょう。

 

 

保守性を高める

 

第3回となれば、記述量も増えてきました。実際の開発でも役立つよう、本来のシステム開発により近い状態にすること意識して、以下の2点を意識しながら進めていきます。

ファイルの分割

コメントの追加

 

 

ファイルの分割

 

メソッドやプロパティが増えてくれば、それだけ記述量が多くなり、1ファイルの可視性は悪くなります。オブジェクト指向で使用するクラスは、基本的に1クラス1ファイル(クラス名.php)です。なので、今回作成したポケモンとピカチュウのクラスと実行ファイルを以下の階層で分割していきましょう。

/index.php(実行ファイル)
/Class/Pikachu.php(ピカチュウ※子)
/Class/Pokemon.php(ポケモン※親)

 

ファイルを分割すれば、それぞれで必要なファイルを読み込まなければなりません

まずは、ピカチュウクラスのファイル(/Class/Pikachu.php)の最上部に以下の記述を追加します。

require_once('/Class/Pokemon.php');

 

extendsでポケモンのクラスを継承しているため、Pokemon.phpを読み込まなければなりません。それに対してポケモンクラスは読み込まれている継承元のため、現在は特に別ファイルを読み込む必要がありません

 

次に、実行ファイル(/index.php)の最上部に以下の記述を追加します。

require_once('Class/Pikachu.php');

 

実行ファイルではピカチュウのインスタンス(実体)をするためにnew Pikachuと呼び出しています。そのため、実行ファイルではPikachu.phpを読み込まなければなりません。

 

 

コメントの追加

 

ファイル分けをすれば、次にコメントに記述を見直していきます。以下参考URLです。

 

コメントにも書き方があります。特にチーム開発をするのであれば、どういった記法をするのか共有して置かなければなりません

※今回のポケモンに関しては、参考URLの書き方を完全に遵守しているわけではありませんが、比較的同じようにわかりやすくまとめていきます

# ピカチュウクラス内
/**
* 正式名称
* @var string(min:1 max:5)
*/
protected $name = 'ピカチュウ';
 
# ポケモンクラス内
/**
* 正式名称を取得する
* @return string
*/
public function getName()
{
    return $this->name;
}

 

オブジェクト指向を使った開発の場合、多くのメソッドやプロパティを使用するため、それがどういった値を格納しており、引数や返り値などがひと目で分かるようにしておくことが保守性を高めることに繋がります。これはPHPに限らず他の言語についても同様です。

プログラミングに余裕が出てくれば、コメントの記法についても頭に入れておくことをオススメします。

 

 

初期レベルの実装

 

保守性について少し触れたところで、レベルシステムを実装するための開発を進めていきましょう。

ポケモンは捕まえた時(出現したとき)に初期レベルが設定されています。中には決まったレベルのポケモンもいますが、野生の場合は前後1〜2レベルぐらいのことが多いです。

そのためにも、まずは初期レベルの振れ幅をピカチュウのクラスへ追加しましょう。 

 

ピカチュウのクラス(/Class/Pikachu.php)
/**
* 初期レベル
* @var array
*/
protected $default_level = [
    7, 8, 9,
];

 

初期レベルはポケモンによって異なるため、親クラスではなくピカチュウクラスへ設定しています。今回は7〜9レベルの幅で出現させます。 

次に、レベルをセットするためのメソッドをポケモンクラスに追加します。

 

ポケモンのクラス(/Class/Pokemon.php)
/**
* 現在のレベル
* @return integer
*/
protected $level;

 

次に、ポケモンが出現または捕まえた時(インスタンス時)に初期レベルを決定したいので、コンストラクタ(__constract)内に初期レベルを設定するメソッドを記述し、メソッドは全ポケモン共通で使用できるためポケモンクラスに用意します。

 

ポケモンのクラス(/Class/Pokemon.php
<?php
// ポケモン
abstract class Pokemon
{

… 一部省略

    /**
    * レベルをセットする
    * @return void
    */
    protected function setLevel()
    {
        // 初期レベルからランダムで値を取得
        $key = array_rand($this->default_level);
        $this->level = $this->default_level[$key];
    }

}

 

ピカチュウのクラス(/Class/Pikachu.php
<?php
require_once('Class/Pokemon.php');

// ピカチュウ
class Pikachu extends Pokemon
{

… 一部省略
 
    /**
    * インスタンス作成時に実行される処理
    */
    public function __construct()
    {
        $this->setLevel();
        echo 'ピカチュウをゲットした';
    }
 
}

 

コンストラクタ内に記述していたニックネーム設定用のメソッドを削除しました。こちらは後ほど呼び出す形式で実装しましょう。

追加で、呼び出した際にそのことがわかるように、echoを使って「ピカチュウをゲットした」というメッセージを出力しています。

 

では、初期レベルをセットしているポケモンクラス内のsetLevelのメソッドの処理を確認してみましょう。

/**
* レベルをセットする
* @return void
*/
protected function setLevel()
{
    // 初期レベルからランダムで値を取得
    $key = array_rand($this->default_level);
    $this->level = $this->default_level[$key];
}

 

初期レベルを設定するメソッドは、外部から呼び出しをされては困りますので、アクセス修飾子はprotectedになります。

まずは、default_levelに格納されている数値(レベル)をランダムで取得するためにarray_randを使用します。 

 

array_randの返り値はランダムで取得した値が格納されているキーを返却してくれます。なので、$this->default_levelに対して取得したキーを指定して、レベル($this->level)に格納します。

$this->level = $this->default_level[$key];

 

では、index.phpを以下の用に記述して出力結果を確認してみましょう。

 

出力ファイル(/index.php
<?php

require_once('Class/Pikachu.php');
 
$pikachu1 = new Pikachu;
$pikachu2 = new Pikachu;
?>

<p>ピカチュウ1のレベル:<?=$pikachu1->getLevel()?></p>
<p>ピカチュウ2のレベル:<?=$pikachu2->getLevel()?></p>

 

出力結果は以下の通りです。

※一部改行して表示させています

# 出力結果
ピカチュウをゲットした
ピカチュウをゲットした
ピカチュウ1のレベル:8
ピカチュウ2のレベル:7

 

それぞれ初期レベルの範囲内で別の値が割り振られていますね。もちろん上記の設定では3通りしかないので、同じレベルのピカチュウがゲットできることもあります。

 

 

レベルに合わせた技の習得

 

レベルが高ければ、それに合わせて技を覚えている場合がありますね。初代(赤・青・緑)のピカチュウであれば、レベルが9になると「でんじは」という技を覚えます。なので、技リストに対して習得レベルを割り当てましょう。

 

ピカチュウのクラス(/Class/Pikachu.php
/**
* レベルアップで覚える技
* @var array
*/
protected $level_move = [
    [1, 'でんきショック'],
    [1, 'なきごえ'],
    [9, 'でんじは'],
    [16, 'でんこうせっか'],
    [26, 'スピードスター'],
    [33, 'こうそくいどう'],
    [43, 'かみなり'],
];

 

ピカチュウのクラスに対して、level_moveというプロパティを追加し、習得レベルと技名称を1行に格納しました。ここまでくればデータベースで管理するのが一般的ですが、今回は簡易のアプリケーションのため、現段階はPHPだけで実装していきます。

注意ポイントは、レベルはkeyとして割り振らず、名称と同様に値(value)として割り振っている点です。初期技や同レベルで習得できる技があると重複するというのが理由です。

 

次に、ピカチュウクラスに設定していたmoveプロパティ(技の一覧)の初期として技を入れる必要が無くなったので、空配列を初期値としてポケモンクラスへ移動しておきましょう。

 

ポケモンのクラス(/Class/Pokemon.php
/**
* 覚えている技
* @var array
*/
protected $move = [];

 

次に、初期技をセットするためのメソッドを作成しましょう。こちらも全ポケモン共通で使用できるのでポケモンのクラスへ追加します。

ポケモンのクラス(/Class/Pokemon.php)
/**
* 技を覚える
* @return string
*/
public function setMove($move)
{
    $this->move[] = $move;
    if(count($this->move) > 4){
        unset($this->move[0]);
    }
}
 
… 一部省略

/**
* 初期技をセットする
* @return void
*/
protected function setDefaultMove()
{
    foreach($this->level_move as list($level, $move)){
        if($level <= $this->level){
            // 現在レベル以下の技であれば習得
            $this->setMove($move);
        }else{
            // 現在レベルを超えていれば処理終了
            break;
        }
    }
}

  

まずは追加したsetDefaultMoveのメソッドから確認していきましょう。

foreach($this->level_move as list($level, $move)){

 

foreachを使用して、レベルで習得する技の一覧($this->level_move)を上から順に回していきます。asの後ろは$valのように値を取得せず、list関数を使用します。

 

foreachで回す際に取得できる値は、レベルと技名称が格納された配列です。それを添え番で取り出すよりも名称のついた変数として取り出せる方が都合が良いので、今回はlistを使用しています。配列の左から順にlist内で指定した変数へ格納されるので、1回目であれば$levelには「1」、$moveには「でんきショック」が格納されています。

 

次にif文を使った条件分岐を使い、格納する技を決めていきます。

if($level <= $this->level){
    // 現在レベル以下の技であれば習得
    $this->setMove($move);
}else{
    // 現在レベルを超えていれば処理終了
    break;
}

 

まず、技レベル($level)と現在のレベル($this->level)を比較します。もし技レベルが現在のレベル以下であれば習得可能なので、技を覚えるためのメソッドであるsetMoveを使用します。

もし、技レベルが現在のレベルより高ければ、その時点で処理を終了します。

※ピカチュウのクラスに設定されているlevel_moveプロパティがレベル順に上から並んでいることを想定しています

 

初期技はレベルと同様にインスタンスを作成した時点で覚えて置かなければなりませんので、ピカチュウクラスのコンストラクタに追記しましょう。

 

ピカチュウのクラス(/Class/Pikachu.php
/**
* インスタンス作成時に実行される処理
*/
public function __construct()
{
    $this->setLevel();
    $this->setDefaultMove();
    echo 'ピカチュウをゲットした';
}

 

ここのポイントは、メソッドを呼び出す順番です。setDefaultMove(初期技を設定するメソッド)では現在のレベルを使用しています。なので、まずはsetLevel(レベルを設定するメソッド)を記述しておく必要があります。逆になってしまうと技が覚えられなくなってしまうので注意しましょう。

 

それでは、出力ファイル(index.php)に以下を記述して結果を確認してみましょう。

 

出力ファイル(/index.php

※一部改行して表示しています

# 出力結果
ピカチュウをゲットした
ピカチュウをゲットした
 
ピカチュウ1のレベル:9
ピカチュウ1の技
array (
  0 => 'でんきショック',
  1 => 'なきごえ',
  2 => 'でんじは',
)
 
ピカチュウ2のレベル:8
ピカチュウ2の技
array (
  0 => 'でんきショック',
  1 => 'なきごえ',
)

 

レベル9のピカチュウは「でんじは」を覚えており、レベル8のピカチュウは覚えていませんね。これで技に対するレベルの割り振りが完了しました。

 

以下最終コードです。

※第1回、第2回で作成したコードを一部修正しています

 

ポケモンのクラス(/Class/Pokemon.php
<?php
// ポケモン
abstract class Pokemon
{
 
    /**
    * ニックネーム
    * @return string(min:1 max:5)
    */
    protected $nickname;
 
    /**
    * 現在のレベル
    * @var integer
    */
    protected $level;
 
    /**
    * 覚えている技
    * @var array
    */
    protected $move = [];
 
    /**
    * ニックネームを付ける
    * @return string
    */
    public function setNickname($nickname)
    {
        if(empty($nickname) || mb_strlen($nickname, 'UTF-8') > 5){
            echo 'ニックネームは1〜5文字で入力してください';
            return;
        }
        $this->nickname = $nickname;
    }
 
    /**
    * 正式名称を取得する
    * @return string
    */
    public function getName()
    {
        return $this->name;
    }
 
    /**
    * ニックネームを取得する
    * @return string
    */
    public function getNickname()
    {
        if(empty($this->nickname)){
            return $this->name;
        }
        return $this->nickname;
    }
 
    /**
    * 覚えている技の一覧を取得する
    * @return array
    */
    public function getMove()
    {
        return $this->move;
    }
 
    /**
    * 現在のレベルを取得する
    * @return integer
    */
    public function getLevel()
    {
        return $this->level;
    }
 
    /**
    * 技を覚える
    * @return string
    */
    public function setMove($move)
    {
        $this->move[] = $move;
        if(count($this->move) > 4){
            unset($this->move[0]);
        }
    }
 
    /**
    * レベルをセットする
    * @return void
    */
    protected function setLevel()
    {
        // 初期レベルからランダムで値を取得
        $key = array_rand($this->default_level);
        $this->level = $this->default_level[$key];
    }
 
    /**
    * 初期技をセットする
    * @return void
    */
    protected function setDefaultMove()
    {
        foreach($this->level_move as list($level, $move)){
            if($level <= $this->level){
                // 現在レベル以下の技であれば習得
                $this->setMove($move);
            }else{
                // 現在レベルを超えていれば処理終了
                break;
            }
        }
    }
 
}

 

ピカチュウのクラス(/Class/Pikachu.php
<?php

require_once('Class/Pokemon.php');

// ピカチュウ
class Pikachu extends Pokemon
{
 
    /**
    * 正式名称
    * @var string(min:1 max:5)
    */
    protected $name = 'ピカチュウ';
 
    /**
    * 初期レベル
    * @var array
    */
    protected $default_level = [
        7, 8, 9,
    ];
   
    /**
    * レベルアップで覚える技
    * @var array
    */
    protected $level_move = [
        [1, 'でんきショック'],
        [1, 'なきごえ'],
        [9, 'でんじは'],
        [16, 'でんこうせっか'],
        [26, 'スピードスター'],
        [33, 'こうそくいどう'],
        [43, 'かみなり'],
    ];
 
    /**
    * インスタンス作成時に実行される処理
    */
    public function __construct()
    {
        $this->setLevel();
        $this->setDefaultMove();
        echo 'ピカチュウをゲットした';
    }
 
}

 

 

まとめ

 

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

今回は「ピカチュウから学ぶオブジェクト指向 〜レベルシステムの導入〜」をご紹介しました。

クラスやメソッド、プロパティの使い方や呼び出し方は、何度も回数をこなせば自然と理解が深まっていきます。興味を持ってくれた人は、ぜひポケモンのゲームにある機能を増設してみたり、他のゲームを参考に練習していくと良いでしょう。

※販売には著作権等の問題を考慮しながら適切な判断をしてください

 

これからPHPを学習しようと考えている方は、ぜひ参考にしてみてくださいね。

 

第4回はコチラ(トレイト編 + 経験値システムの導入)

ピカチュウから学ぶオブジェクト指向 〜トレイト編〜 4 ピカチュウから学ぶオブジェクト指向 〜トレイト編〜 4

  ピカチュウから学ぶオブジェクト指向の第4弾は「トレイト(trait)の活用」についてです。更に、レベルシステムを導入すれば欠かせない経験値システムも合わせて実装します。 第3回からの続きとなりますので、もし前回をまだ見ていない人は是非ご参考ください。 [shortcode_url_og url="https://s-yqual.c...

 

注目の記事

システムエンジニア向けまとめ情報サイト IT News Checker
ネットワーク
システムエンジニア向けまとめ情報サイト IT News Checker

新年のスタートダッシュが遅れ気味に見えるかも知れませんが、年末からじっくりと作業を進めており、やっとある程度形になりました。 師走の如く作業に走り、気分転換に雪遊びもしつつ、成人式を終えた辺りでリリースしたのが「IT News Checker」です。   IT News Checkerとは 簡潔に説明すると、まと...

PHPポケモン「バトルシステム編〜状態異常2〜」31
プログラミング
PHP,PHPポケモン,ポケモン
PHPポケモン「バトルシステム編〜状態異常2〜」31

  前回に引き続き、状態異常チェックを実装します。 まず、前回実装した「ねむり」の処理についてですが、やはりターン数をセットして経過ターン数を引いていくという処理の方が解除率もゲーム再現になるので、まず修正をしておきます。サーセン。   チェック格納トレイト(/Traits/Battle/CheckTrait.php) ...

なぜ、お金を配るの?悪質メール・SNSを利用した詐欺的手法への対処法とは
ネットワーク
amazon,SNS,Twitter,お金配り,楽天,迷惑メール
なぜ、お金を配るの?悪質メール・SNSを利用した詐欺的手法への対処法とは

定期的に書きたくなるコラムのコーナー! 今回は、迷惑メールやSNSのDMを活用した悪質な勧誘、巷で流行っているお金配りを隠れ蓑のした巧妙な詐欺的手法などをいくつかご紹介、その対策・リクス回避の方法をまとめました。   まず結論からお伝えすると 「怪しいと思うなら手を出すな」 です。その詳細を知りたい...

AIが人類にもたらす驚異!深層学習が与える影響とは
ネットワーク
AI,ディープフェイク,深層学習
AIが人類にもたらす驚異!深層学習が与える影響とは

  海外の記事でAIについて記述した興味深いものが掲載されました。   今回は「AIが人類にもたらす驚異!深層学習が与える影響とは」について、上記サイトを参考にまとめましたのでご紹介します。 ※直訳ではありません、あくまで記事の内容を参考にして自らの考えを記述したものです     AIの驚異と...

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

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

フリーランスの仕事の取り方教えます!この3つを押さえておけばOKです【企業も応用可】
フリーランス
フリーランス,独立,起業
フリーランスの仕事の取り方教えます!この3つを押さえておけばOKです【企業も応用可】

  仕事ってどうやってとればいいの?   独立したい、起業したいと考えている人の多くが、仕事はどうやってとればいいのかと悩んで足踏みしています。 実は、基本的な3つのポイントさえ知っていれば、継続して仕事を受注することは簡単です。 今回は自分が実際にやっていることを例に「フリーランスなら...

売れるECサイトになるために必要な3つの戦略
マーケティング
ECショップ,コンサルティング
売れるECサイトになるために必要な3つの戦略

  ECサイトで全く売れない・・・   ネットショップのオープンが手軽で安価になり、クレジット決済も主流の今ECサイトを立ち上げるお店も増えてきました。 しかし期待感とは裏腹に、思ったような売上が出なかったり、お客さんが1人も獲得できていないケースも少なくありません。   今回はそういった「...

そらをとぶ&あなをほる編 PHPポケモン46
プログラミング
PHP,PHPポケモン,ポケモン
そらをとぶ&あなをほる編 PHPポケモン46

チャージ中の回避技 以前は「ロケットずつき」や「ソーラービーム」をサンプルとしてチャージ技を実装しましたが、今回は少し特別な効果をもったチャージ技を実装します。それが「そらをとぶ」と「あなをほる」です。これらは初代ポケモンでも重宝される技であり、チャージ中に相手からの攻撃を回避することができま...

カテゴリ

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 独立 神戸 福祉 秘密鍵 翻訳 自己啓発 英語 見積書 計算機 読書 起業 迷惑メール 配列 銀の弾丸 集客 雑学力