2110427
: การบ้านครั้งที่ 3
จุดประสงค์
- ออกแบบขั้นตอนวิธีการแบ่งข้อความในหนึ่งย่อหน้าให้เป็นบรรทัดต่างๆ
เพื่อแลดูสวยงาม
โดยใช้กำหนดการพลวัต โดยผลของการบ้านดูได้จาก applet ข้างล่างนี้
สามารถเปลี่ยนแปลงข้อความได้โดยตรงในช่องด้านบน จะปรากฎการจัดบรรทัดใหม่โดยทันทีที่ช่องด้านล่าง
หรือถ้าอยากลองปรับความกว้างของเนื้อที่ที่แสดง ก็ให้นำ mouse ไปวางไว้ในกรอบสี่เหลี่ยมน้ำเงิน กดแล้วลากดู
ความเป็นมา
หน้าที่พื้นฐานอย่างหนึ่งของโปรแกรมประมวลจัดพิมพ์เอกสารในปัจจุบันที่ต้องทำก็คือ การแบ่งข้อความในย่อหน้าหนึ่งๆ ออกเป็นบรรทัดๆ โดยการแบ่งนี้มีจุดประสงค์เพื่อให้ที่ว่างทางขวามือปลายบรรทัดในแต่ละบรรทัดของย่อหน้า (ยกเว้นบรรทัดสุดท้าย) แลดูสวยงาม
กำหนดให้บรรทัดหนึ่งมีความกว้างของบริเวณที่แสดงข้อความวัดได้ M จุดภาพ (pixels) ถ้าบรรทัดหนึ่งประกอบด้วยคำที่ i ถึง j ของย่อหน้า บรรทัดนั้นจะกินที่ไป
(พจน์ ji ก็คือช่องว่างที่ต้องคั่นระหว่างคำในภาษาอังกฤษ) ดังนั้นที่ว่างที่เหลือปลายบรรทัดก็คือ

โดยที่ SPACE คือจำนวนจุดภาพตามแนวกว้างของช่องว่างหนึ่งช่อง และ เป็นฟังก์ชันคำนวณจำนวนจุดภาพของความกว้างในการแสดง ซึ่งคือคำที่ k ของข้อความ กำหนดให้ย่อหน้าหนึ่งถูกแบ่งเป็น m บรรทัด บรรทัดที่ i ของย่อหน้า เริ่มด้วยคำที่ ของย่อหน้า ดังนั้นบรรทัดที่ i ก็ย่อมมีที่ว่างปลายบรรทัดเป็น

