プログラミング入門者のためにこれをやれば初級者になれる課題5選(開発環境の構築から)
本日はプログラミングができない!けどやりたい!という友人のためにこれをやればそこそこ出来るようになるという課題を5選用意しました。
その前に入門者がつまづく開発環境について説明します。
前回のブログVagrantとchefで簡単お手軽ローカル環境構築 - nigoblogにローカル環境開発環境のことを書いたんだけど、
あれは中級者以上向けの話。最初はMAMP or XAMPPからやっとくべき。
というわけで次の流れで説明します。
- ローカル環境の構築 ~MAMP編~
- ローカル環境の使い方
- 課題が終わって出来ること
- 1. フォームの作成 HTML
- 2. フォームの値を取得 PHP
- 3. フォームの値をDBにセット PHP+MySQL
- 4. DBの値を取得 PHP+MySQL
- 5. viewとcontrollerの分割 MVC
以上の流れで書いていきます。
ローカル環境の構築 ~MAMP編~
ローカル環境という言い方をしているけど、ざっくりいうと自分のPCでPHP+MySQLを使ったアプリケーションを作れる環境のこと。
大抵の初心者はここで挫折。スタートラインにも立てずに挫折する人が多い。
MAMPとは
M : Mac
A : Apache
M : MySQL
P : PHP
の略称で、それらを自分のMacにインストールし、さらには面倒臭い設定も全部やったるという粋なアプリケーション。
ちなみにwindowsの場合はXAMPP、linuxの場合はLAMPなどがあります。
とりあえずこちらMAMP: Mac, Apache, MySQL, PHPからダウンロード。
フリーの方でも構いません。
ダウンロードしたらインストーラーを起動。
従っていけばインストールされ、ブラウザで次の画面が表示されます。
※画像は画面の一部を切り取ったものです。
もし表示されなければ検索バーに
http://localhost:8888/MAMP/?language=Japanese
と打ち込みます。
それでもダメならサーバーが起動していない可能性があります。
LaunchpadなどからMAMPを起動します。
すると次のようなウィンドウが表示されます。
ここで左のランプがどちらも緑になっていればOK。
なっていなければ、「サーバーを起動」ボタンを押します。
それで「スタートページを開く」を押せば、ブラウザに「MAMPへようこそ」と表示されます。
これで開発環境は完了。
すごく簡単。
ただし、インストールにかなり時間がかかるので途中で心が折れないように。
ローカル環境の使い方
Macの場合であればFinderもしくはターミナルから色々操作します。
Finderの場合
アプリケーション > MAMP > htdocs
の中にディレクトリを作成します。
アプリケーション > MAMP > htdocs > 作成したプロジェクト名
に「index.html」というファイルを作成し、
<h1>Hello World</h1>
と入力します。
ターミナルの場合
cd ../../Applications/MAMP/htdocs
と入力し,
mkdir プロジェクト名
でプロジェクトを作成
vim index.html
でファイルを作成
<h1>Hello World</h1>
とでも入力し、保存。
Finderの場合もターミナルの場合も
結果、あるプロジェクトに「Hello World」と表示させるファイルを作成しました。
次にブラウザの検索バーに
「localhost:8888」
と入力します。
すると先ほど作成したプロジェクト名のリンクがあり、
クリックすると「Hello World」と表示されます。
簡単にまとめると
- MAMP内のhtdocsにプロジェクトを置く
- localhost:8888でアクセス
という感じです。
これでスタートラインに立った状態。
というわけで次から課題へ!!
課題が終わって出来ること
今回提示する課題が終わればひと通りwebアプリケーションを作る基礎が出来ます。
はっきりいうとプログラミングであるPHPの役割は2つしかありません。
- DBから値を取得
- DBの値を書き換える
複雑そうに見えても結局やることはこの2つ。
そのブラックボックスを今回の課題を解くことによって知ることが出来ます。
早速スタート!!
1. フォームの作成 HTML
最初の課題はHTMLでフォームを作成すること。
結果として次の画像の感じになればOK
ちなみに課題に関しては懇切丁寧に教えるつもりはありません。
勝手にググって解決してください。
ただし、一つ言えるのはこの課題が終われば完璧にwebアプリケーションを理解できるってこと!
3. フォームの値をDBにセット PHP+MySQL
次は実際に取得した値をDBにセットするまで。
初めてDBを使うので、phpMyAdminと呼ばれるMySQLを激使いやすくするツールをつかいます。
MAMPに最初っから入っています。
スタートページのグローバルメニューのphpMyAdminをクリック
phpmyadminの画面になったらまずはデータベースを作成。
適当に名前は付けて良いですが、右のプルダウンは「utf8_general_ci」を選択したください。意味は知らなくて良いです。
次はテーブルの作成
ここも名前は適当で良いですが、
フィールド数は3とします。
そこでフィールド名をそれぞれ
- id
- name
- address
とします。
種別はそれぞれ
- int
- varchar
- text
とし、nameのみ長さを20に設定します。
またidのみ
インデックスをprimary、A_Iにチェックを付けます。
これでDBのセッテイングは完了!
あとは課題であるようにフォームからの値をDBに挿入するだけ。
最終的にフォームに入力し、phpMyAdminで見た時、
となればOK!
5. viewとcontrollerの分割 MVC
これまでは表示させるファイルと処理をするファイルを共通のものにしました。
次は表示させるファイルと処理をするファイルを別々のものにします。
具体的にはフォルダ内が次のようになればOK!
test/ index.php controller.php
理由としてはデザイナーがわかりやすくなるため。
だったり、あとすっきりします。
以上、こんな感じの課題をこなしていけば、そこそこプログラミングが出来るようになっていくと思います!!
それから懇切丁寧に書かなかったのは、調べる能力も一つのプログラミング能力
やりたいことがはっきりしている場合は調べることもそんな難しいもんじゃないので。
というわけで頑張ってやってみてください!!
PHPとAjaxで擬似的にリアルタイム通信を実現する。
先日QiitaQiita [キータ] - プログラマの技術情報共有サービスが主催するハッカソンに参加して参りました。
結果はなんと優勝しちゃいました!!
テーマは「マルチスクリーンで動作するアプリケーション」というわけで、
一つの画面を複数のデバイスで操作するという感じのアプリケーションを作成しました。
その時に端末のデバイスでのイベントをリアルタイムでメインの画面に反映させるということをPHPとAjaxで行いました。
アイディア
具体的にどんなものかというと、一つのメイン画面にバーが2つあり、端末を振るとそのバーが変化します。
2台以上の端末を使って、バーを二手に分け、どちらがより振ったかを競うようなアプリケーションです。
端末側はチームメンバーで私はメインの方を担当しました。
PHP, Ajax実現アルゴリズム
擬似的にリアルタイム通信を実現する流れは次のようになります。
以上の流れで擬似的にリアルタイムが実現できます。
擬似的なのはテーブルが更新されたのをキッカケにメイン側でアクションが起きるわけではないからです。
もっと本格的なリアルタイムを実現したい場合はwebsocketを使う必要があります。
端末側
まず端末がわではテーブルを更新するAPIを叩きます。
今回の場合「振った」というイベントでAPIを叩きます。
そのAPIのコードが以下になります。
public function api(){ header("Content-Type: application/json; charset=utf-8"); $data['point'] = $_GET['point']; $data['team'] = $_GET['team']; $this->load->model('supporter_model', 'supporter'); $this->supporter->insertPoint($data['point'], $data['team']); $json = json_encode($data); print_r($json); }
JSONでのリターンがあるのは正常に通信が行われているかどうかを確認するためです。
モデルは省略しますが、
$this->supporter->insertPoint($data['point'], $data['team']);
の部分でテーブルを更新しています。
ちなみに今回codeigniterを利用しております。
メイン側
テーブルのデータを取得し、JSONで返します。
public function apiPointGet(){ header("Content-Type: application/json; charset=utf-8"); $this->load->model('supporter_model', 'supporter'); $data['pointSumA'] = $this->supporter->selectPoint('A'); $data['pointSumB'] = $this->supporter->selectPoint('B'); $result_array = array( 'teamA' => $data['pointSumA']['SUM(point)'], 'teamB' => $data['pointSumB']['SUM(point)'] ); $result = json_encode($result_array); print_r($result); }
同様に説明を省きますが、下記でデータを取得します。
$data['pointSumA'] = $this->supporter->selectPoint('A'); $data['pointSumB'] = $this->supporter->selectPoint('B');
このAPIを随時叩くことにより擬似的にリアルタイムを実現します。
取得した結果を一定間隔でDOM操作する
ここが今回のメインとなります。JS部分だけを説明します。
function graph(){ function reload(){ $.getJSON( './supporters/apiPointGet', // アクセス先のURL function(data, status) { teamTotal = Number(data.teamA) + Number(data.teamB); teamA = (Number(data.teamA) * 100) / Number(teamTotal); teamB = (Number(data.teamB) * 100) / Number(teamTotal); $('#teamA').css('width', teamA + '%'); $('#teamB').css('width', teamB + '%'); console.log(teamA); console.log(teamB); } ); } var teamA = 0; var teamB = 0; timer = setInterval(reload, 100); }
簡単ですが以上になります。
reload()という関数をsetIntervalで100ミリ秒感覚で実行します。
reload()内は上記で説明したテーブルの内容を取得し、JSONをパースしcss操作をする処理となります。
以上、簡単ですが、PHPとAjaxで擬似的にリアルタイムを実現する方法でした。
ただしあくまで擬似的なので今後node.jsなので本格リアルタイム通信を実現させたいと思います!!
PHPのGDライブラリを使ってヒストグラムを描画する~ルービックキューブの色を解析~
前回PHPのGDライブラリを使って画像の色を取り出す~ルービックキューブの画像処理~ - nigoblogに引き続きGDライブラリを用いた画像処理プログラムを公開します。
前回
「画像処理をするには下処理が重要」
ということを書きました。
例えばこの画像のこの部分は○色だ!というような処理をしたい時、予めその処理をしやすいような処理をするということです。
こんな感じで説明します。
ヒストグラムとは
ヒストグラム(histogram)はざっくりいうと棒グラフのことです。ざっくりいうとってかそのままの気がするけど。。。
棒グラフをかっこ良くいう感じですね。
web系の人間ならABC分析やABテストで用いられるかと思います。
どういう時に用いられるかというと、「ある状態やもの」の「数や売上」などがどれだけあるかということを相対的に知りたい時に用いられます。
今回の場合
ある状態 = RGBそれぞれの階調(16段階)
となり
RGBそれぞれの階調がどれだけあるかということを相対的に知りたい。
ということを叶えるヒストグラムを得ます。
RGBごとにヒストグラムを作成
RGBそれぞれ16段階あるとし、それぞれがどれだけあるかを画素ごとにカウントしていきます。
前回PHPのGDライブラリを使って画像の色を取り出す~ルービックキューブの画像処理~ - nigoblog同様、左上からスキャンしていきます。
実装
それでは実際に実装したものが以下となります。前回のコードの下に入るような感じです。
// 1 $histogramR = array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); $histogramG = array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); $histogramB = array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); // 2 for($y = 0; $y < $imagey;$y++){ for($x = 0; $x < $imagex; $x++){ $rgb = imagecolorat($img, $x, $y); $r = ($rgb >> 16) & 0xFF; $g = ($rgb >> 8) & 0xFF; $b = $rgb & 0xFF; $histogramR[(int)($r/16)]++; $histogramG[(int)($g/16)]++; $histogramB[(int)($b/16)]++; } } // 3 function writeHistogram($value, $char){ for($i=0;$i<$value;$i++){ echo $char; } } // 4 echo 'Red <br>'; foreach($histogramR as $countR){ writeHistogram($countR/100, 'r'); echo '<br>'; } echo 'Green <br>'; foreach($histogramG as $countG){ writeHistogram($countG/100, 'g'); echo '<br>'; } echo 'Blue <br>'; foreach($histogramB as $countB){ writeHistogram($countB/100, 'b'); echo '<br>'; }
まず1はヒストグラムのデータの初期値を設定します。
2で画像をスキャンし、画素ごとにRGBの値を取り出します。それを16で割ることで階調を16段階にします。もう少し細かく分けたければ10で割ると26段階、8で割ると32段階とどんどん階調を増やすことができます。
3の関数はヒストグラムを描画する関数で、4で実際に描画します。数を100で割っているのは数が大きすぎたためです。
結果
それでは上記の結果を示します。まず、用いた画像は次の画像です。
それのヒストグラムを作成した結果次のようになりました。上から順に0 ~ 15までの16段階のヒストグラムです。
Red 0~15 rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr 16~31 rrrrrrrrrrrrrrrrrrrrrr 32~47 rrrrrr 48~63 rrrr 64~79 rrr 80~95 rrr 96~111 rrr 112~127 rr 128~143 rrrrr 144~159 rrrrrrr 160~175 rrrrrrrrrrrr 176~191 rrrrrrrrrrrrrrr 192~207 rrrrrrrrrrrrrr 208~223 rrrrrrrrrrrrrrrrr 224~239 rrrrrrrrrrrrrr 240~255 rrrr
軸がないのがわかりにくいので後で付け足しました。このヒストグラムからわかることは全体的に暗いということ。また144~239の間にも分布していることが一目でわかります。
まとめ
結果からわかることは、47以下の階調の場合、階調に比例した数をかけることでうまく処理ができるかと考えられます。
下処理をどうするかはまだわかりませんが、とりあえず今回は下処理をするための下処理ということでした。
それ以外にもヒストグラムの考え方がなんとなくわかったかと思います。
それではルービックキューブアプリ乞うご期待!!
PHPのGDライブラリを使って画像の色を取り出す~ルービックキューブの画像処理~
PHPにはすごく便利なライブラリにGDライブラリというものがあります。
用途は主に画像関連の処理!!
というわけでGDライブラリを用いて画像の色を取り出し、解析を行なっていきます!!
- そもそも
- GDライブラリ
- 使う関数とその説明
- 実装
このような流れで説明していきます。
そもそも
なんでこれをやろうと思ったかを少し。
このブログで前回ルービックキューブの実装をPHPでしてみた~ルービックキューブクラス~ - nigoblogルービックキューブについてブログを書きました。
それで思いついたアプリケーションが
「ルービックの写真から解法を導くアプリケーション」
を作ろうと思ったわけです。
そのアプリケーションの流れはこんな感じ
- バラバラのルービックキューブの写真を取る(3面)
- その画像を解析し、ルービックキューブがどのような状態かを判断
- 解くまでの手順を表示
- 使った人は簡単にルービックキューブを完成!
みたいな感じの。
それで手順2の画像を解析しルービックキューブがどのような状態かを判断するために今回のテーマをやりました。
GDライブラリ
とはざっくりいうと「PHPで画像を処理するためのライブラリ」です。
ここに色々マニュアルがのっています。PHP: GD - Manual
使う関数とその説明
GDライブラリには色々な関数があるのですが、今回は次の5種類の関数をつかいます。
imagecreatefrompng(filename);
これは説明では「新しい画像をファイルあるいはURLから作成する」
とあります。
正直これはいまいち掴みどころがわからないのですが、ここで作成した画像を今後使います。実際には
$img = imagecreatefrompng(filename);
のように作成した画像を変数に代入します。
imagesx($img); imagesy($img);
この2つは画像の幅x 、高さy を取得します。
imagecolorat($img, width, height);
これは画像 $img の width, height の時のRGBの値を取得します。ただし16進数で連続で値を返すため、わかりやすくするために次の関数をつかいます。
$rgb = imagecolorat($img, width, height); $colors = imagecolorsforindex($img, $rgb); print_r($colors);
こうすると次のように出力されます。(値は適当)
array( [red] => 100, [green] => 100, [blue] => 100 )
というわけで各ピクセルのRGBの値を取り出すことができました。
実装
それで今回、画像を入力して画像の画素で赤の時は 「 r 」 , 白の時は 「 w 」 , 緑の時は 「 g 」 , その他の時は 「 @ 」
を表示するプログラムを書きました。
用いた画像はこちらです
早速コードはこちら
define('CUBE', '20121009234619.png'); // 1 $img = imagecreatefrompng(CUBE); $imagex = imagesx($img); $imagey = imagesy($img); // 2 $red = array(150, 110, 110); $green = array(110, 110, 110); $white = array(110, 110, 110); // 3 for($y = 0; $y < $imagey;$y++){ for($x = 0; $x < $imagex; $x++){ $rgb = imagecolorat($img, $x, $y); $colors = imagecolorsforindex($img, $rgb); $r = $colors['red']; $g = $colors['green']; $b = $colors['blue']; if($white[0] < $r && $white[1] < $g && $white[2] < $b){ echo 'w'; }else if($red[0] < $r && $red[1] > $g && $red[2] > $b){ echo 'r'; }else if($gren[0] > $r && $green[1] < $g && $green[2] > $b){ echo 'g'; }else{ echo '@'; } } echo '<br>'; }
早速解説します。
まず 1 では画像の生成をしています。
そして生成した画像の幅と高さを取得してそれぞれ $x, $y に代入します。
2では RGB の閾値を設定します。
写真が全体的に暗いため設定も少し甘めになっています。
ここでポイントなのですが
「画像処理をするにはその前の下処理が重要となる」
今回は全体的に暗い、また全体的に明るいということも考えられます。
補足
ヒストグラム(カラーの分布)という概念があるのですが、これがある程度「疎」になっていると処理が楽になります。 なので実用化させるためには下処理も実装する必要があります。 今回はとりあえず閾値を甘めにするということで対応しています
3で画像をスキャンしていきます。
スキャンは画像の左上から右上、一段さげて左から右へと解析していくことです。
ここで1ピクセルづつRGBを取得し、用意した閾値により赤、白、緑、その他を判断し、それぞれ 「 r 」,「 w 」,「 g 」,「 @ 」を表示します。
以上ざっくりと画像処理についてでした。
しかし、今回赤、白はある程度うまく取得できたのですが、緑だけは中々うまく取得できませんでした。
つまり先程説明した下処理が必要ということが今回の原因のようです。
というわけで次回はその下処理の実装を考えていきたいと思います。
ではでは。
ルービックキューブの実装をPHPでしてみた~ルービックキューブクラス~
前回ルービックキューブにハマる~そしてアルゴリズムへ~ - nigoblog
ルービックキューブにハマったということを書いたのですが、今回そのアルゴリズムを実装するべくチャレンジすることにしました。
まずはアルゴリズムを記述する前に色々な動作を書く必要があると思ったのでそこから書いて行きました。
- ルービックキューブクラス
- ルービックキューブを配列で表す
- 入れ替え関数
- 回転処理関数
- まとめ
という流れでみていきます。
ルービックキューブクラス
まずは動作とデータモデルを表すためのクラスを設計します。
実装は次章以降で。
入れ替え
キューブの回転処理の際に発生する入れ替えを行うクラス。単純にスワップです。
回転処理
ここがメインです。ルービックキューブは回転させるという動作を組み合わせて遊ぶものです。
なので回転させ、その結果どうなったかを記述します。
回転の要素は3種類あって
- 方向
- 位置
- 回転角
がそれぞれ回転のパラメータです。
ある面を上に見た時に、
縦回転、横回転、高さ回転
それぞれ
右、中、左 (縦)
手前、中、奥 (横)
上、中、下 (高さ)
さらに
90, 180, 270 (単位: deg)
というわけで全27の動作があります。様々な書き方があると思いますが、方向を関数で、位置と回転角を引数で表します。
ルービックキューブを配列で表す
ルービックキューブクラス自体は次のようになります。
class Cube{ }
ここにフィールド変数という形でcubeモデルを作成します。
すると
class Cube{ private $cube = array( '1' => array('Y1', 'Y2', 'Y3', 'Y4', 'Y5', 'Y6', 'Y7', 'Y8', 'Y9'), '2' => array('G1', 'G2', 'G3', 'G4', 'G5', 'G6', 'G7', 'G8', 'G9'), '3' => array('O1', 'O2', 'O3', 'O4', 'O5', 'O6', 'O7', 'O8', 'O9'), '4' => array('R1', 'R2', 'R3', 'R4', 'R5', 'R6', 'R7', 'R8', 'R9'), '5' => array('B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7', 'B8', 'B9'), '6' => array('W1', 'W2', 'W3', 'W4', 'W5', 'W6', 'W7', 'W8', 'W9') ); }
という感じで表します。この時、YやらGやらは色を表しております。
またサイコロのように連想配列を設定します。
今回、ベクトルを2つ用意するか、一つのベクトルかで迷い、結局ベクトルは一つで表現することにしました。
入れ替え関数
これは単純にスワップなのですが、データ構造上、4つの引数が必要ということで次のようになりました。
public function swap($key1, $value1, $key2, $value2){ $tmp = $this->cube[$key1][$value1]; $this->cube[$key1][$value1] = $this->cube[$key2][$value2]; $this->cube[$key2][$value2] = $tmp; }
本当にただのスワップです。
回転処理関数
今回ここがメインとなります。
先程にも書きましたが、回転方向で関数を分け、位置と回転角を引数で表現します。すると次のようになります。
//position => right, center, left public function verticalRotate($position, $deg){ if($position == 'right'){ if($deg == 90){ $this->swap(1, 2, 5, 2); $this->swap(1, 5, 5, 5); $this->swap(1, 8, 5, 8); $this->swap(1, 2, 6, 2); $this->swap(1, 5, 6, 5); $this->swap(1, 8, 6, 8); $this->swap(1, 2, 2, 2); $this->swap(1, 5, 2, 5); $this->swap(1, 8, 2, 8); }elseif($deg == 180){ $this->swap(1, 2, 6, 2); $this->swap(1, 5, 6, 5); $this->swap(1, 8, 6, 8); $this->swap(2, 2, 5, 2); $this->swap(2, 5, 5, 5); $this->swap(2, 8, 5, 8); }elseif($deg == 270){ $this->swap(1, 2, 2, 2); $this->swap(1, 5, 2, 5); $this->swap(1, 8, 2, 8); $this->swap(1, 2, 6, 2); $this->swap(1, 5, 6, 5); $this->swap(1, 8, 6, 8); $this->swap(1, 2, 5, 2); $this->swap(1, 5, 5, 5); $this->swap(1, 8, 5, 8); } } }
長々と書いておりますが、今回は簡単のため
回転方向 縦
位置 右
角度 90, 180, 270
の3つのパターンの回転の動作を書きました。同様のものをあと24個書いて動作は完了です。(多い…)
まとめ
以上をまとめとして、実行部分のコードを示します。
$new_cube = new Cube(); $origin = $new_cube->getCube(); echo '<pre>'; print_r($origin); echo '</pre>'; $new_cube->verticalRotate('right', 270); $after_swap = $new_cube->getCube(); echo '<pre>'; print_r($after_swap); echo '</pre>';
まずはCubeクラスのインスタンスを作成します。
ちなみにこれまで説明しませんでしたが、ゲッターもあります。
まずはオリジナルを表示。つまり全部が揃っている状態。
次に縦方向に右の位置で270度回転させ、
それを表示しています。
結果は大量になるので載せませんが無事成功してました。
そんな感じで、
次は残りの動作を全て作成。
その後、問題をセットするなどをやっていきたいと思います。
ではでは