2020年7月22日 星期三

用 APP Inventor 2 寫成手機遙控器(藍牙遙控車): squid v.5 大魷魚遙控器




我在國小課後社團任教,課程名稱是 "Maker 藍牙遙控車",顧名思義,除了教孩子們組裝車子之外,還需要一個手機程式,透過藍牙來遙控車子,這個APP是用APP Inventor 2寫成的,開啟APP之後,除了可以用畫面上的方向鍵來控制車子,也可以用"體感方式"來命令車子前進,後退,左轉和右轉, 把收機平放,前傾就是前進,後仰就是後退,左傾是左轉,右傾就是右轉,蠻好玩的。

按我下載APP


2020年6月14日 星期日

APP Inventor 記憶卡牌的手機遊戲

我用APP Inventor寫的手機遊戲,規則是有八組不同數字的牌各兩張(共16張牌),分別隨機放在不同的位置,遊戲開始前給玩家看3秒後蓋牌,玩家須把相同的牌選出來,如果選錯牌遊戲會凍結兩秒才可繼續選牌,如果選對牌可馬上繼續選牌。遊戲花費時間越少表示記憶能力越高超。我們家大姊最快4秒,歡迎大家來挑戰喔!
APP Inventor寫手機程式超簡單,想知道這個遊戲怎麼寫嗎?我可以教你喔! 想讓孩子學APP inventor的家長可以聯絡"大魷魚創客"喔! 網址:https://www.facebook.com/csquid.maker/


這個遊戲雖然規則簡單,但是很耐玩。



姊姊的最高紀錄截圖,只花了4秒鐘。

2020年5月4日 星期一

最簡單的圖片裁切和縮放方式

由於Facebook, IG, Line等社群媒體的盛行,遇到圖片編修的機率非常高,要嘛太大太小需要改變尺寸,要嘛比例不對需要裁減,當然有很多影像處理軟體和線上網站可用,但是各位知道你得電腦中就有一個不用花錢,小而美的工具軟體可用嗎?
那就是微軟的小畫家。

Q. 如何開啟小畫家?
A. 它在"開始" -> "Windows附屬應用程式" -> "小畫家"




Q. 如何裁切圖片?
A. 開啟小畫家之後,按檔案->開啟舊檔 選到你要的圖片,然後選擇圖中的選取,這個時候你就可以任意選取圖中的一個方形區域,作為裁切的標的。決定裁切的區域之後按裁切,然後就完成了,記得另存新檔或存檔

 裁切前的圖片

選取你要的區域


裁切之後的圖片




Q. 如何縮放圖片?
A. 開啟小畫家之後,選取你要的圖片,然後點選"調整大小",然後就可以依照需要進行大小的調整,調整方式有兩種輸入百分比像素,另外,系統預設是等比例縮放,如果你要長寬任意調整,就必須把"維持外觀比例"的選項取消。


"調整大小"的位置


縮放圖片時,要注意這三個選項,依需要選擇。

等比例縮小50%


非等比例縮放,會造成圖片變形,宜謹慎使用。





2020年5月1日 星期五

Arduino 循跡車程式

/**************************************************   
  Arduino 循跡車程式
  硬體: Arduino Uno + L298N + TCRT5000 + TT減速馬達
  原理是用TCRT5000感應模組(車頭左右各一個),
  當感應器偵測到黑色物體時會傳回1,否則會傳回0,
  據此我們可以判斷(左,右) =
  (0,0)時,車子剛好在黑線這上方,所以直行,
  (1,0)時,左邊已經壓線,所以要左轉,
  (0,1)時,右邊已經壓線,所以要右轉,
  (1,1)時,左右兩邊都已壓在黑線上,所以停止車子。
 
  注意!!!!!
  車子速度不可太快,否則一下子就會衝出線外,無法控制。

 
    大魷魚創客工作室 2020.4.4 
    https://www.facebook.com/groups/806191766461206/

***************************************************/

int R_TCRT_Pin = 2;  //右邊感應器連接在D2           
int L_TCRT_Pin = 12; //左邊感應器連接在D12                 

const int IN1 = 3;  //馬達控制板連接在D3, D5, D6, D9
const int IN2 = 5; 
const int IN3 = 6; 
const int IN4 = 9; 

void setup() {
  Serial.begin (9600);           
  pinMode(R_TCRT_Pin, INPUT); //把D2設成輸入模式       
  pinMode(L_TCRT_Pin, INPUT); //把D12設成輸入模式
}

void loop()
{
  int  R=0, L=0;   //存放左,右感應器狀態的變數,預設值給定為0
  byte speed = 128;
 
  R = digitalRead(R_TCRT_Pin); //讀取右邊感應器的狀態
  L = digitalRead(L_TCRT_Pin); //讀取左邊感應器的狀態
 
  if( R==0 && L==0 ) Forward(speed); // (白,白): 車子剛好在黑線正上方,所以直行。
  if( L==1 && R==0 ) Left(speed);    // (黑,白): 左邊已經壓線,所以要左轉。
  if( L==0 && R==1 ) Right(speed);   // (白,黑): 右邊已經壓線,所以要右轉。
  if( L==1 && R==1 ) Stop();         // (黑,黑): 左右兩邊都已壓在黑線上,所以停止車子。
}

void Forward(byte speed) /* 車子前進的函數 */     
{ analogWrite(IN1, 0);
  analogWrite(IN2, speed);
  analogWrite(IN3, speed);
  analogWrite(IN4, 0);
}

void Back(byte speed) /* 車子後退的函數 */       
{ analogWrite(IN1, speed);
  analogWrite(IN2, 0);
  analogWrite(IN3, 0);
  analogWrite(IN4, speed);
}
void Left(byte speed) /* 車子左轉的函數 */         
{ analogWrite(IN1, 0);
  analogWrite(IN2,speed);
  analogWrite(IN3, 0);
  analogWrite(IN4, speed);
 }