แล้วเราจะนิยามความสวยของการพิมพ์ได้อย่างไร แน่นอนว่าความสวยที่ว่านี้คงต้องขึ้นกับ
(ยกเว้นบรรทัดสุดท้ายของย่อหน้า เพราะถึงแม้มีที่ว่างเยอะก็แลดูไม่น่าเกลียด) ก็ต้องลองดูว่าเราจะแปลงความสวยมาเป็นฟังก์ชันจุดประสงค์กันอย่างไรดี จึงจะสะท้อนว่าถ้ามีค่าน้อยแสดงว่าสวยมาก (0 แสดงว่าสวยสุด) มีค่ามากก็สวยน้อย ถ้าให้เป็น ก็อาจจะไม่ค่อยดีเพราะถ้าบรรทัดหนึ่งว่าง 10 อีกบรรทัดว่าง 0 จะสวยเหมือนบรรทัดหนึ่งว่าง 5 อีกบรรทัดก็ว่าง 5 (ซึ่งแบบหลังน่าจะสวยกว่า) ก็แสดงว่าเราไม่ชอบที่ว่างเยอะ อันนี้ทำได้เช่น ให้ทำโทษเป็นยกกำลังสองของที่ว่าง ได้ฟังก์ชันจุดประสงค์เป็น หรือแม้กระทั่งให้เป็น ก็จะสะใจมากขึ้น
สำหรับการบ้านครั้งนี้ขอเป็นยกกำลังสามก็แล้วกัน (ไม่มีเห็นผลใดนอกจากความสะใจ แต่ถ้าจะทดลองเปรียบเทียบดูก็ดีเหมือนกัน)
สิ่งที่ต้องทำ
ฺเขียน
method wordWrap ในแฟ้ม Hw3.java ซึ่งมีหัวดังนี้
public static Vector wordWrap( String text, int width, FontMetrics fm ){
...
}
|
- wordWrap เป็น static method
หมายความว่าสามารถเรียกใช้ได้โดยไม่ต้องสร้าง
object ของ class ทีมี method นี้ (นั่นคือสามารถเรียกใช้
Hw3.wordWrap(s,w,f) ได้เลย)
- text คือ string
ที่เก็บตัวอักษรต่างๆของทั้งย่อหน้า
- width คือ
จำนวนจุดภาพ (pixel)
ของความกว้างของเนื้อที่แสดงในหนึ่งบรรทัด
- fm คือ
ตัวที่ใช้ช่วยหาขนาดต่างๆที่เกี่ยวกับ
font
เช่นเราสามารถใช้หาจำนวนจุดภาพตามแนวกว้างของ
blank หนึ่งตัว
ได้โดยเรียกใช้ space = fm.charWidth( ' '
);
หรือใช้หาจำนวนจุดภาพตามแนวกว้างของ
string x ได้โดยเรียกใช้ w =
fm.stringWidth( x );
อ่านรายละเอียดต่างๆ
ได้จาก help ของ JDK เรื่อง class
FontMetrics (อาจใช้ method อื่นๆ แทน
charwidth หรือ stringWidth ก็ได้)
- สิ่งที่ wordWrap
คืนกลับมาคือ Vector ที่เก็บ
string ต่างๆ
ที่แทนข้อความในแต่ละบรรทัด
ซึ่จะถูกนำไปแสดงบนจอภาพ
ด้วย code ข้างล่างนี้ (นักเรียนไม่ต้องเขียน
code ข้างล่างนี้
ที่แสดงให้ดูจะได้รู้ว่าตัว
applet ใช้ wordWrap อย่างไร)
public void paint( Graphics g ) {
g.setFont( new Font("Serif", Font.PLAIN, 12));
FontMetrics fm = g.getFontMetrics();
int fontHeight = fm.getAscent() - fm.getDescent();
Vector lines = Hw3.wordWrap( text, lineWidth, fm );
int curY = 20;
g.setColor( Color.black );
Enumeration enum = lines.elements();
while( enum.hasMoreElements() ) {
g.drawString((String)enum.nextElement(), 5, curY);
curY += fontHeight * 1.5;
}
}
|
download
- unzip แฟ้ม 427hw3.zip
ลงใน directory
ที่เก็บเฉพาะการบ้านนี้
จะพบแฟ้มต่างๆ ดังนี้
- Hw3.java (แฟ้มที่ต้องเขียน
method wordWrap
ของการบ้าครั้งนี้)
- hw3.jar (แฟ้มเก็บ
class สำคัญอื่นๆ ของ applet)
- hw3.htm (แฟ้มเอาไว้ดูผลการทำงานของ applet)
- hw3.pdf (เอกสารที่กำลังอ่านอยู่นี้แบบ pdf)
- แก้ไขแฟ้ม Hw3.java ด้วย editor อะไรก็ได้ (เช่น
notepad, edit plus, ...)
- compile ด้วย javac -classpath
.;hw3.jar Hw3.java
- สั่งทำงานด้วย
appletviewer hw3.htm
(หรือจะเปิด hw3.htm ด้วย web browser ก็ได้)
วิธีทดสอบ
กำหนดส่ง
- วันที่ 30 กรกฎาคม 2544
(แต่แนะนำว่าให้ทำให้เสร็จก่อนวันสอบกลางภาค)
สมชาย
ประสิทธิ์จูตระกูล
2110427 :
การวิเคราะห์และออกแบบอัลกอริทึม
|