Sunday, May 30, 2004

 

兩點間畫有箭頭的線

我project裡面的片段程式
不知道有沒有更好的作法~
//畫箭頭
double x1 = fromPoint.getX();
double y1 = fromPoint.getY();
double x2 = toPoint.getX();
double y2 = toPoint.getY();
double distance = fromPoint.distance(toPoint);

double cita = Math.toDegrees(Math.asin(Math.abs(y1 - y2) / distance));
double subCitaSin = ARROW_LENGTH * Math.sin(Math.toRadians(cita - 30));
double subCitaCos = ARROW_LENGTH * Math.cos(Math.toRadians(cita - 30));
double addCitaSin = ARROW_LENGTH * Math.sin(Math.toRadians(cita + 30));
double addCitaCos = ARROW_LENGTH * Math.cos(Math.toRadians(cita + 30));
double up1, down1, up2, down2;
if(x1 > x2){
   //箭頭在第二象限
   if(y1 > y2){
      up1 = x2 + subCitaCos;
      down1 = y2 + subCitaSin;
      up2 = x2 + addCitaCos;
      down2 = y2 + addCitaSin;
   }
   //箭頭在第三象限
   else{
      up1 = x2 + subCitaCos;
      down1 = y2 - subCitaSin;
      up2 = x2 + addCitaCos;
      down2 = y2 - addCitaSin;
   }
}
else{
   //箭頭在第一象限
   if(y1 > y2){
      up1 = x2 - subCitaCos;
      down1 = y2 + subCitaSin;
      up2 = x2 - addCitaCos;
      down2 = y2 + addCitaSin;
   }
   //箭頭在第四象限
   else{
      up1 = x2 - subCitaCos;
      down1 = y2 - subCitaSin;
      up2 = x2 - addCitaCos;
      down2 = y2 - addCitaSin;
   }
}
g2d.draw(new Line2D.Double(new Point2D.Double(up1, down1), toPoint));
g2d.draw(new Line2D.Double(new Point2D.Double(up2, down2), toPoint));

由 swanky 發表於 May 30, 2004 11:56 PM
迴響

剛好路過, 覺得您的做法太繁瑣...
多多利用平移,旋轉將會讓您輕鬆許多.
野人獻曝,請多包含.

Here is my example:


import javax.swing.*;
import java.awt.*;
import java.awt.geom.*;

/**
* @author T55555
* @version 1.0.0 2004-06-30
*/
public class DrawArrow extends JComponent {
public static void main(String[] args) {
JFrame f = new JFrame("DrawArrow ----- by T55555");
f.getContentPane().add(new DrawArrow());
f.setSize(275, 150);
f.setLocationRelativeTo(null);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}

public void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
double p = 10.0;
double q = 100.0;
double m = (p + q) / 2;

ciyawasay_drawArrow(g2d, new Point2D.Double(p, p), new Point2D.Double(q, q));
ciyawasay_drawArrow(g2d, new Point2D.Double(q, q), new Point2D.Double(p, p));
ciyawasay_drawArrow(g2d, new Point2D.Double(p, q), new Point2D.Double(q, p));
ciyawasay_drawArrow(g2d, new Point2D.Double(q, p), new Point2D.Double(p, q));
ciyawasay_drawArrow(g2d, new Point2D.Double(m, p), new Point2D.Double(m, q));
ciyawasay_drawArrow(g2d, new Point2D.Double(m, q), new Point2D.Double(m, p));
ciyawasay_drawArrow(g2d, new Point2D.Double(p, m), new Point2D.Double(q, m));
ciyawasay_drawArrow(g2d, new Point2D.Double(q, m), new Point2D.Double(p, m));

g2d.translate(150.0, 0.0);
t55555_drawArrow(g2d, new Point2D.Double(p, p), new Point2D.Double(q, q));
t55555_drawArrow(g2d, new Point2D.Double(q, q), new Point2D.Double(p, p));
t55555_drawArrow(g2d, new Point2D.Double(p, q), new Point2D.Double(q, p));
t55555_drawArrow(g2d, new Point2D.Double(q, p), new Point2D.Double(p, q));
t55555_drawArrow(g2d, new Point2D.Double(m, p), new Point2D.Double(m, q));
t55555_drawArrow(g2d, new Point2D.Double(m, q), new Point2D.Double(m, p));
t55555_drawArrow(g2d, new Point2D.Double(p, m), new Point2D.Double(q, m));
t55555_drawArrow(g2d, new Point2D.Double(q, m), new Point2D.Double(p, m));
g2d.translate(-150.0, 0.0);
}