void Right(byte speed) /* 車子右轉的函數 */         
{ analogWrite(IN1, speed);
  analogWrite(IN2, 0);
  analogWrite(IN3, speed);
  analogWrite(IN4, 0);
}

void Stop() /* 車子停止的函數 */           
{ analogWrite(IN1, 0);
  analogWrite(IN2, 0);
  analogWrite(IN3, 0);
  analogWrite(IN4, 0);
}

2020年4月4日 星期六

把Python程式變有趣:情人的愛心 ( 附 Python 完整程式碼)





白色情人節剛過,應景一下,用Python寫一個程式,在二維座標上,使用三角函數計算出一個愛心的圖形,並用matplotlib畫出來。獻給天下有情人,不管是結婚了沒。

這個程式很簡單,上半部是兩個半圓,下半部則是用 acos()的函數來完成,幾行程式就可以完成一個漂亮的心型圖案,寫這類程式可以讓寫程式本身變得更有趣,也可以把它當成另類禮物,送給你的愛人,是不是很酷呢。以下就是完整程式碼:

import matplotlib.pyplot as plt
import numpy as np 

fig, ax = plt.subplots()
ax.set_aspect('equal')
plt.rcParams['font.sans-serif'] = ['Noto Sans CJK TC']

#plot part1 ( y >= 0 )
left = -2.0
right = 2.0
step = 0.0001
x = np.arange(left, right, step)
y = np.sqrt(1.0 - (np.abs(x) - 1.0)**2 )
ax.plot(x, y, color='#ff0000', linewidth = 10)

#plot part2 ( y < 0 )
y = np.arccos(1.0 - np.abs(x)) - np.pi
ax.plot(x, y, color='#9F0000', linewidth = 10)

ax.set(xlabel='x', ylabel='y', title='白色情人節快樂 ^_^')
ax.grid(color='b', linestyle='--', linewidth=1)
ax.legend(['y=sqrt(1-(|x|-1)^2)', 'y=acos(1-|x|)-PI'])

plt.show()

2020年2月4日 星期二

用Python寫經典遊戲"貪食蛇"(Snake Game),只要200行程式,真的! (附完整程式碼 Full Source code)

         
        今天花了點時間,用Python寫了一個小遊戲,貪食蛇(Snake),這個遊戲大家都玩過,規則也都很清楚:蛇會不斷前進,你要控制他的方向,吃了紅點就可以獲得分數,可是蛇也會跟著變長,千萬別讓蛇頭碰到自己的身體,不然就Game Over啦 !

        這個遊戲其實不難,我是用PyQt5的套件來實現我的視窗系統:先開視窗,產生20x20個Label,然後再用一個Queue來記錄蛇的位置,再來隨機放置紅點,使用一個timer來計時,每0.2秒觸發一次檢查程式並使蛇前進,寫出一個判斷是否碰觸到蛇身的函數,再穿插簡單的判斷,那整個程式就完成了。

不囉嗦,以下就是完整程式碼,請參考。如有任何問題,歡迎隨時跟我討論。

from PyQt5.QtWidgets import QWidget, QLabel
from PyQt5.QtCore import QTimer, Qt
import random

class Point:
    pass

bonus = Point()
GAME_ROW = 20
GAME_COL = 20
GRID_WIDTH = 20
GRID_HEIGHT = 20
SNAKE_INIT_ROW = 10
SNAKE_INIT_LEMGTH = 5
SNAKE_Q_LENGTH = GAME_ROW * GAME_COL + 100
SNAKE_COLOR =      "background-color:#ffffff;"
SNAKE_HEAD_COLOR = "background-color:#ffff00;"
BONUS_COLOR      = "background-color:#ff0000;"
BG_COLOR =         "background-color:#000000;"
snake_head = SNAKE_INIT_LEMGTH - 1 
snake_tail = 0
SNAKE_ADD_LENGTH = 5
snake_move = 1

class myWindow(QWidget):
    def __init__(self):
        super().__init__()
        
    def keyPressEvent(self, event):
        global snake_dir        
        if event.key() == Qt.Key_Up:
            if snake_dir != 2:
               snake_dir = 1
        
        if event.key() == Qt.Key_Down:
            if snake_dir != 1:
               snake_dir = 2
        
        if event.key() == Qt.Key_Left:
            if snake_dir != 4:
               snake_dir = 3
    
        if event.key() == Qt.Key_Right:
            if snake_dir != 3:
               snake_dir = 4
    
window = myWindow()

def inside_snake(mode, x, y):
    #print('inside_snake():')
    global snake_q, snake_head, snake_tail, SNAKE_Q_LENGTH
    s = snake_head 
    e = snake_tail    
    if mode == 1:
        if x == snake_q[s].x and y == snake_q[s].y:
            #print('inside_snake(1)')
            return True
            
    while True:
        s -= 1
        if s == -1:
            s = SNAKE_Q_LENGTH - 1
        if x == snake_q[s].x and y == snake_q[s].y:
            #print('inside_snake(0)')
            return True

        if s == e:
            break            

    return False

def new_bonus():
    global bonus, grids, GAME_COL, GAME_ROW, BONUS_COLOR
    while True:
        bonus.x = random.randint(0, GAME_COL-1)
        bonus.y = random.randint(0, GAME_ROW-1)
        if not inside_snake(1, bonus.x, bonus.y):
            break
    #print('new_bonus():', bonus.x, bonus.y) 
    grids[bonus.y][bonus.x].setStyleSheet(BONUS_COLOR)
   
