プログラミング

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

 

注目の記事

成功に近い3つの思考「楽して稼ぐ」「知識オタク」「資産形成は無駄」
雑記
成功に近い3つの思考「楽して稼ぐ」「知識オタク」「資産形成は無駄」

  「楽して稼ぎたい」   人間誰しも、そう考えているはずです。これは正しく、成功するためには必要な思考です。 それを「楽に稼ぐ方法なんてない」と無理やり押さえつけてしまう人は、完全に本質が見えておらず、その大半に「楽して稼げない自分を認められてない」というマイナス因子が含まれてい...

プログラミングでフリーランスを目指す人にPHP学習をオススメする3つの理由
プログラミング
Laravel,PHP,SEO,WordPress
プログラミングでフリーランスを目指す人にPHP学習をオススメする3つの理由

  「フリーランスになるためにプログラミングを身に着けたい」 「セカンドキャリアで技術を習得したい」 「副業でパソコン1台で稼げるものに挑戦したい」   終身雇用が危ぶまれている現在、スキルを身に着けて転職やフリーランスとして活躍したいと考える人が増え、プログラミングの需要は年々高まってきて...

npm run watch-poll中にPCがフリーズした時の解決法
プログラミング
CSS,JavaScript,Laravel,Linux
npm run watch-poll中にPCがフリーズした時の解決法

  Laravelで開発中にPCが頻繁にフリーズするという問題にぶち辺り、原因がnpm run watch-pollだということが解ったので、その解決方法をまとめておきます。 複雑な原因でもなく大きな問題にもならなかったのですが、これが原因でデータ破損となれば困るので、同じような問題に直面した開発者向けです。    ...

SEOで強いURLとは?安易に決めると危険だった!「よく分かるSEO対策」パーマリンク編
SEO対策
WordPress,ブログ
SEOで強いURLとは?安易に決めると危険だった!「よく分かるSEO対策」パーマリンク編

  パーマリンクの設定ってSEO対策に関係あるの?   意外と気になっているポイントではないでしょうか。実は、URLとSEO対策には全くの無関係ではなく、安易に決めてしまうとせっかく積み上げた資産的価値を台無しにしてしまうかも知れない危険なポイントでもあるのです。   今回は、ブログの収益化を目指...

パーティーの並び替え編 PHPポケモン 82
プログラミング
PHP,PHPポケモン,ポケモン
パーティーの並び替え編 PHPポケモン 82

パーティーの並び替え ポケモンをバトルに選出する際に欠かせないのが「パーティーの並び替え」です。パーティーの先頭(ひんし状態でない)がポケモンでは自動的に選択されるため、戦闘前に並び替えをしておく必要があります。 ゲーム上では簡単に見える処理ですが、これがPHPで行うとなれば少し厄介な問題が出てき...

PHPポケモン「UI(Bootstrap4の導入)編」コード配布・デモ有り 13
プログラミング
PHP,PHPポケモン,ポケモン
PHPポケモン「UI(Bootstrap4の導入)編」コード配布・デモ有り 13

  第13回のPHPポケモンは「UI編」ということで、CSSの大人気フレームワークBootstrapさんにお手伝いいただきます。 また、前回実装したレスポンス機能により進化のアクションに一部不具合が出ていたので、このあたりも合わせて修正をしながら進めていきましょう。   Bootstrapを導入するにあたり、今までin...

フリーランスの最大の敵は休日!?正しい休息の取り方教えます
フリーランス
フリーランス,独立
フリーランスの最大の敵は休日!?正しい休息の取り方教えます

  フリーランスになりたての人は、仕事のペースがわからなかったり、無理に自分へ追い込みをかけて頑張ろうとしてしまうことがあります。 毎日を仕事でいることが、フリーランスにとっての心がけや意識のあり方としては大切ですが、それをそのままの意味で実行してしまうと明らかなオーバーペースになるのは事...

コンテンツ配信業でバズるために大切な3つの法則〜『1ヶ月でチャンネル登録者数1000人』は参考にするな
マーケティング
YouTube,YouTuber,ブログ
コンテンツ配信業でバズるために大切な3つの法則〜『1ヶ月でチャンネル登録者数1000人』は参考にするな

  YouTubeやブログを始めたけど思ったように伸びない・・・   こういった人は、チャンネル登録者数を伸ばす方法などの動画を見ても参考にならなく、結果に繋がらないという場合がほとんどです。 その理由は、その人自身に問題があるわけではなく、動画の前提条件がそもそも違っているからです。   今回は「...

カテゴリ

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