public void ciyawasay_drawArrow(Graphics2D g2d, Point2D fromPoint, Point2D toPoint) {
double ARROW_LENGTH = 10.0;
double x1 = fromPoint.getX();
double y1 = fromPoint.getY();
double x2 = toPoint.getX();
double y2 = toPoint.getY();
double distance = fromPoint.distance(toPoint);

double cita = Math.toDegrees(Math.asin(Math.abs(y1 - y2) / distance));
double subCitaSin = ARROW_LENGTH * Math.sin(Math.toRadians(cita - 30));
double subCitaCos = ARROW_LENGTH * Math.cos(Math.toRadians(cita - 30));
double addCitaSin = ARROW_LENGTH * Math.sin(Math.toRadians(cita + 30));
double addCitaCos = ARROW_LENGTH * Math.cos(Math.toRadians(cita + 30));
double up1, down1, up2, down2;
if(x1 > x2){
if(y1 > y2){
up1 = x2 + subCitaCos;
down1 = y2 + subCitaSin;
up2 = x2 + addCitaCos;
down2 = y2 + addCitaSin;
}
else{
up1 = x2 + subCitaCos;
down1 = y2 - subCitaSin;
up2 = x2 + addCitaCos;
down2 = y2 - addCitaSin;
}
}
else{
if(y1 > y2){
up1 = x2 - subCitaCos;
down1 = y2 + subCitaSin;
up2 = x2 - addCitaCos;
down2 = y2 + addCitaSin;
}
else{
up1 = x2 - subCitaCos;
down1 = y2 - subCitaSin;
up2 = x2 - addCitaCos;
down2 = y2 - addCitaSin;
}
}
g2d.draw(new Line2D.Double(new Point2D.Double(up1, down1), toPoint));
g2d.draw(new Line2D.Double(new Point2D.Double(up2, down2), toPoint));
g2d.draw(new Line2D.Double(fromPoint, toPoint));
}

// Note: pre-condition: toPoint != fromPoint
// ( if the 2 points are the same ===> distance == 0 and angle is indeterminate )
public void t55555_drawArrow(Graphics2D g2d, Point2D fromPoint, Point2D toPoint) {
double ARROW_LENGTH = 10.0;
double ARROW_ANGLE = Math.toRadians(30);
double ax = ARROW_LENGTH * Math.cos(ARROW_ANGLE);
double ay = ARROW_LENGTH * Math.sin(ARROW_ANGLE);

AffineTransform originTransform = g2d.getTransform();
g2d.translate(toPoint.getX(), toPoint.getY());
g2d.rotate((fromPoint.getY() > toPoint.getY() ? -1 : 1) * Math.acos((toPoint.getX() - fromPoint.getX()) / fromPoint.distance(toPoint)));
g2d.draw(new Line2D.Double(0, 0, -ax, -ay));
g2d.draw(new Line2D.Double(0, 0, -ax, ay));
g2d.setTransform(originTransform);
g2d.draw(new Line2D.Double(fromPoint, toPoint));
}

}

The main idea is translate the origin to the toPoint,
and rotate to make the axe X parallel to the vector (fromPoint, toPoint).

For the rotate angle, the "classic" way is try to using atan like:

if (x1 > x2) {
g2d.rotate(Math.PI + Math.atan((y1 - y2) / (x1 - x2)));
} else if (x1 y2) {
g2d.rotate( -Math.PI / 2 );
} else if (y1 g2d.rotate( Math.PI / 2);
} else {
return;
}
As you can see, there are many checking to do.
The example I show you do not using the atan.
I am using vector dot product formula.
A . B = |A| |B| cos(theda)
with A = vector (fromPoint, toPoint),
B = (1, 0) (axe X, unit vector)

In case if you want fill the arrow, with
3rd point that can define by the distance from the toPoint, the method I used will even simpler(compare to yours).

Posted by: T55555 發表於 2004-06-30 10:27 PM

Oops, it seems the atan checking have trouble to layout...
(my post code is not the same as showing on the page, bug on the post text re-formating ?)

Anyway, I do not know how to layout to post it correctly. And this is real simple algebra formula.