def game_init():
    global GAME_ROW, GAME_COL, grids, BG_COLOR, SNAKE_INIT_LEMGTH, snake_q, snake_head, snake_tail, snake_dir, game_mode, snake_move, score
    for i in range(GAME_ROW):
        for j in range(GAME_COL):
            grids[i][j].setStyleSheet(BG_COLOR)    

    for i in range(SNAKE_INIT_LEMGTH):
        snake_q[i].y = SNAKE_INIT_ROW; 
        snake_q[i].x = i;
        grids[SNAKE_INIT_ROW][i].setStyleSheet(SNAKE_COLOR)        
    snake_head = SNAKE_INIT_LEMGTH - 1
    snake_tail = 0;
    grids[snake_q[snake_head].y][snake_q[snake_head].x].setStyleSheet(SNAKE_HEAD_COLOR)

    while True:
        snake_dir = random.randint(1, 4)
        if snake_dir != 3:
            break
    game_mode = 1 
    snake_move = 1 
    score = 0
    new_bonus()    
#---------------------------------  main program ----------------------------------------------
grids = []
for y in range(GAME_COL):
    g_row=[] #for 1 row only
    for x in range(GAME_ROW):
        g = QLabel(window)
        g.setStyleSheet(BG_COLOR) #set all grids with black color
        g.setFixedSize(GRID_WIDTH, GRID_HEIGHT)
        g.move(GRID_WIDTH*x, GRID_HEIGHT*y)
        g_row.append(g)        
    
    grids.append(g_row) #create 2-D array of grids

snake_q = []
for i in range(SNAKE_Q_LENGTH):
    p = Point()
    snake_q.append(p)
    
for i in range(SNAKE_INIT_LEMGTH):
    p = Point()
    p.y = SNAKE_INIT_ROW
    p.x = i
    snake_q[i] = p 
    grids[SNAKE_INIT_ROW][i].setStyleSheet(SNAKE_COLOR)                
grids[snake_q[snake_head].y][snake_q[snake_head].x].setStyleSheet(SNAKE_HEAD_COLOR)

while True:
    snake_dir = random.randint(1, 4)
    if snake_dir != 3:
        break
game_mode = 1
snake_move = 1 
score = 0
new_bonus()
timer = QTimer(window)  

def timer_tick():
    global snake_q, snake_head, SNAKE_Q_LENGTH, GAME_ROW, GAME_COL, timer, SNAKE_ADD_LENGTH, snake_move, score, snake_tail, BONUS_COLOR
    #print('snake_q len=', len(snake_q), 'snake_head=', snake_head)
    y = snake_q[snake_head].y
    x = snake_q[snake_head].x
    snake_head += 1
    if snake_head == SNAKE_Q_LENGTH:
        snake_head = 0    
    snake_q[snake_head].y = y 
    snake_q[snake_head].x = x

    if snake_dir == 1:
        snake_q[snake_head].y -= 1
        if snake_q[snake_head].y < 0:
            snake_q[snake_head].y = GAME_ROW - 1    

    if snake_dir == 2:
        snake_q[snake_head].y += 1
        if snake_q[snake_head].y >= GAME_ROW:
            snake_q[snake_head].y = 0    

    if snake_dir == 3:
        snake_q[snake_head].x -= 1
        if snake_q[snake_head].x < 0:
            snake_q[snake_head].x = GAME_COL - 1    

    if snake_dir == 4:
        snake_q[snake_head].x += 1
        if snake_q[snake_head].x >= GAME_COL:
            snake_q[snake_head].x = 0
     
    grids[snake_q[snake_head].y][snake_q[snake_head].x].setStyleSheet(SNAKE_HEAD_COLOR)
    grids[y][x].setStyleSheet(SNAKE_COLOR)        
    if inside_snake(1, bonus.x, bonus.y):
        new_bonus()
        snake_move += SNAKE_ADD_LENGTH
        score += 100     
        print('score=', score)

    if inside_snake(0, snake_q[snake_head].x, snake_q[snake_head].y):
        print('game over')
        timer.stop()        
        game_init()
        timer.start()
        return     

    if snake_move == 1:
        grids[snake_q[snake_tail].y][snake_q[snake_tail].x].setStyleSheet(BG_COLOR)
        snake_tail += 1
        if snake_tail == SNAKE_Q_LENGTH:
            snake_tail = 0
    else:
        snake_move -= 1
        
window.show()
timer.timeout.connect(timer_tick)
timer.start(200)


2019年7月28日 星期日

如何用 Python 程式計算專案原始碼 (source code) 的總行數(line count) ?

        常常,當我們埋頭開發一個程式專案時,隨著時間的推移,檔案不斷變多,行數不斷增加,到後來也只知道這個專案很大,但是,當有人問你整個專案究竟有幾行程式碼時,你就呆住了,究竟有幾行啊?或許你會說,打開每個檔案,看看最後一行的行號,然後再把每個檔案的行數加總就可以了,哇,聽起來很簡單啊,確實,當你的專案只有幾個檔案時,這不成問題,但是,當你的專案有幾十個檔案(或幾百個)時,那你就累了。

        事實上,不需要這麼累,用python寫一個計算專案程式大小的程式很簡單,幾行就可以搞定,而且可以一直使用下去,從此以後,當老闆或客戶問你專案程式碼總共有幾行時,你就不需支支吾吾,被這麼簡單的問題逼死了,哈哈哈。

以下就是完整程式碼:

import os
import operator

source_path = 'c:/my_project'   #放置你的專案的目錄
line_count = 0
name_size = {}

