プログラミング

ピカチュウから学ぶオブジェクト指向 〜レベルシステム導入編〜 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...

 

注目の記事

手っ取り早く情報強者になる簡単な方法
雑記
アウトプット,インプット,ニュース
手っ取り早く情報強者になる簡単な方法

  ニュースや情報番組、討論番組をみると、出演者の方々の情報量の多さに圧倒されることがあります。 また、ユニークな考え方に共感を得る人も多いでしょう。   どうやって、情報を仕入れているのか? なぜそんなことまで知っているのか?   メディアで取り上げられているような人や、活躍している人の多く...

迷惑メールはなぜ届く?amazonや楽天を騙る悪質メールへの対処法とは
ネットワーク
amazon,スパム,メール,楽天
迷惑メールはなぜ届く?amazonや楽天を騙る悪質メールへの対処法とは

「いきなり迷惑メールが届くようになった」 「Amazonや楽天を装ったメールはどうやって見分ければいいの?」   知らない人からいきなり連絡が届いたり、登録もしていないようなサービスからメールが届けば、それは詐欺メールかも知れません。 スマホやパソコンが一般的に普及して、ネットでの買い物やサービスを利用...

ノーコード開発で将来プログラミングは不要?我々は何を学ぶべきなのか
プログラミング
amazon,AWS,Honeycode,NoCode,プログラミング学習
ノーコード開発で将来プログラミングは不要?我々は何を学ぶべきなのか

  近年、プログラミングの需要は増え勢いを増していますが、それ以上にノーコードというソースコードを打たなくでもアプリ開発ができるというソフトウェアやプラットフォームが普及してきました。 これにより一部の期待感とは別に、プログラマーという職業は今後不要になるのではないかと危機感を抱く人が出て...

簡単に良質なブログ記事を量産する3箇条【ネタがないとは言わせない】
ライティング
ブロガー,ブログ
簡単に良質なブログ記事を量産する3箇条【ネタがないとは言わせない】

  ブログの毎日のテーマ決めが大変・・・ そもそも良質な記事をどうやって書けるようになるのかわからない   こんな悩みを抱えていませんか? 始めたばかりで伸び悩んでいる人には多いのではないでしょうか。 今回はブログで収益化や、アクセス数を伸ばそうと考えている人へ向けて「簡単に良質なブログ...

トレーナー戦編 バトルシステムへの追加 PHPポケモン 98
プログラミング
PHP,PHPポケモン,ポケモン
トレーナー戦編 バトルシステムへの追加 PHPポケモン 98

トレーナー戦闘の追加 前回トレーナー情報を作成したので、今回はその情報をバトルシステムへ組み込んでいきます。 現在、野生ポケモンとの戦闘では「battle」という値actionの値で受け取っています。同じサービス内で分岐を作ると複雑になってしまうので、battle_trainerという新しい分岐を使ってサービス分けをし...

オブジェクト指向有効活用編 PHPポケモン 93
プログラミング
PHP,PHPポケモン,ポケモン
オブジェクト指向有効活用編 PHPポケモン 93

オブジェクト指向の有効活用 β版に向けたPHPポケモンの構成見直し、今回は「オブジェクト指向」の役割について、より理解を深めつつ、保守性も良くなるように整えていきます。   機能を持たせる 様々なプロパティを定数や静的変数へ以降していますが、今回は「静的メソッド」の活用範囲を増やしていきます。まず...

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

状態異常チェック 今回は少し先延ばししていた状態異常判定を一部作成していきましょう。 状態異常では「行動前」と「行動後」に判定するものに分けることができます。 行動前 まひ、ねむり、こおり  行動後 どく、もうどく、やけど   まずは簡単な行動前から実装していきます。行動前に判...

進化の石編(構成) PHPポケモン 102
プログラミング
PHP,PHPポケモン,ポケモン
進化の石編(構成) PHPポケモン 102

進化の石 ピカチュウさんもそろそろ進化したがっているので、β版の公開に向けて進化の石を実装していきます。しかし、イーブイなど特別な進化先や条件を持ったポケモンを考慮すると、少し実装が手間取りそうだったので、今回は構成部分のみのまとめとなっておりますので、ご了承ください。   アイテムクラスの作...

カテゴリ

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