Posted by: T55555 發表於 2004-06-30 10:49 PM

太感謝了~
您的方法真是比我的好很多~ ^^"

Posted by: swanky 發表於 2004-06-30 10:59 PM

 

把顏色"存"起來

最近做的專題中
為了讓設計者可以更改Concept的顏色
所以多了一個可以選擇顏色的功能

不過要怎麼把這個顏色很方便地從一般文字檔案中存取呢?

Color類別中可以找到答案喔~

存:
使用Color類別中的getRGB()方法取得型態為int的RGB值,再轉成字串
   Color color = Color.BLUE;
   String colorRGBText = "" + color.getRGB();


讀:
把RGB值丟給Color的建構子
   Color color = new Color(Integer.parseInt(colorRGBText));
由 swanky 發表於 May 30, 2004 12:58 PM

Wednesday, May 26, 2004

 

SOMEWHERE OUT THERE

很久以前的一部卡通--美國鼠譚
這是裡面我最愛的一首歌--SOMEWHERE OUT THERE
小時後看的 劇情已經忘的差不多了 但這首歌一直記得
不知道大家有沒有看過~

《歌詞中英對照》

SOMEWHERE OUT THERE
外面那裡的某一個地方
(Barry Mann, Cynthia Weil, and James Horner)

Somewhere out there beneath the pale moonlight
外面那裡的某一個地方 在那蒼白的月光下
Someone\'s thinking of me and loving me tonight
今晚有個人正在想念著我 愛著我
Somewhere out there someone\'s saying a prayer
外面那裡的某一個地方 有個人正在祈禱
That we\'ll find one another in that dream somewhere out there
但願我們會找到彼此 在外面某一個地方的美夢裡

And even though I know how very far apart we are
而即使我知道我們相隔多麼遙遠
It helps to think we might be wishin\' on the same bright star
想到我們或許\正在對著同一顆星星許\願 就可以讓我好過許\多
And when the night wind starts to sing a lonesome lullaby
而當夜風開始唱一首寂寞的搖籃曲
It helps to think we\'re sleeping underneath the same big sky
想到我們睡在同一片寬闊的天空下 就可以讓我好過許\多

Somewhere out there if love can see us through
外面那裡的某一個地方 如果愛可以讓我們堅強
Then we\'ll be together somewhere out there
那麼我們將會團聚 在外面那裡的某一個地方
Out where dreams come true
某一個夢想可以成真的地方

由 shumi 發表於 May 26, 2004 09:23 PM
迴響

能不能唱給我聽呢? ^^

Posted by: swanky 發表於 2004-05-26 11:59 PM

這部卡通不久前迪士尼有撥過
可能還會重播
我看ㄌ好幾遍

Posted by: albert 發表於 2004-09-04 03:09 PM

什么时候再听都是一首很好听很好听的歌,尤其是电影版的原曲。真的很感激一楼的shumi。Thank you!

Posted by: Pasu 發表於 2004-09-05 08:25 PM

我都好鍾意呢首歌~! 記得套卡通片係叫"老鼠也移民"~

Posted by: 招仔 發表於 2004-11-07 04:23 PM

我也喜欢这首歌,可是在哪里可以下载它的mp3呢?

Posted by: traycy 發表於 2005-03-21 12:50 PM

我也不知道呢~

Posted by: swanky 發表於 2005-03-21 06:54 PM

Monday, May 17, 2004

 

Sorts比較

比較各Sorts:
時間複雜度
in-place or not in-place
stable or unstable

《Sorts比較》

sorts.jpg

比較表 Time Complexity Space Complexity Stable/Unstable
Best Case Worst Case Average Case
Insertion Sort
O(n)
O(n2)
O(n2)
O(1)
Stable
Selection Sort
O(n2)
O(n2)
O(n2)
O(1)
Unstable
Bubble Sort
O(n)
O(n2)
O(n2)
O(1)
Stable
Shell Sort
O(n3/2)
O(n2)
O(n2)
O(1)
Unstable
Quick Sort
O(nlogn)
O(n2)
O(nlogn)
O(logn)~O(n)
Unstable
Merge Sort
O(nlogn)
O(nlogn)
O(nlogn)
O(n)
Stable
Heap Sort
O(nlogn)
O(nlogn)
O(nlogn)
O(1)
Unstable
LSD Radix Sort
O(d*(n+r))
O(n*r)
Stable