#get all files in source path
os.chdir(source_path)
for _root, _dir, _files in os.walk(os.getcwd()):
    print('\n'+_root)
    for f in _files:
        try:
            f_type = f.split('.')[1]
            if  f_type in ['c', 's', 'h']:
                print('  '+f, end='')
                file = open(_root+'/'+f, 'r')
                c = 0
                for line in file:
                    #print(line)
                    c += 1
                    line_count += 1
                file.close()
                name_size[f] = c
                print(' ('+str(c)+')')
        except:
            pass

print('\n\n\ntotal lines =', line_count)

''' 如果你要看檔案大小排名,就打開以下程式碼
result_dic = sorted(name_size.items(), key=operator.itemgetter(1), reverse=True)    
for x in result_dic:
    print(x)
'''

2018年11月2日 星期五

科幻推理小說 "最後理論(Final Theory)" 馬克‧艾伯特著 讀後心得

前幾天在高雄的茉莉二手書店買的小說"最後理論",本來是沒有特別感興趣的,但是翻了幾頁之後,沒想到是出奇的好看...強力推薦。

這本小說結合推理、科幻、驚悚,是馬克‧艾伯特(Mark Alpert)的第一本小說著作,出版之時得到各方的讚譽,被認為是科幻版本的達文西密碼。以愛因斯坦的統一場論作為主軸,就結合部分史實,亦真亦假的情節,很容易讓人融入其中,作者本身有深厚的物理學基礎,所以解釋量子物理的時候,很具說服力,也加深這本小說的知識深度。另外,絕無冷場的鋪陳和流暢的文筆,也是一隻抓住讀者不放,強而有力的魔手。

傳說愛因斯坦去世之前,發現了超級理論,以這個理論可以發展出比核彈更具威力的武器,足以毀天滅地,但是愛因斯坦並沒有發表,而是將它隱藏起來,於是各方人馬,包括美國FBI、不知名的大亨、俄國人等,都想得到這些理論。主角大衛是個物理學逃兵,現任歷史學教授,但是因緣巧合之下,被扯進了這個爭奪戰之中,一路上不僅要逃避各方追殺,還要用恩師臨死前給予的片段線索,找出並拼湊出整個"最後理論",他辦得到嗎?

2018年6月29日 星期五

【布蘭登‧山德森精選集:皇帝魂】The Emperor's Soul 讀後心得

      【布蘭登‧山德森精選集:皇帝魂】The Emperor's Soul 是〝山神〞於2013年,唯一授權台灣的精選集,整本書由五個故事構成:皇帝魂、軍團、第十一種金屬、長嫡、保衛幸福之地,其中【皇帝魂】更奪得2013年,第71屆雨果獎最佳中長篇小說的殊榮。我個人非常喜歡這本精選集,這本書也是我成為山德森讀者開始,同時,也開啟我去追【迷霧之子】和【破戰者】之路,我私自認為,這本精選集名氣雖沒山神其他著作來得響亮,可在我心目中卻是一本經典之作,不想花太多時間,又想領略山神說故事功力的讀者,這絕對是一個最佳選擇。


【皇帝魂】
這個短篇故事,據說是山德森遊歷了台灣的故宮博物院之後,發現很多畫作上都蓋有歷代收藏者的印章,他認為這是一種很特殊的文化,詢問並了解其用意之後,給了他寫作上的靈感,於是就創作出這一個極富東方色彩的故事,魂印和仿術,構築了故事中的奇幻世界,王珊露是帝國中仿術出神入化的仿師,卻因仿畫而入獄,此時帝國統治者因遭刺殺而身亡,為維護帝國穩定,議政大臣們想出讓珊露運用本身高超的仿術仿造一個看不出破綻的帝王,珊露既要完成任務,又要全身而退,她需要把握時間並且想出縝密的計畫,否則,不管完成與否,都只有死路一條‧‧‧‧‧‧最後靠著事先的準備,還有貴人相助,他終於造出另一個皇帝,並逃出皇宮,歸隱山林。

這像不像人生的縮影啊?!在群魔亂舞的職場,工作做不好,會死得很慘,工作做得好,死得更慘,唯一的生存之道是綜觀全局,幫自己預留後路,切莫含著眼淚帶著微笑,無語問蒼天地壯烈犧牲。雖然偶爾也會遇到仙人指路,得貴人幫忙,在渾沌魔域中找到通往光明之路,但是要知道,這也是平日廣結善緣、誠懇待人的結果,還有自身實力更為重要,當遇到要突圍的決戰時刻,這可是最後武器,能殲敵致勝或是被就地正法,就看自己的功夫了。


【軍團】
男主角史蒂芬是一個患有多重人格症的人,常常處於一人分飾多角的情境,可能有保鏢、分析師、語言學家,有時還會出現科學家,他自己也知道這種情況,奇妙的是,他可以利用這些幻想中的角色解決很多困難的問題,也因此被視為有特功能的人,某日,他接到委託要尋找一個可能改寫人類歷史的發明,一台可以拍出過去歷史照片的相機,但是發明人跑到耶路撒冷,一路抽絲剝繭,後面居然有個大陰謀,恐怖份子想利用這台相機,證明耶穌復活是假的,進而造成混亂,沒想到相機卻已經故障,需要修復,史蒂芬在和恐怖份子周旋之際,趁亂殺死了一幫匪徒,逃出死亡陰影的史蒂芬,正好找到他的科學家分身,想著接下來該如何修好這架神奇的照相機~~~

故事中的神奇相機,代表的是一種超凡的能力,當人們有這樣的能力時,會做好事還是壞事?就算是大家眼中的好人拿到之後,會否因一己之私,人也跟著腐化了呢?很難講,所以,當一個巨大的能量或能力被發現時,真的需要被善加控管和運用,否則,必然會是一個天大的災難,甚至是世界的毀滅,不可不慎。


