Shoeisha Technology Media

CodeZine(コードジン)

特集ページ一覧

Java meets Python - 第2回 配列と別れる50の方法

よろずプログラマーのためのPython導入ガイド (4)

  • ブックマーク
  • LINEで送る
  • このエントリーをはてなブックマークに追加
2007/11/13 14:00

配列を扱うたびに悩ましいのがArrayIndexOutOfBoundsExceptionです。配列の境界を越えないかという心配の種がなくなれば、明るい未来が開けてくるかもしれません。今回は、パズルの事例を通して、伝統的な手法から視点を移して、オブジェクト指向の立場から観察することで、これらの相互理解を深めます。

目次

はじめに

 連載2回目は、プログラミング歴2年余の伊藤が担当します。今回のパズルゲームは、プログラミングを始めたばかりの半年に満たない頃に作成したものです。当時を振り返りながら、初心に還ったつもりで解説しますので、よろしくお願いします。

 伝統的なスタイルを卒業して、OOPを習得するときに、越えなければならない壁の一つが配列です。2次元配列を扱った事例は多数ありますが、ともすると配列が主役になり、その中身が脇役になる場面も少なくありません。そこで、発想を転換して主客逆転させると、新しい世界が見えてくるかもしれません。

注意
 今回の記事は、ゲームを作成するための一般的な手法を紹介したものではありません。伝統的な手法とは違うオブジェクト指向の発想を示すのが「目的」です。ゲームを題材に選んだのは、目的(学習)を達成する手段(教材)の一つにすぎません。

対象読者

 こんな症状を抱えているなら……。

  • 配列を扱うたび、例外ArrayIndexOutOfBoundsExceptionに悩まされる。
    【効能】 主客転倒させることで、パラダイムシフトが容易になるかも。
    【副作用】 まだ配列を使っているんですかと言いたくなるかも。
    【おまけ】 Java/C#版のコードを、Jython版と比較してみるのも一興かも(サンプルファイルには、Java/C# 版のコードも収録されています)。

解けないパズルに懸賞金

 Fifteen Puzzleは、米国のパズル作家Samuel Loyd(1841-1911)が、1878年に創案したとされています。最初に整然と並べられた状態から「14と15だけを入れ換えた後で元に戻せるか」という問題に懸賞金が賭けられたほどですが、後に、不可能であることが証明されます。

 このパズルは「スライディングブロックパズル」に分類され、4×4に区切られたボードの上に番号(1~15)を振ったコマが並べてあります。一つだけ空いたマス目を利用して、これらのコマを移動させながら、目的の形を作ります。

 ここで、懸賞問題が解けないことを簡単に(実際の証明はもっと複雑)説明しておきます。コマの移動は、空いたマス目と交換する操作と見なせます。そのため、他のコマに手を触れず、任意の2つのコマだけを交換できません。

 今年も世界大会が開かれたルービックキューブは、これを3次元化したものと見なせます。分解して組み直す(途中で諦めて)ときに、キューブの方向を間違えると、元に戻せなくなります。これを逆手に取って、わざとそのキューブを仕込んでおくと、近所の腕自慢を当惑させられるかもしれません。

山手線の起点/終点(問題編)
 山手線の始点と終点を知っていますか。物事には始りと終りがあります。初めの一歩が末の千里に繋がるように、オブジェクト指向の奥義を極める旅の途中で、一息ついてみませんか。1872年(明治5年)には、日本初の鉄道が新橋-横浜間に開通しました。話を先に進める前に、山手線の始点と終点について想いを巡られてみるのも一興です。

配列の隘路

 現実の世界では、ゲーム盤の外にコマが飛び出すことがありますが、プログラミングの世界でも、同様のバグに悩まされます。配列の添字が範囲を超えると、C言語では実行時に暴走しかねません。Javaでは、運が良いとコンパイル時に警告されますが、運が悪いと実行時に例外ArrayIndexOutOfBoundsExceptionを生成します。

 配列の添字は「0から始まるべきか1からか」という論争は、プログラミング言語の違いを越えて、今も続いています。例えば、Javaで条件式を記述するときに、

for (int i = 0; i <= array.Length; i++)

 等号「=」が必要かどうかで、迷ったりしませんか。この添字問題とよく似た状況が、部分文字列にも見られます。

ある事情:Javaの立場

 Javaでは、部分文字列を生成したいとき、次のように記述します。

substring(begin, end);

 ここで、先頭の位置が0になるのは、後に示すC#と同じです。先頭はbeginですが、違いはその末尾です。例えば、次のようにすると、

"string".substring(3, 5);  // Java

 得られる部分文字列は、"in"でしょうか。"ing"でしょうか。山手線の先頭と末尾も気掛りですが、ここは先を急ぎましょう。

ある事情:C#の立場

 C#では、部分文字列を生成したいとき、次のように記述します。

Substring(startIndex, length);

 先頭の位置startIndexとそこからの長さlengthを指定して、部分文字列を生成します。例えば、次のようにすると、

"string".Substring(3, 2);  // C#

 部分文字列"in"が得られます。先頭の位置が0になるのは、Javaと同じです。3番目の位置から長さ2の部分文字列を生成するときに、選択の余地はありません。

ある事情:Pythonの立場

 Pythonでは、部分文字列を生成するときに、スライスという概念を適用します。スライスとは、どの位置で「切り分けるslice」かということです。

 指定した位置で文字列を切り分けたと考えるなら、添字endの位置は、生成される部分文字列には含まれません。山手線の起点/終点を知らなくても問題ありませんが、部分文字列の先頭/末尾は押さえておきたいものです。


  • ブックマーク
  • LINEで送る
  • このエントリーをはてなブックマークに追加

著者プロフィール

  • 伊藤うさぎ(イトウ ウサギ)

    ペンネームの「由来は」と言うと。苗字の方は、セミナー研修で同じチームになった、3人の合体ユニット名 [I:石塚, T:田川, O:尾沢] から来ています。名前の方は、同じ干支(卯:1987 年生)に因んだものです。既に2人は卒業して、残る1人がその名跡を継承しています。

  • 小泉ひよ子とタマゴ倶楽部(コイズミヒヨコトタマゴクラブ)

    http://tamago-club.cocolog-nifty.com/ 「楽しくなければ仕事じゃない」が私たちのモットー。99%の苦悩の連続も、1%の成功に報われます。だからこそ、この仕事が楽しくて仕方がないのです。楽をするための努力なら惜しみません。何もせず楽をしているのと、努力をしたか...

バックナンバー

連載:よろずプログラマーのためのPython導入ガイド

もっと読む

All contents copyright © 2005-2019 Shoeisha Co., Ltd. All rights reserved. ver.1.5