由 shumi 發表於 May 17, 2004 08:53 AM

 

Sorts總整理5--Bubble Sort

Bubble Sort的演算法和程式碼

《Bubble Sort》

Algorithm :
Bubblesort(A)
for i←1 to length[A]
   do for jlength[A] downto i+1
      do if A[j]<A[j-1]
         then exchange A[j]←→A[j-1]

java code:整數排序
void bubbleSort(int[] Array) {
   int temp;

   for (int i = 0; i < Array.length; i++) {
      for (int j = 0; j < (Array.length - i - 1); j++) {
         if (Array[j].score > Array[j + 1].score) {
            temp = Array[j].score;
            Array[j].score = Array[j + 1].score;
            Array[j + 1].score = temp;
         }
      }
   }
}
java code:字串排序
void bubbleSort(String[] Array) {
   String temp;

   for (int i = 0; i < Array.length; i++) {
      for (int j = 0; j < (Array.length - i - 1); j++) {
         if (Array[j].name.compareTo(Array[j + 1].name) > 0) {
            temp = Array[j].name;
            Array[j].name = Array[j + 1].name;
            Array[j + 1].name = temp;
         }
      }
   }
}
由 shumi 發表於 May 17, 2004 08:41 AM

 

Sorts總整理4--Quick Sort

Quick Sort的演算法和程式碼

《Quick Sort》

Algorithm :
Quicksort(A,p,r)
if p<r

   then qPartition(A,p,r)
      Quicksort(A,p,q-1)

   Quicksort(A,q+1,r)
Partition(A,p,r)
xA[r]
ip-1
for jp to r-1
   do if A[j]≦x

      then ii+1
         exchange A[i]←→A[j]
exchange A[i+1]←→A[r]

return i+1
java code:整數排序
void quickSort(int[] Array, int p, int r){
   if(p < r){
      int q = partition(Array, p, r);
      quickSort(Array, p, q - 1);
      quickSort(Array, q + 1, r);
   }
}

int partition(int[] Array, int p, int r){
   int x = Array[r];
   int i = p - 1;

   for(int j = p; j <= r - 1; j++){
      if(Array[j] <= x){
         i++;
         int t1 = Array[i]; Array[i] = Array[j];
         Array[j] = t1;
      }
   }
   int t2 = Array[i+1]; Array[i+1] = Array[r]; Array[r] = t2;
   return i + 1;
}
java code:字串排序
int partition(String[] Array, int p, int r) {
   String x = Array[r].name;
   int i = p - 1;

   for (int j = p; j <= (r - 1); j++) {
      if (Array[j].name.compareTo(x) <= 0) {
         i++;

         String t1 = Array[i].name;
         Array[i].name = Array[j].name;
         Array[j].name = t1;
      }
   }

   String t2 = Array[i + 1].name;
   Array[i + 1].name = Array[r].name;
   Array[r].name = t2;

   return i + 1;
}

void quickSort(String[] Array) {
   quickSort(Array,0,Array.length-1);
}

void quickSort(String[] Array, int p, int r) {
   if (p < r) {
      int q = partition(Array, p, r);
      quickSort(Array, p, q - 1);
      quickSort(Array, q + 1, r);
   }
}
由 shumi 發表於 May 17, 2004 08:28 AM

 

Sorts總整理3--Heap Sort

Heap Sort的演算法和程式碼

《Heap Sort》

Algorithm :
Parent(i)
return i/2
Left(i)
return 2i
Right(i)
return 2i+1

Max-Heapify(A,i)
lLeft(i)
rRight(i)

if lheap-size[A] and A[l]>A[i]
   then largestl

   else largesti
if rheap-size[A] and A[r]>A[largest]
   then largestr

if largesti
   then exchange A[i]←→A[largest]
      Max-Heapify(A,largest)

Build-Max-Heap(A)
heap-size[A]←length[A]
for ilength[A]/2 downto 1
   do Max-Heapify(A,i)

Heapsort(A)
Build-Max-Heap(A)
for ilength[A] downto 2
   do exchange A[1]←→A[i]
      heap-size[A]←heap-size[A]-1
   Max-Heapify(A,1)

java code:整數排序
int parent(int i){
   return (i - 1)/2;
}

int left(int i){
   return 2 * i + 1;
}