【第十一種金屬】
看過《迷霧之子》的讀者都知道,凱西爾是發動革命,推翻最後帝國的靈魂人物,這則短篇小說,補充了凱西爾師從何人,和如何戰勝對手並得知第十一種金屬,但更重要的是,在這個過程中,凱西爾決心要打敗不死帝王『統御主』,並且解放被奴役的社會下層『司卡』。

凱西爾在迷霧之子裡,是個個性活潑、睿智、幽默、充滿正義感的領袖人物,曾經經歷巨大苦難,內心復仇的意志堅決,甚至於在必要時刻,犧牲自己以成就大局,這樣的人,在現實世界很難遇到,如果你的老闆是個這樣的人,代表你三生有幸,跟緊點,他是個會成就大事業的人,更重要的是,他會善待你。

【長嫡】
丹尼森是星際帝國積極培養的指揮官,但是他對指揮艦隊根本就不再行,縱使如此,在一連串的指揮失誤之後,上級仍持續給予機會,對他寄予厚望,原因只有一個,他是橫掃千軍、戰無不勝且即將征服帝國的艦隊指揮官法瑞恩的複製人。最後戰役中,丹尼森面對史上最強的戰神,雖然全無勝算且屢戰屢敗,但他利用了一次通訊上的欺敵,讓法瑞恩以為自己大勢已去,最後選擇舉槍自盡,終於完成了不可能的任務。

人總是執著於自己的強項,面對失誤,很難即時面對現實並積極調整,此時信心一旦潰敗,就很難挽救敗局,法瑞恩當時如果願意再等待一段時間,再釐清真相,就不會被自己的自尊所害,另一個角度來看,丹尼斯雖然一路挫敗,卻在關鍵時刻發現通訊網路有可趁之機,進而以一招瞞天過海,反敗為勝,這證明了,不到最後關頭,勝負難料呀。

【保衛幸福之地】
傑森是個身懷絕技的盲人探員,為一家電話公司工作,這家電話公司壟斷了和所有外星人的溝通的管道。為了調查一個女子因身體被外星種族入侵,而來到這個太空站,在危機四伏的調查行動中,傑森慘遭禁錮,後來想辦法擊敗對手並脫困,答案逐漸明朗,傑森原本信任的外星種族,其實私底下卻是會打擊反對份子,造成這些反對份子以激進手段破壞星際和平,於是,傑森為了消弭對立,決定把新技術《超光速旅行》公諸於世。

我們通常對於習以為常的事情不加懷疑,但是真相有的時候卻是和我們的認知背道而馳,嘗試了解真相,並且小心求證,否則在我們大夢初醒之時,不曉得已經錯了多久,另外,保持開放的心胸也很重要,堅持本位主義,只是讓所有的人和你針鋒相對,這絕不是一件好事。

2018年6月26日 星期二

奇幻小說【破戰者 Warbreaker 】(Brandon Sanderson 布蘭登‧山德森著) 讀後感

        破戰者(Warbreaker)是布蘭登‧山德森(Brandon Sanderson )的著作,這部小說維持著"山神"的一貫寫作風格,充滿想像力的奇幻色彩,除了緊張懸疑之外,最後的結局也完全超出讀者的預料,七百多頁的分量,比起山神其他大部頭的作品,算是分量適中,閱讀的時候,不會有遙遙無期的壓迫感,很適合一般或剛起步的讀者來閱讀。


        故事發生在兩個處於關係緊張的國家:哈蘭隼和義卓司,這兩個國家其實是有很深的淵源,甚至於有血緣關係,但是基於不同的宗教和政治理念,演變成截然不同的國家。義卓司有單一王室和國王,人民生性保守,信奉奧斯太神,人民基於教義習於單調灰暗的色彩,而哈蘭隼則是色彩豐富,不只有政教合一的政府,還有半人半神的領袖"神君",神君底下領有"眾神"(復歸者:因經歷特殊事績,死而復生的人),人民喜歡多彩的事物,經濟和國力也最為強大。義卓司國王為了二十年前和哈蘭隼訂的協議,必須把自己的女兒許配給哈蘭隼當今的神君當皇后,否則可能招來兵戎相見,而國王在最後一刻,放棄訓練已久且內定的大公主,而改派個性活潑不羈的小公主,作為和親的人選,於是故事於焉展開,小公主因為面臨宮廷的政治鬥爭,和面對神魔一般的丈夫,陷入生存危機,而大公主為了要營救自己的妹妹,和同伴潛入哈蘭隼,準備一系列推翻哈蘭隼的行動,卻因涉世未深遭到利用,後來更歷經悲慘的乞丐生涯,所幸遇到沉默寡言,特立獨行的絕世高手法榭所救,接著出生入死的冒險,讓故事高潮迭起,令人目不暇給。

         故事當中以顏色和人體彩習為基礎,駐氣 (像是武俠小說裡的【氣】)則是決定法力的高低,駐氣可以傳遞至沒有生命的物體,並令其作動,除此之外,還可以將駐氣傳給他人,累積夠多的駐氣,可以發揮無與倫比的力量,幾乎可以控制所有物體,像是故事接近尾聲時的神君,簡直達到了橫掃千軍的驚人法力,另外,故事中對於宗教的探討,也有所著墨,像是魯莽王萊聲,身為眾神之一,卻也同時質疑自己是否有當神的資格,甚至不想別人把自己當作神,雖然如此,他卻在緊要時刻,大無畏的犧牲自我,發揮十足的神性,還有,大公主維溫娜原本對自身宗教的堅持,鄙視哈蘭隼多神多彩的教義,到後來接觸並接受,這個過程讓讀者在思考宗教平等的議題上,也給予了很大的思考空間。

         小公主希麗嫁入哈蘭隼宮中之後,從本來的懼怕憎恨,到後來嘗試溝通,進而瞭解神君本身也是個遭禁錮的可憐人,在相處過程當中,神君展現了真誠和赤子之心,希麗因此愛上這個原本遭到誤解的魔神,所以後來除了要積極地突圍脫困,還要尋求解救自己愛人的方法,即使萬分凶險,也挺身面對,這樣為了愛人而不惜犧牲自己的女人,是不是十分令人動容呢?

        整個故事當中,還有許多亮點,包括萊聲和眾神的詼諧談話,丹司的絕妙騙術,法榭的識喚術,還有宵血劍亦正亦邪的行徑等,都等著帶領讀者進入這個豐富多彩又引人入勝的奇幻世界。
       

