TOP Column Menu 戻る
WideStudio かんどころ(4)
WideStudioによる無作法なC++ 2003/05/03
第四回 本格的カレンダーのプログラムを作る
カレンダーの論理(1)
さて、前回で画面が完成したことになりました。
ⅠのデザインをⅡするにはどうしたらよいのでしょうか。
今回作成するプログラムは以下の区分にわかれます。
- 部品(オブジェクト)操作のプログラム
- 部品の大きさ(幅や高さ)の設定
- 部品の位置(Xj軸とY軸)の操作
- 表示文字列(キャプション)の設定
- カレンダーのアルゴリズム
- 曜日の取得
- うるう年の操作
- カレンダーアルゴリズムによる部品の操作
- 部品(オブジェクト)によるカレンダー操作
部品操作のプログラム
前回の部品の5つの分けを思い出してください
①年月日表示ラベル
②年移動ボタン
③月移動ボタン
④曜日表示ラベル
⑤日操作ボタン
| プログラム起動して初期カレンダーが表示されて以後 |
| 操作による変化(↓) 部品グループ(→) |
① |
② |
③ |
④ |
⑤ |
| 表示文字列が変わる |
○ |
× |
× |
× |
× |
| ①の年月日表示ラベルの変更が出来る |
× |
○ |
○ |
× |
○ |
| ⑤の日操作ボタンの位置や数を変更出来る |
× |
○ |
○ |
× |
× |
プログラム起動前では全ての部品の位置や表示文字列は画面Ⅰの状態でした。それが本日が2003年の5月3日ならⅡの画面になります。
ボタン操作によってⅢやⅣの画面の状態にもなります。
上の表のように
移動したり部品の数が変わったのは⑤の日操作ボタンです。
また、表示文字列の変わったのは①の年月日表示ラベルです。
Ⅱ(2003年5月)とⅢ(2003年6月)のカレンダー画面を見てください。5月の31日は土曜日ですので31のボタンは土曜の位置にあり、6月1日は当然日曜日になるわけですから、6月のカレンダーは日曜の位置から始まっています。
Ⅳのカレンダー画面(2003年8月)では1日は金曜から始まっています。そうすると日のボタンは6行となります。
カレンダーの日は4行から6行まで変化します。最も4行は1日が日曜日で閏年以外の2月のカレンダーだけです。
つまり、先ほどの表に付け加えなければならないのはカレンダーの縦の大きさも変化するということです。
|
0列目 |
1列目 |
2列目 |
3列目 |
4列目 |
5列目 |
6列目 |
| 日 |
月 |
火 |
水 |
木 |
金 |
土 |
| 0行目 |
0 0 |
0 1 |
0 2 |
0 3 |
0 4 |
0 5 |
0 6 |
| 1行目 |
1 0 |
1 1 |
1 2 |
1 3 |
1 4 |
1 5 |
1 6 |
| 2行目 |
2 0 |
2 1 |
2 2 |
2 3 |
2 4 |
2 5 |
2 6 |
| 3行目 |
3 0 |
3 1 |
3 2 |
3 3 |
3 4 |
3 5 |
3 6 |
| 4行目 |
4 0 |
4 1 |
4 2 |
4 3 |
4 4 |
4 5 |
4 6 |
| 5行目 |
5 0 |
5 1 |
5 2 |
5 3 |
5 4 |
5 5 |
5 6 |
では、この最も複雑な日ボタン移動の論理はどんなものなのでしょう。
次の表で日ボタン移動の場所を地図化してみましょう。つまり、左の数字は行(0〜5)をあらわし右の数字は列(0〜6又は日曜〜土曜)をあらわします。
もし、2003年6月みたいに1日が日曜なら8日も15日も22日も日曜日ですし、2日、9日、16日、23日は月曜日となります。つまり、7日後は同じ曜日なわけですね。(おぉ〜い!どうぜんじゃろ!)
2003年6月のカレンダーの論理
この場合(1日が日曜日)はその(日付−1)を7で割った余りが曜日に対応するわけです。
VisualBasicの場合は mod 関数が余りを計算し CやC++では % が余りを計算します。
- Visual Basicなら 曜日=( (日付-1) mod 7)
- CやC++なら 曜日=( (日付-1) % 7);
となりますね。
ところで、前回の画面作成の時にオブジェクトの配列の名称は[0]からはじまっていました。曜日も月も日も配列は全て[0]からはじめました。
つまり日移動のボタンの最初は ddbtn[0] は1日とすればよいわけです。また曜日ラベルは
yb[0]〜yb[6]を日月火水木金土にたいおうさせましょうね。日付に対応する配列番号は日付−1ということです。
そこで先ほどの曜日の計算式は
- Visual Basicなら 曜日=( (配列番号) mod 7)
- CやC++なら 曜日=( (配列番号) % 7);
だから14日は配列番号は13番です。従って曜日は13÷7での余り、即ち6ということになります。曜日配列番号の6は土曜日ということですね。6月14日は娘の誕生日なのですが、それが土曜日であることはこうして検証できるのですね。
では、行はどうなのでしょう。
行は配列番号を7で切り捨てで割った数字となります。
- Visual Basicなら 行番号=int( (配列番号) / 7)
- CやC++なら 行番号=( (配列番号) / 7);
1日〜7日は配列番号で0〜6ですので7で切捨てで割れば0と言うことになります。当然8日から14日は配列番号で[7]〜[13]なので7で割り切れば1になりますので1行目となります。
全ての月に通じるカレンダーの論理
では2003年の8月のカレンダーはどうなっているのでしょうか。8月の1日は金曜日です。3日は2行目の日曜日となります。
そこで先ほどの曜日の計算式に1日の曜日配列番号を補正値としていれてやればいいのです。
1日が金曜日ですので、金曜日の曜日配列番号は5です。
- Visual Basicなら 曜日=( (配列番号+1日の曜日配列番号) mod 7)
- CやC++なら 曜日=( (配列番号+1日の曜日配列番号) % 7);
となり行番号は
- Visual Basicなら 行番号=int( (配列番号+1日の曜日配列番号) / 7)
- CやC++なら 行番号=( (配列番号+1日の曜日配列番号) / 7);
もしも月の1日の曜日がわかればその月のカレンダーをつくる論路はこれで出来るわけです。あとはその月の最大の日が30日なのか31日なのか28日なのか4年に1度の29日なのかだけですね。