関数のコメントが細かく多い クラスや 関数 1つ 1 つにコメントを細かく多く入れる事を正しいと勘違いしている人は多くいます また 学校によってはその様な指導をする所もあります しかし プログラムが分かり易ければコメントを書く必要性は低く 多いと逆に読みにくくなります 特に関数の説明をするコメントの

Similar documents
Microsoft PowerPoint - CproNt02.ppt [互換モード]

JavaプログラミングⅠ

株式会社アルウィン C 言語コーディング規約 ver.0.1

PowerPoint プレゼンテーション

/*Source.cpp*/ #include<stdio.h> //printf はここでインクルードして初めて使えるようになる // ここで関数 average を定義 3 つの整数の平均値を返す double 型の関数です double average(int a,int b,int c){

Microsoft PowerPoint Java基本技術PrintOut.ppt [互換モード]

教材ドットコムオリジナル教材 0から始めるiアフ リ リファレンス i アプリ簡易リファレンス ver i アプリ Java 独自のメソッド (1)iアプリの命令を使えるようにする import com.nttdocomo.ui.*; (2) 乱数を使う import java.u

Java講座

Microsoft PowerPoint - prog03.ppt

Slide 1

Java Scriptプログラミング入門 3.6~ 茨城大学工学部情報工学科 08T4018Y 小幡智裕

<4D F736F F D2091E63589F182628CBE8CEA8D758DC08E9197BF2E646F6378>

とても使いやすい Boost の serialization

Javaプログラムの実行手順

概要 プログラミング論 変数のスコープ, 記憶クラス. メモリ動的確保. 変数のスコープ 重要. おそらく簡単. 記憶クラス 自動変数 (auto) と静的変数 (static). スコープほどではないが重要.

Prog2_12th

(1) プログラムの開始場所はいつでも main( ) メソッドから始まる 順番に実行され add( a,b) が実行される これは メソッドを呼び出す ともいう (2)add( ) メソッドに実行が移る この際 add( ) メソッド呼び出し時の a と b の値がそれぞれ add( ) メソッド

char int float double の変数型はそれぞれ 文字あるいは小さな整数 整数 実数 より精度の高い ( 数値のより大きい より小さい ) 実数 を扱う時に用いる 備考 : 基本型の説明に示した 浮動小数点 とは数値を指数表現で表す方法である 例えば は指数表現で 3 書く

Java プログラミング Ⅰ 7 回目 switch 文と論理演算子 今日の講義講義で学ぶ内容 switch 文 論理演算子 条件演算子 条件判断文 3 switch 文 switch 文 式が case のラベルと一致する場所から直後の break; まで処理しますどれにも一致致しない場合 def

JavaプログラミングⅠ

break 文 switch ブロック内の実行中の処理を強制的に終了し ブロックから抜けます switch(i) 強制終了 ソースコード例ソースファイル名 :Sample7_1.java // 入力値の判定 import java.io.*; class Sample7_1 public stati


Microsoft PowerPoint - ruby_instruction.ppt

slide5.pptx

2

Microsoft PowerPoint - 計算機言語 第7回.ppt