2017年11月27日 星期一

用C# 寫小遊戲: 模擬重力及封閉環境的物體運動 完整程式碼 (Full Source Code)

這個小遊戲模擬一個小方塊在封閉環境中的運動情況,考慮了初速度,重力加速度,反彈,摩擦力等物理特性,所以看起來更為真實。(在視窗中任一點按下滑鼠,方塊會以特定初速,沿著特定方向運動)



2017年11月21日 星期二

用C# 寫經典遊戲: 記憶卡牌遊戲(Memory Game) 完整程式碼 (Full Source Code)

記憶卡牌遊戲(Memory Game) 是規則簡單,又容易撰寫的小程式,大人小孩都愛玩。
(程式中用到的圖形版權屬於動畫電影:Strange Magic 仲夏夜魔法,由迪士尼公司旗下的盧卡斯電影製作)。



2017年11月13日 星期一

用C# 寫經典遊戲: TETRIS 俄羅斯方塊(魔術方塊) 完整程式碼 (Full Source Code)

       
        用C#寫出經典遊戲:俄羅方塊(又名魔術方塊,TETRIS)?乍聽之下,好想頗複雜,但是實際上,你只要會幾個簡單的語法,就可以順利的把它實做出來。


 
先來看看執行的情況 !!!



  如果你真的很有興趣,想要自己動手做,那麼就 ...
下載完整程式碼 (download full source code)

2017年9月14日 星期四

蘇黎士投機定律 (The Zurich Axioms by Max Gunther) 讀書筆記

1. 憂慮不是心理疾病,而是健康的徵兆。如果你不擔憂,那就是你冒的險不夠。
     1-1. 始終要下有意義的賭注。
     1-2. 避免過份分散風險。

2. 盡早獲利了結。   
    2-1. 預先決定投機賺多少,目標達成後,立即獲利了結。

3. 船開始下沉時,不要禱告,趕快脫身。
   3-1. 欣然接受小損失,儘管歷經多次失敗,但要設法一次扳回來。

4. 人類的行為根本不能預測,不要相信任何未卜先知。

5. 出現條理之前的混論並不危險。
    5-1. 當心歷史會重演的心理陷阱。
    5-2. 謹防圖表分析的幻覺。
    5-3. 勿輕易論斷因果關係。
    5-4. 勿犯賭徒的荒謬心理。

6. 避免紮跟,它妨礙靈活性。
    6-1. 不要因為意氣或念舊,而駐足於已經沒有希望的投資活動。
    6-2. 如果要更吸引人的機會橫在前面,要毫不遲疑脫開原來的樊籠。

7. 可以解釋的預感或直覺是值得信賴的。
    7-1. 絕對不要把希望和預感混為一談。

8. 上帝創造世界的計畫中,未必包括使你發財。
    8-1. 占星術要是靈的話,占星學家早都發了。
    8-2. 不要過度迷信,如果你能淡然處之,也可以享受到一些樂趣。

9. 預期最佳況會發生就是樂觀,信心則是知道如和處理最壞情況,決不要因為樂觀而採取投       機活動。

10. 請藐視多數人的意見,因為他們可能是錯的。
      10-1. 不要追逐風潮。沒有人進場的時候,往往就是買進的時機。

11. 如果第一次沒賺到錢,忘掉他,重新再來。
      11-1. 決不要用向下承接的攤平法,挽救沒有希望的投機。

12. 長期計畫引起的危機是,它讓你認為未來是可以控制的,永遠不要為自己或讓別人為你制        定長期計畫。
       12-1. 避開長期計畫。

2017年5月12日 星期五

科幻小說"三體(The Three-Body Problem)" (劉慈欣 著,2015年雨果獎得主) 讀書心得

     


      "三體" 這本小說的作者,是大陸最炙手可熱的科幻作家-劉慈欣,本書榮獲2014年『星雲獎』提名,並於2015年獲得『雨果獎』最佳長篇小說的殊榮,也是華人圈第一次得到這個榮譽,"三體"被前美國總統歐巴馬,臉書創辦人祖克柏列為閱讀書單,除此之外,版權還被美國好萊塢買下,準備拍成電影。

        本小說的書名"三體",源自於書中外星人的故鄉"半人馬座alpha星系",一個三合星系,也就是由三個恆星構成的系統,而擁有高度科技文明的的外星人,就居住在這星系中的一個行星,雖然已經擁有極其高度的文明,卻被不穩定的生存條件所困擾,氣候有時溫度極為溫和(只有一個太陽),有時卻是黑暗冰凍(沒有太陽)和猛爆烈焰(兩個或三個太陽),歷經幾百次幾乎慘遭毀滅的輪迴之後,外星人決定離開如此惡劣的環境,移往一個氣候穩定的星球,而這個時候,從一個遠達4.2光年外的太陽系行星,傳來有文明存在的信號,又得知該行星的氣候非常溫和且穩定,這個個行星就是人類居住的地球...當外星人收到這樣的信號,會有什麼樣的反應呢? 和地球人交朋友?還是毀滅地球人呢?

          三體女主角"葉文潔",經歷過文化大革命,其父慘死於紅衛兵的批鬥,之後遭流放並輾轉進到中國當時名為"紅岸"的祕密機構,因一次機會,他利用機構內的超大型發射器,以太陽為放大器,對全宇宙進行廣播,八年多以後,獲得了外星人的回應,由時間來推算,這極有可能是從半人馬座alpha星系裡的外星文明所傳來,但是首先接收到訊號的外星人卻警告葉文潔不要再次傳遞訊號,更不能告知其他外星文明地球的所在位置,否則很可能會遭致毀滅的命運,而在葉文潔經歷過一連串無情的打擊,對人性徹底失望之際,她決定不再留戀整個人類社會,於是和其黨羽繼續和外星人聯繫並提供情報,而外星人在了解人類的狀況後,憑其高超的科技,傳送了僅有質子大小的智慧微機械:智子,對人類科技進行封鎖和監控其所有活動,同時也派出龐大的星際艦隊以光速的百分之一速度,朝地球進行侵略行動,當然,地球人不可能坐以待斃,據估算,外星人到達地球,還需420年的時間,於是整個地球世界都動員起來,進行跨國合作,期望能找到有效的辦法,以抵禦外星人的入侵‧‧‧