int right(int i){
   return 2 * i + 2;
}

void heapSort(int[] Array){
   buildMaxHeap( Array );
   for(int i = Array.length - 1; i >= 1; i--){
      int temp = Array[0]; Array[0] = Array[i]; Array[i] = temp;
      heapSize--;
      maxHeapify(Array, 0);
   }
}

void buildMaxHeap(int[] Array){
   heapSize = Array.length;
   for(int i = (int)( (Array.length/2) - 1 ); i >= 0; i--){
      maxHeapify(Array, i);
   }
}

void maxHeapify(int[] Array, int i){
   int L = left(i);
   int R = right(i);
   int largest;
   if( (L < heapSize) && (Array[L] > Array[i]) )
      largest = L;
   else
      largest = i;
   if( (R < heapSize) && (Array[R] > Array[largest]) )
      largest = R;
   if(largest != i){
      int temp = Array[i]; Array[i] = Array[largest];
      Array[largest] = temp;
      maxHeapify(Array, largest);
   }
}
java code:字串排序
int parent(int i){
   return (i - 1)/2;
}

int left(int i){
   return 2 * i + 1;
}

int right(int i){
   return 2 * i + 2;
}

void buildMaxHeap(String[] Array) {
   heapSize = Array.length;

   for (int i = (int) ((Array.length / 2) - 1); i >= 0; i--) {
      maxHeapify(Array, i);
   }
}

void maxHeapify(String[] Array, int i) {
   int L = left(i);
   int R = right(i);
   int largest;

   if ((L < heapSize) && (Array[L].name.compareTo(Array[i].name) > 0)) {
      largest = L;
   } else {
      largest = i;
   }

   if ((R < heapSize) && (Array[R].name.compareTo(Array[largest].name) > 0)) {
      largest = R;
   }

   if (largest != i) {
      String temp = Array[i].name;
      Array[i].name = Array[largest].name;
      Array[largest].name = temp;
      maxHeapify(Array, largest);
   }
}


void heapSort(String[] Array) {
   buildMaxHeap(Array);

   for (int i = Array.length - 1; i >= 1; i--) {
      String temp = Array[0].name;
      Array[0].name = Array[i].name;
      Array[i].name = temp;
      heapSize--;
      maxHeapify(Array, 0);
   }
}
由 shumi 發表於 May 17, 2004 12:23 AM

 

Sorts總整理2--Merge Sort

Merge Sort 的演算法和程式碼

《Merge Sort》

Algorithm :
Merge(A,p,q,r)
n1q-p+1

n2r-q
△cerate arrays L(1..n1+1) and R(1..n2+1)

for i←1 to n1
   do L[i]←A[p+i-1]

for j←1 to n2
   do R[j]←A[q+j]

L[n1+1]←∞
R[n2+1]←∞
i←1
j←1
for kp to r

   do if L[i]≦R[j]
      then A[k]←L[i]
         ii+1
      else A[k]←R[j]
         jj+1

Merge-Sort(A,p,r)
if p<r

   then q←└(p+r)/2┘
   Merge-Sort(A,p,q)
   Merge-Sort(A,q+1,r)
   Merge(A,p,q,r)

java code:整數排序
void mergeSort(int[] Array, int p, int r){
   if( p < r ){
      int q = ( p + r )/2;
      mergeSort(Array, p, q);
      mergeSort(Array, q + 1, r);
      merge(Array, p, q, r);
   }
}

void merge(int[] Array, int p, int q, int r){
   int n1 = q - p + 1;
   int n2 = r - q;
   int[] L = new int[n1 + 1], R = new int[n2 + 1];
   int i, j;
   for(i = 0; i < n1; i++){
      L[i] = Array[p + i];
   }
   for(j = 0; j < n2; j++){
      R[j] = Array[q + j + 1];
   }
   L[n1] = R[n2] = Integer.MAX_VALUE;
   i = j = 0;
   for(int k = p; k <= r; k++){
      if(L[i] <= R[j]){
         Array[k] = L[i];
         i++;
      }
      else{
         Array[k] = R[j];
         j++;
      }
   }
}
java code:字串排序
void mergeSort(String[] Array){
   mergeSort(Array,0,Array.length-1);
}