Method(C 言語では関数と呼ぶ ) メソッドを使うと 処理を纏めて管理することができる 処理 ( メソッド ) の再実行 ( 再利用 ) が簡単にできる y 元々はC 言語の関数であり 入力値に対する値を 定義するもの 数学では F(x) = 2x + 1 など F(x)=2x+1 入力値 (

C プログラミング演習 1( 再 ) 2 講義では C プログラミングの基本を学び 演習では やや実践的なプログラミングを通して学ぶ

02: 変数と標準入出力

Microsoft Word - no11.docx

第 2 章インタフェース定義言語 (IDL) IDL とは 言語や OS に依存しないインタフェース定義を行うためのインタフェース定義言語です CORBA アプリケーションを作成する場合は インタフェースを定義した IDL ファイルを作成する必要があります ここでは IDL の文法や IDL ファイ

02: 変数と標準入出力

Functional Programming

intra-mart Accel Platform — IM-Repository拡張プログラミングガイド   初版  

プログラミングA

PowerPoint プレゼンテーション

メソッドのまとめ

することができます通常は 開発現場ごとに 関数の説明として記述する内容や形式が決まっていること が多いです javadoc 内では コメントを記入する際にクラスやメソッドの役割を示す為のタグを使用します : : クラス

Microsoft PowerPoint - chap10_OOP.ppt

た場合クラスを用いて 以下のように書くことが出来る ( 教科書 p.270) プログラム例 2( ソースファイル名 :Chap08/AccountTester.java) // 銀行口座クラスとそれをテストするクラス第 1 版 // 銀行口座クラス class Account String name

Sort-of-List-Map(A)

Java プログラミング Ⅰ 3 回目変数 変数 変 数 一時的に値を記憶させておく機能型 ( データ型 ) と識別子をもつ 2 型 ( データ型 ) 変数の種類型に応じて記憶できる値の種類や範囲が決まる 型 値の種類 値の範囲 boolean 真偽値 true / false char 2バイト文

PowerPoint プレゼンテーション

プログラミング基礎I(再)

GEC-Java

<4D F736F F D20438CBE8CEA8D758DC F0939A82C282AB2E646F63>

オブジェクト指向プログラミング・同演習 5月21日演習課題

Prog1_10th

Java演習(4) -- 変数と型 --

Microsoft PowerPoint - kougi7.ppt

Microsoft PowerPoint - handout07.ppt [互換モード]

人工知能入門

数はファイル内のどの関数からでも参照できるので便利ではありますが 変数の衝突が起こったり ファイル内のどこで値が書き換えられたかわかりづらくなったりなどの欠点があります 複数の関数で変数を共有する時は出来るだけ引数を使うようにし グローバル変数は プログラムの全体の状態を表すものなど最低限のものに留

PowerPoint プレゼンテーション

.NETプログラマー早期育成ドリル ~VB編 付録 文法早見表~

PowerPoint プレゼンテーション

Java プログラミング Ⅰ 7 回目 switch 文と論理演算子 条件判断文 3 switch 文 switch 文式が case の値と一致した場合 そこから直後の break; までを処理し どれにも一致しない場合 default; から直後の break; までを処理する 但し 式や値 1

分割コンパイル (2018 年度 ) 担当 : 笹倉 佐藤 分割コンパイルとは 一つのプログラムのソースを複数のソースファイルに分けてコンパイルすること ある程度大きなプログラムの場合ソースファイルをいくつかに分割して開発するのが普通 1

Microsoft Word - Training10_プリプロセッサ.docx

プログラミング基礎


JUnit 概要 2015/4/16 版今泉俊幸 2015 bbreak Systems 1

Microsoft PowerPoint - ●SWIM_ _INET掲載用.pptx

Microsoft PowerPoint - lec06 [互換モード]

スライド 1

Prog1_15th

ガイダンス

JavaプログラミングⅠ

PowerPoint Presentation

メンバ変数とインスタンス

program7app.ppt

関数 C 言語は関数の言語 関数とは 関数の定義 : f(x) = x * x ; 使うときは : y = f(x) 戻り値 引数

Microsoft Word - no15.docx

Microsoft PowerPoint P演習 第10回 関数.ppt [互換モード]

プログラミング入門1

C#の基本2 ~プログラムの制御構造~

PowerPoint プレゼンテーション

Microsoft PowerPoint ppt

SuperH RISC engine C/C++ コンパイラ Ver.7 不具合内容 - 過去のお知らせ SuperH RISC engine C/C++ コンパイラ Ver.7 台における不具合内容を以下に示します のチェックツールをルネサスエレクトロニクス株式会社のホームページ

PowerPoint Presentation

memo

コンピュータ工学講義プリント (7 月 17 日 ) 今回の講義では フローチャートについて学ぶ フローチャートとはフローチャートは コンピュータプログラムの処理の流れを視覚的に表し 処理の全体像を把握しやすくするために書く図である 日本語では流れ図という 図 1 は ユーザーに 0 以上の整数 n

Microsoft Word - no12.doc

プログラミングA

バイオプログラミング第 1 榊原康文 佐藤健吾 慶應義塾大学理工学部生命情報学科

Microsoft PowerPoint - 09.pptx

プログラミング基礎

Prog1_6th

課題

GEC-Java

デバッグの工夫

タブ or スペース? インデントには タブ文字を使用する方法と半角スペースを使用する方法があります インデントにタ ブ文字を使うか半角スペースを使うかは 各プロジェクトで決められていることもありますが プログラ ムを書く人の好みだったりすることもあります まともなエディタであれば タブキーを押下し

演算増幅器

やさしいJavaプログラミング -Great Ideas for Java Programming サンプルPDF

3,, となって欲しいのだが 実際の出力結果を確認すると両方の配列とも 10, 2, 3,, となってしまっている この結果は代入後の配列 a と b は同じものになっていることを示している つまり 代入演算子 = によるの代入は全要素のコピーではなく 先をコピーする ため 代入後の a と b は

第 1 章 Java 言語について ( オブジェクト指向, 変数の扱い方, 繰り返し条件と条件分岐 ) Java 言語の概要とオブジェクト指向, 変数の扱い方, 繰り返し条件と条件分岐について理解し, プログラム作成を行う 1.1 Java 言語の概要 JAVA は Sun Microsystems

Javaセキュアコーディングセミナー東京 第2回 数値データの取扱いと入力値の検証 演習解説

プログラミングA

Microsoft Word - C言語研修 C++編 3.doc

K227 Java 2

Transcription:

悪いプログラムの書き方 今回は応募作品中に見られる 初心者にありがちな悪いプログラムの書き方について 例をあげて説明したいと思います 悪い書き方これだけではなく まだ沢山ありますので更に本を読んだりして勉強して下さい また 書き方について更に学びたい場合は コーディングルール をみてみると良いでしょう 会社やチームごとに細かな違いがありますが コーディングルール はどの様にすれば間違いが少なく 無駄が少なく 統一的な書き方が出来るか を考えて作られた規約です ネット上では様々な コーディングルール が公開されています Google で "C++ コーディングルール " を検索してみて下さい ローマ字表記を使用している 少数ですがプログラム中にローマ字表記を使う人がいます その人たちは例外なくプログラムの書き方が良くありませんので 評価する側はローマ字表記を見た時点で初心者と判断します プログラムでは英語表記が基本です 英単語は辞書ですぐ調べられるので 必ず 英語を使って下さい int teki_suu; int zikan; Foo* Kensaku( const char* namae ); int enemy_num; int time; Foo* Find( const char* name ); 表記が統一されていない 会社説明会のスライドでも説明しましたが 書き方が統一されていないプログラムは読みにくく チーム制作ではバグの原因になります 大文字 小文字の混在 複数単語の表記順番が違う といった間違いが多いです 以下の例ではスピードを表す単語が Spd, spd,speed の 3 つがあり 前に動詞が付いたり付かなかったりしています また 変数名の開始が大文字だったり 小文字だったりしています class Player Vector3 pos; float Rot; float jumpspd; float speedx; float speedy; float enemy_spd; int Action; int ActCount; int ActCntTemp; ; class Player Vector3 pos; float rot; float jumpspd; float movexspd; float moveyspd; float enemyspd; int action; int actcnt0; int actcnt1; ;

関数のコメントが細かく多い クラスや 関数 1つ 1 つにコメントを細かく多く入れる事を正しいと勘違いしている人は多くいます また 学校によってはその様な指導をする所もあります しかし プログラムが分かり易ければコメントを書く必要性は低く 多いと逆に読みにくくなります 特に関数の説明をするコメントの内容の多くは関数自体を見れば分かるので 書く必要がありません 例えば Draw() 関数の説明に 描画する と書いてあっても無意味です シンプルなコメントを心がけましょう そして 分かりにくい動作をする場合や 関数の呼び出しに注意するべき事項がある場合にコメントを入れましょう 例えば以下の様な動作が単純な関数では 書かなくても意味が理解できます また引数も分かりやすい名前を付ける事で分かりやすく出来ます /******************************************************************************/ /* 関数名 : Stage::Clear() 書いてあるのでいらない説明 : ステージの初期化用関数 関数名から意味がわかるので必要ない引数 1 : ステージ番号 なるべく引数の変数名で意味がわかる様にしておく戻り値 : なし担当 : 宇佐見 バージョン管理ツールをつかえば誰が何を作成 変更したかわかる作成日 : 2014/06/06 バージョン管理ツールをつかえば誰が何を作成 変更したかわかる */ /******************************************************************************/ void Stage::Initialize( int n ) m_ stageid = n; /******************************************************************************/ /* 関数名 : Stage::Draw() 説明 : ステージを描画する 引数 1 : なし 戻り値 : なし 担当 : 宇佐見 作成日 : 2014/06/06 */ /******************************************************************************/ void Stage::Draw() m_stageobject.draw(); void Stage::Initialize( int stageid ) m_stageid = stageid; void Stage::Draw() m_stageobject.draw(); 即値を多用する 会社説明会のスライドでも説明しましたが 調整や変更される可能性が高い箇所に直に数値を指定してはいけません 以下の例では三次元のマップデータを生成しています しかし これでは固定のサイズのマップデータしか生成できません class MapBlock int m_blocktbl[10][30][30]; public: void Initialize(); ; void MapBlock::Initialize() for( int y = 0; y < 10; ++y ) for( int z = 0; z < 30; ++z ) for( int x = 0; x < 30; ++x ) m_blocktbl[y][z][x] = BLOCK_SPACE; m_blocktbl[1][ 2][ 2] = BLOCK_DOOR; m_blocktbl[3][15][ 4] = BLOCK_START; m_blocktbl[7][ 4][28] = BLOCK_GOAL;

m_blocktbl[6][14][18] = BLOCK_SW1; m_blocktbl[0][22][ 6] = BLOCK_SW2; プログラムが長くなりますが 以下の様に大きさが変わっても問題無く動くようにするべきです そして 生成する際の大きさやアイテムの配置はデータ化しています この様に設定部分をデータ化する事で 後で容易に変更できるようになります データ部分以外に 0 以外の即値がない点が重要です struct MapItem int m_x; int m_y; int m_z; int m_type; ; struct MapData int m_xsize; int m_zsize; int m_ysize; const MapItem* m_itemtbl; ; class MapBlock int* m_blocktbl; int m_xsize; int m_zsize; int m_ysize; int m_xzsize; int m_xzysize; public: void Initialize( const MapData& data ); void SetItem( const MapItem& item ); ; void MapBlock::Initialize( const MapData& data ) m_xsize = data.m_xsize; m_zsize = data.m_zsize; m_ysize = data.m_ysize; m_xzsize = m_xsize * m_zsize; m_xzysize = m_xzsize * m_ysize; m_blocktbl = new int[m_xzysize]; for( int y = 0; y < m_ysize; ++y ) for( int z = 0; z < m_zsize; ++z ) for( int x = 0; x < m_xsize; ++x ) int n = ( y * m_xzsize ) + ( z * m_xsize ) + x; m_blocktbl[n] = BLOCK_SPACE; for( int i = 0; i < data.m_itemtbl[i].m_type!= BLOCK_SPACE; ++i ) SetItem( data.m_itemtbl[i] ); void MapBlock::SetItem( const MapItem& item ) if( item.m_x < 0 item.m_x >= m_xsize ) return; if( item.m_z < 0 item.m_z >= m_zsize ) return; if( item.m_y < 0 item.m_y >= m_ysize ) return; int n = ( item.m_y * m_xzsize ) + ( item.m_z * m_xsize )+ item.m_x; m_blocktbl[n] = item.m_type; void CreateMap00() const MapItem mapitem00[] = 2, 2, 1, BLOCK_DOOR, 15, 4, 3, BLOCK_START, 4, 28, 7, BLOCK_GOAL, 14, 18, 6, BLOCK_SW1, 22, 6, 0, BLOCK_SW2, 0, 0, 0, BLOCK_SPACE, ;

const MapData mapdata00 = 30, 30, 10, mapitem00 ; MapBlock mapblock; mapblock.initialize( mapdata00 ); 1 つの式に [] 演算子 -> 演算子. 演算子が 何個も使われている オブジェクトを参照する為に使われる [] 演算子 -> 演算子. 演算子が連なって使われる場合は プログラムの構造化が出来ていないか 構造体やクラスの設計に問題がある場合が殆どです 処理ごとに関数を分けて下さい そうすると これらの演算子を多用する事は無くなります 以下の例では Game クラスの中に Player クラスの処理が入っています その為 Player クラスやその先のオブジェクトを参照する為の演算子を多用します void Game::UpdatePlayer() for( int i = 0; i < PLAYER_NUM; ++i ) if( g_playertbl[i].getactionflag() == ACT_ATTACK ) Vector3 dirc = g_playertbl[i].getweapon()->getdirction(); Vector3 pos = g_playertbl[i].getposition(pl_arm_r); g_playertbl[i].getweapon()->createbullet( pos, dirc ); if( g_playertbl[i].getactionflag() == ACT_GUARD ) // ガードの処理 Player クラスに対する処理は Player クラスの関数で処理を行う様にします また プレイヤーの条件による処理の分岐 と プレイヤー起こす行動 で動作の意味が違いますので これも関数を分けます void Game::UpdatePlayer() for( int i = 0; i < PLAYER_NUM; ++i ) g_playertbl[i].update(); void Player::Update() if( GetActionFlag() == ACT_ATTACK ) Attack(); if( GetActionFlag() == ACT_GUARD ) Guard(); void Player::Attack() Weapon* weapon = GetWeapon(); Vector3 dirc = weapon->getdirction(); Vector3 pos = GetPosition(PL_ARM_R); weapon->createbullet( pos, dirc ); void Player::Guard() // ガードの処理 関数 1 つの行数が長い 関数の行数が多い場合 1 つの関数に処理を詰め込みすぎている場合が殆どです

長くなる場合は機能ごとに関数を分けて下さい そうすると これらの長い関数になる事は無くなります 基本 100 行以内に収めましょう 以下の例では プレイヤーの移動処理全てを 1 つの関数にまとめて書いてしまっています この様なパターンはよく見かけます プレイヤーの状態判定と 行動処理 ステージとの衝突判定が全て入っています void Game::UpdatePlayer() const float limit = 0.0f; D3DXVECTOR3 vec; if( player.getflyflag() == false && player.getactiveflag() == false ) D3DXVECTOR3 movepos; if( IsInputKey(KEY_UP) ) bool ishit = false; D3DXVec3TransformCoord(&vec,&D3DXVECTOR3( 0, 0, 1 ), &player.getrot() ); D3DXVec3Normalize( &vec, &vec ); for(int i = 0; i < stage.getobjmax(); i++ ) D3DXVECTOR3 dist = player.getpos() - stage.getobj(i)->getpos(); if( D3DXVec3Length( &dist ) <= 12 ) short collisionid = stage.getobj(i)->getcollisionid(); if(collisionid!=-1) if( player.frontray( xobj.getobj( collisionid )->GetMesh(), &stage.getobj(i)->getmatrix(), limit, &movepos ) == true ) ishit=true; else if( player.frontray( xobj.getobj( stage.getobj(i)->getobjnum() )->GetMesh(), &stage.getobj(i)->getmatrix(), limit, &movepos ) == true) ishit=true; if( ishit == true ) bool bflg = false; D3DXVec3TransformCoord( &vec, &D3DXVECTOR3( 0, 0, -1 ), &player.getrot() ); D3DXVec3Normalize( &vec, &vec ); for( int i = 0; i < stage.getobjmax(); i++ ) D3DXVECTOR3 dist = player.getpos() - stage.getobj(i)->getpos(); if( D3DXVec3Length( &dist ) <= 12 ) if( bflg == false ) D3DXVECTOR3 plpos = player.getpos() + movepos; player.initpos( plpos.x, player.gety(), plpos.z ); else if(player.getjumpflg()==false) player.setpos( 0, 0, 0.5f ); else player.setpos( 0, 0, 0.25f ); if( IsInputKey( KEY_DOWN ) ) if( IsInputKey( KEY_LEFT ) )

if( IsInputKey( KEY_RIGHT ) ) if( IsInputKey( KEY_SPACE ) ) この様な場合 衝突判定は Stage クラスの関数に プレイヤーの処理は Player クラスの関数に分け 更に Player クラスの関数は 条件判定処理 と 行動処理 で更に関数に分けます この様に関数 1 つ 1 つが何の処理を担当しているか 明確に区分する事が重要です const float limit = 0.0f; bool Stage::CollisionPlayer( Player& player, D3DXVECTOR3* movepos ) D3DXVECTOR3 vec; D3DXVec3TransformCoord(&vec,&D3DXVECTOR3( 0, 0, 1 ), &player.getrot() ); D3DXVec3Normalize( &vec, &vec ); for( int i = 0; i < GetObjMax(); i++ ) SMesh* meshobj = stage.getobj(i); D3DXVECTOR3 dist = player.getpos() - meshobj->getpos(); if( D3DXVec3Length( &dist ) <= 12 ) short collisionid = GetObj(i)->GetCollisionId(); LPD3DXMESH d3dmesh = collisionid!= -1? xobj.getobj( collisionid )->GetMesh() : xobj.getobj( meshobj->getobjnum() )->GetMesh() ; if( player.frontray( d3dmesh, &meshobj->getmatrix(), limit, movepos ) ) return true; return false; bool Stage::CollisionPlayer2nd( Player& player, D3DXVECTOR3* movepos ) D3DXVECTOR3 vec; D3DXVec3TransformCoord( &vec, &D3DXVECTOR3( 0, 0, -1 ), &player.getrot() ); D3DXVec3Normalize( &vec, &vec ); for( int i = 0; i < GetObjMax(); i++ ) SMesh* meshobj = stage.getobj(i); D3DXVECTOR3 dist = player.getpos() - meshobj->getpos(); if( D3DXVec3Length( &dist ) <= 12 ) return false; void Player::MoveForward() D3DXVECTOR3 movepos; bool ishit = stage.collisionplayer( *this, &movepos ); if( ishit == true ) bool ishit2 = stage.collisionplayer2nd( *this, &movepos ); if( ishit2 == false ) D3DXVECTOR3 plpos = GetPos() + movepos; InitPos( plpos.x, GetY(), plpos.z );

else if( GetJumpFlg() == false ) SetPos( 0, 0, 0.5f ); else SetPos( 0, 0, 0.25f ); void Player::Update() if( GetFlyFlag() == false && GetActiveFlag() == false ) if( IsInputKey( KEY_UP ) ) MoveForward(); if( IsInputKey( KEY_DOWN ) ) MoveBack(); if( IsInputKey( KEY_LEFT ) ) TurnLeft(); if( IsInputKey( KEY_RIGHT ) ) TurnRight(); if( IsInputKey( KEY_SPACE ) ) Jump(); //----------------------------- File game.h void Game::UpdatePlayer() player.update(); グローバル変数 スタティック変数を多用する ゲーム全体で使用する変数を利用するとき グローバル変数 スタティック変数を使わないようにしましょう 初心者はこのような変数を 1 つのファイルに設定値をまとめて それを参照するための global.h を定義するといった傾向があります 以下の様な例では ゲームでの設定値は Game クラスのオブジェクトに グラフィックデバイス関連の値は GraphicDevice クラスに と機能ごとにクラスを作り そのメンバとして定義する様にして下さい //----------------------------- File global.h extern LPDIRECT3DDEVICE g_d3ddevice; extern int g_nowstageid; extern int g_player1id; extern int g_player2id; extern int g_playtime; extern bool g_debugflag; //----------------------------- File main.cpp LPDIRECT3DDEVICE g_d3ddevice; // グラフィックデバイスへのアクセス int g_nowstageid; // 現在のステージ番号 int g_player1id; // 1Pのプレイヤー番号 int g_player2id; // 2Pのプレイヤー番号 int g_playtime; // プレイ残り時間 bool g_debugflag; // デバッグ機能ありorなし //----------------------------- File stage.h class Stage int m_id; ; //----------------------------- File graphicdevice.h class GraphicDevice LPDIRECT3DDEVICE m_device; ; //----------------------------- File player.h class Player int m_id; ; //----------------------------- File game.h

class Game int m_debugflag; int m_playtime; ; // それぞれのクラスは 必要な段階で new をして確保する 同じ処理を何度も呼び出す 以下の例では 関数は整頓されているように見えますが 条件判断文の条件と関数の引数が違うだけで 同じ関数呼び出しが並んでいます このようなプログラムは データ と 処理 に分けることが出来ます void Enemy::DropItem() int temp = GetRand(19); switch( kind ) case MANTIS: if( temp < 10 ) MakeItem( Item::POINT_LOW,position ); else if( temp == 10 ) MakeItem( Item::HP_MINI,position ); else if( temp < 14 ) MakeItem( Item::BOM_MINI,position ); case APPLE: if( temp < 8 ) MakeItem( Item::POINT_HIGH,position ); else if( temp < 12 ) MakeItem( Item::SCORE,position ); else if( temp < 16 ) MakeItem( Item::RAPID,position ); else MakeItem( Item::HP_BIG,position ); case MISSILETANK: if( temp < 3 ) MakeItem( Item::HP_MINI,position ); else if( temp < 4 ) MakeItem( Item::HP_BIG,position ); else if( temp < 9 ) MakeItem( Item::BOM_MINI,position ); else if( temp < 14 ) MakeItem( Item::BOM_BIG,position ); 違う部分 ( 条件判断文の条件と関数の引数 ) をデータとして分けます この部分は将来 ファイルから読み込ませたり エディタで値を変更させられるようにしたり といった変更を簡単に出来るようになります また データ部分が増えてもプログラムは増えることはありません static Item::Type GetDropItem( const DropItemTbl* dropitemptr ) int rate = GetRand(19); for( ; dropitemptr->rate!= 0; ++dropitemptr ) if( rate < dropitemptr->rate ) return dropitemptr->itemtype; void Enemy::DropItem() const DropItemTbl dropitemtbl_mantis[] = 10, Item::POINT_LOW, 11, Item::HP_MINI, 14, Item::BOM_MINI, 0, Item::NONE, ; const DropItemTbl dropitemtbl_apple[] = 8, Item::POINT_HIGH, 12, Item::SCORE, 16, Item::RAPID, 0, Item::HP_BIG, ; const DropItemTbl dropitemtbl_missiletank[] = 10, Item::POINT_LOW, 11, Item::HP_MINI, 14, Item::BOM_MINI, 0, Item::NONE, ; const DropItemTbl* dropitemtbl[] = dropitemtbl_mantis, dropitemtbl_apple, dropitemtbl_missiletank, ; // テーブル数はテーブルから求める const int tblsize = sizeof(dropitemtbl)/sizeof(dropitemtbl[0]);

if( kind < 0 kind >= tblsize ) return; Item::Type itemtype = GetDropItem( dropitemtbl[kind] ); if( itemtype!= Item::NONE ) MakeItem(itemType,position); 変数の確保定数に const 指定を行わない 定数には必ず const を付けましょう 以下の例では 関数内にデータテーブルを持っていて それが書きかえられないにも関わらず const を付けていません この様な箇所が多いと 変数や定数の区別が付いていない初心者と判断されてしまいます void StageBlock::CheckCorner( int xpos, int ypos ) int checktbl[][2] = 1,1, 1,-1, -1,-1, -1,1 ; unsigned int result = 0; for( int i = 0; i < 4; ++i ) result = CheckPos( xpos + checktbl[i][0], ypos + checktbl[i][1] ); void StageBlock::CheckCorner( int xpos, int ypos ) const int checktbl[][2] = 1,1, 1,-1, -1,-1, -1,1 ; unsigned int result = 0; for( int i = 0; i < 4; ++i ) result = CheckPos( xpos + checktbl[i][0], ypos + checktbl[i][1] );