2016年12月10日 星期六

股市各項指標及其計算方式

1. K 線: 分為陽線、陰線、中立線三種,以日K為例,當該日收盤價大於開盤價,則為陽線,反之則為陰線,若開盤價等於收盤價,就是中立線。陽線和陰線分為實體和影線,實體是開盤和收盤價的價差,上影線則是最高價和實體上緣的價差,下影線是最低價和實體下緣的價差。另外,常見的K線5分K,10分K,30分K,週K,月K等,道理一樣,皆是取該時段 "開始","結束","最高"和"最低" 繪製而成。



2. 移動平均線 MA(Moving Average, MA,又稱"均線"):
 
     a) 簡單移動平均線(Simple Moving Average): n日均線即表示是最近n日價格的算術平均值:
         SMAn = (P(1)+P(2)+...+P(n))/n
         假使某日的n日SMA 為 SMA(t0, n) 則次日的n日SMA為
         SMA(t1,n) = SMA(t0,n)- P(1)/n + P(n+1)/n
   
      b) 指數移動平均值(exponential Moving Average, EMA o EWMA)
          a=2/(N+1),  若N=19, a=0.1
          S(t)= a*Y(t) + (1-a)*S(t-1)
         
 
3. 隨機指標(Stochastic Oscillator, KD指標):
     RSV (Raw Stochastic Value: 未成熟隨機值)
     RSV = (Cn-Ln)/(Hn-Ln) * 100%
     (n 為交易期間,一般定為9日,Cn為第n日之收盤價,Ln為n日內最低價,Hn為n日內最高價)
 
      K(n) = a*RSV + (1-a)*K(n-1)
      D(n) = a*Kn    + (1-a)*D(n-1)
      (a 一般定為 1/3, 若無前一日K,D值,則以50%代替)

      K值為靈敏平均值,D值為遲鈍平均值,若K>D則表示處於漲勢,否則就是跌勢,K、D值介於0%~100%之間,80%以上為買超區(多頭趨勢),20%以下為賣超區(空頭趨勢)。

4.乖離率(Bias Ration, BIAS):
   nBias = (Close -MAn)/MAn * 100%

   nBias: n日乖離率
  Close: 當日收盤價
  MAn: n日移動平均價,n 一般定為3日和6日

 5.威廉指標(Williams %R):
    W%R = (Hn-Cn)/(Hn-Ln)

    n: 交易期間,一般定為14日
    Cn: 最新收盤價
    Hn: n日內最高價
    Ln: n日內最低價






2016年7月25日 星期一

畢氏定理證明(幾何數學)~~~

        相信大家對畢氏定理都不陌生,也都知道任意直角三角形中:"斜邊平方=其餘兩邊的平方和",但是你知道為什麼會這樣嗎?
         
         這個定理對我來說是再熟悉不過了,但是有一天我女兒問我如何證明時,我也花了一些時間才找出答案,如果你也有興趣,那就先不要看答案,自己先試試看。

        我常跟我女兒說,解數學題目的樂趣在於"解不出來",如果一下子就看出答案的話,那就一點意思都沒有了~~~呵呵。

        如果你已經試過一段時間了˙(不管是否找出答案),那就來看看我的方法,當然啦,方法不只一種,"不管是黑貓還是白貓,只要抓得到老鼠的貓就是好貓",可以解出問題的解法,就是好方法。


ABC為直角三角形,想當然爾,c^2=a^2+b^2,但是如何證明呢?

以AC為一邊長,做一個正方形AEDC,再以BC和BA延長線為兩邊做一個正方形BFHG(使GH通過D,HF通過E),OK,此時你可以看出三角形BAC=三角形AEF=三角形HDE=三角形GCD(因為其斜邊都相等,而且三個角也相等)。那麼
                             
正方形AEDC(紅框)的面積=正方形BFHG(綠框)-4個三角形面積

所以,c^2 = (a+b)^2 - 4*(a*b/2)
化簡    c^2 = a^2+b^2+2ab - 2ab 
 最後   c^2 = a^2+b^2
證明完畢! 夠簡單吧~~~~~

曾經聽過一首打油詩: "人生幾何又幾何,學了幾何又幾何? 幾何學了幾何用? 不學幾何奈我何?"  哈哈哈~蠻好玩的,其實數學沒想像中困難啦,只要肯花點時間了解,其實也可以找出其中樂趣的。

2016年7月20日 星期三

漫談數學動動腦