void mergeSort(String[] Array, int p, int r) {
   if (p < r) {
      int q = (p + r) / 2;
      mergeSort(Array, p, q);
      mergeSort(Array, q + 1, r);
      merge(Array, p, q, r);
   }
}
   
void merge(String[] Array, int p, int q, int r) {
   int n1 = q - p + 1;
   int n2 = r - q;
   String[] L = new String[n1 + 1];
   String[] R = new String[n2 + 1];
   int i;
   int j;

   for (i = 0; i < n1; i++) {
      L[i] = Array[p + i].name;
   }

   for (j = 0; j < n2; j++) {
      R[j] = Array[q + j + 1].name;
   }

   L[n1] = R[n2] = new String(new char[]{Character.MAX_VALUE});
   i = j = 0;

   for (int k = p; k <= r; k++) {
      if (L[i].compareTo(R[j])<= 0) {
         Array[k].name = L[i];
         i++;
      } else {
         Array[k].name = R[j];
         j++;
      }
   }
}
由 shumi 發表於 May 17, 2004 12:01 AM

Sunday, May 16, 2004

 

Sorts總整理1--Insertion Sort

雖然期中考過很久了
不過還是要把Sorts 整理整理
希望有需要的人也可以參考看看

《Insertion Sort》

Algorithm :
Insertion-Sort(A)
for j←2 for length[A]
   do keyA[j]
      △Insert A[j] into the sorted sequence A[1..j-1]

      ij-1
      while i>0 and A[i]>key
         do A[i+1]←A[i]
            ii-1
         A[i+1]←key

java code:整數排序
void insertionSort(int[] Array){
   for(int j = 1; j < Array.length; j++){
      int key = Array[j];
      int i = j - 1;
      while( (i >= 0) && (Array[i] > key) ){
         Array[i+1] = Array[i];
         i--;
      }
      Array[i+1] = key;
   }
}
java code:字串排序
void insertionSort(String[] Array) {
   for (int j = 1; j < Array.length; j++) {
      String key = Array[j].name;
      int i = j - 1;

      while ((i >= 0) && (Array[i].name.compareTo(key)> 0)) {
         Array[i + 1].name = Array[i].name;
         i--;
      }

      Array[i + 1].name = key;
   }
}
由 shumi 發表於 May 16, 2004 11:30 PM

Thursday, May 06, 2004

 

wiki?

聽過這個名詞已經很多次了
但我還是不知道它確切的功能是什麼
"好狗"查了一下資料~

网络交流方式介绍- Wikibooks

wiki可以定義為網上協作寫作系統,屬於“可寫web”的一種。wiki好比軟體發展中的cvs一樣,也屬於協作開發系統。在wiki中,每一頁都是可以編輯的。wiki比起論壇和新聞系統來,能提供效果更好的知識庫。
wikiwiki是夏威夷語“快速”的意思。在這裏指能快速編輯網頁並快速建立新網頁、快速建立鏈結。
在一般的網站上,網頁都是唯讀的,而wiki網頁不但能閱讀,而且能直接修改。能發揮網路互動的優勢,使wiki頁面總是鮮活的。wiki 網站不象一般網站那樣區分讀者和編者,每個讀者都可以作為編者,都可以是網站的主人,一個wiki網站上的內容常常是多個人共同的心血,每個人可以隨時加 入網站的建設。wiki能聚集很多人的智慧,而不是只展示幾個人的智慧。
wiki和論壇相比,論壇只能發消息,wiki不但能發消息,而且能把消息用超鏈結有效的組織起來。wiki還能使多個人共同編輯同一篇文章,使一個文章能像軟體一樣隨時間不斷完善。

wiki軟體需要具有的功能 由 swanky 發表於 May 6, 2004 12:13 PM
迴響

我也想做一ㄍ屬於自己ㄉblog...
要怎ㄇ起頭ㄋ??

Posted by: 梁心瑜 發表於 2004-05-12 11:41 AM

自己架一個比較麻煩
要架server、灌軟體
最難的是還要去維護

現在很多國內的BBS
像是

無名小站
telnet://wretch.twbbs.org/
http://www.wretch.twbbs.org/blog/

狂狷年少
telnet://kgbbs.net/
http://blog.kgbbs.net/

都可以在BBS上註冊後有免費的blog、相簿、留言版
可以去試試囉~ ^^

(妳會不會上BBS啊? @.@)

Posted by: swanky 發表於 2004-05-12 11:15 PM