漫談數學動動腦
最近通訊軟體line流行貼出數學題目,讓大家動動腦筋:

動腦時間
 1  1  1 = 6
 2  2  2 = 6
 3  3  3 = 6
 4  4  4 = 6
 5  5  5 = 6
 6  6  6 = 6
 7  7  7 = 6
 8  8  8 = 6
 9  9  9 = 6
請加入運算符號,但不能加任何數字,以使等號成立。

然後有人解出一組答案如下:


當然,也有其他的答案,
例如4 4+4-√4=6 
例如6 6-6+6=6 
例如9√9×√9-√9=6 

其中應該是8最難,使用到立方根,但這是不合規則的。
這種遊戲題目只能加符號,不能加數字。立方根有用到3就不行。

是,有一位對數學很有興趣的高手想到了8的另一解法,用對數、對數哦!!!

(log8/log(log8/log√8))!

看得懂嗎 ? 解給你看:


然後,加上階層後  3!=3*2*1= 6

神解答呀! Orz......

2016年6月28日 星期二

LabVIEW: 聲音頻率分析

這個練習輸入一個聲音檔案,並做頻率分析。


執行結果
Block diagram



2016年6月21日 星期二

LabVIEW: 簡易秀圖程式(JPG)

這個程式可以選取系統中的JPG 檔案,並且秀在螢幕上:只要簡單幾個元件就可以達成,非常簡單。


執行結果


Block Diagram



LabVIEW: 用 Event Structure 畫出滑鼠軌跡(加強版)

延續 "LabVIEW: 用 Event Structure 畫出滑鼠軌跡"練習,
改成 "按下滑鼠左鍵拖曳,才畫出軌跡,按右鍵清除軌跡"。


執行結果

Block Diagram






2016年6月20日 星期一

LabVIEW: 用 Event Structure 畫出滑鼠軌跡

這個練習使用Event structure偵測並擷取滑鼠位置的座標,並且即時畫到XY Graph上。

Block Diagram


記得Timeout裡面,以要把資料連接起來


人機介面

LabVIEW: XY Graph + Formula Node 製作 愛心圖形

這個練習用XY Graph 和 Formula Node繪製愛心圖形。本程式使用兩段函式繪成:

y=sqrt(1-pow((abs(x)-1), 2));

y=acos(1-abs(x))-3.1415926;

我在[-2,2]區間取用401個點(頭尾都要),先畫上半部,再畫下半部。




執行結果


Block Diagram



2016年5月30日 星期一

LabVIEW: 聲音擷取+頻譜分析

   這個練習非常簡單: 從麥克風讀取一秒鐘的資料,然後輸出至圖表,並作頻譜分析。




人機介面&執行結果



Block digram



Acquire Sound的設定




Spectral Measurements的設定

2016年5月29日 星期日

Arduino + Labview: LM35溫度感測器,即時溫度監控

    利用Arduino開發板上的類比輸入,讀取溫度感測IC上的值,轉成實際溫度然後透過Serial port傳輸至電腦,而電腦這端則是利用LabView來接收,並做適當轉換後以圖表作為監控介面。

實驗結果:




     Arduino這邊的程式很簡單,先初始化serial port,然後再經由A0讀入LM35的感測值,要注意這個感測值是10位元(bits),根據LM35的datasheet得之,正確溫度的計算方式是每10mV(0.01V)增加一度C,也就是說0V代表0度C,0.1 V(10*0.01V)代表10度C,以此類推。因為每次讀回10bit的資料 n,我們要將n換成電壓值: (5V/1024)*n ,又每10mv 增加一度,所以實際溫度=(5V/1024)*n/10mV = (500/1024)*n

     算出實際溫度之後,利用Serial.print()函數將資料輸出至Serial port傳輸至電腦(我的系統是COM6),此時的資料是字串型式(每筆資料都是整數兩位數,小數兩位數,加上小數點共五個字元, EX:  28.93)。

void setup() 
{
  Serial.begin(9600); 
}

void loop()
{
  float x;
  int n;
  n = analogRead(0);
  x = 500.0 * n /1024.0;
  Serial.print(x, 2); 
  delay(500);
}

再來是電腦這邊的Labview程式,

Labview的Block diagram

Labview的人機介面


2016年5月3日 星期二

LabVIEW: 用手機透過網路,監控電腦的 Labview 程式

          如何用手機透過網路來監控遠端的Labview程式呢? 首先你必須先在電腦上寫一個Labview程式,然後宣告一個 shared variable並公開出來,然後在手機裝上data dashboard的app,再用這個app的indicator連上電腦的shared variable就可以了,概念其實很簡單,以下就是詳細步驟:


開一個專案,並且在專案中New一個 Variable


我New一個Variable,並命名為v1


記得要先存檔

存完檔之後再用滑鼠拖曳至你的程式中

我想把這個shared variable(v1)當成輸出,所以記得在v1上按滑鼠右鍵,再選擇Access Mode中的Write屬性


最後將程式執行起來,這個程式很簡單,就是用亂數產生數值再乘以10之後,再送往v1


手機端需要一個app,請先用google play搜尋 "data dashboard for labview",沒錯,就是最上面那一個,安裝她吧!


安裝完之後,執行這個app,會進入這個畫面,按中間那個"+Add"


再點選"Connect to shared variable..."


輸入Labview程式所在的電腦 ip address之後,按"Connect..."


Connect完成,手機螢幕會秀出可以連結的share variables,點選v1


系統顯示出V1為數值變數


接下來選擇indicator,我選右上角那個指針式的顯示器


數值範圍設定為0.0~10.0


顯示器出現後,點選右上角的"Run",進行動態連結~~~



執行結果!!!! ~~~~~~~是不是很酷呢?