2025年3月25日 星期二

MultiPlot

set multiplot layout 2,1 rowsfirst #上下兩張圖 先橫再直 set multiplot layout 2,1 columnsfirst #上下兩張圖 先直再橫 set multiplot layout 1,2 rowsfirst #左右兩張圖 set multiplot layout 2,3 title "Multi 6 Plot" 多個獨立視窗 # 第一張圖 set term qt 0 plot sin(x) # 第二張圖 set term qt 1 plot cos(x)

2025年2月20日 星期四

計算table裡面的最大值 最小值 平均值

#!/usr/bin/perl use strict; use warnings; #檔案路徑 (請自行修改成正確路徑) my $filename = $ARGV[0]; my @numbers; #檢查檔案是否存在 unless (-e $filename) { die "檔案 $filename 不存在! \n"; } #讀取檔案內容 open (DATA, "<$filename"); while (){ chop $_; $_ =~ s/[",\\();a-zA-Z]//g; print "$ \n"; my @ary=split(" ",$_); push @numbers, @ary; } ## 計算最大值、最小值和平均值 my $max = (sort { $b <=> $a } @numbers)[0]; my $min = (sort { $a <=> $b } @numbers) [0]; my $sum =0; $sum += $_ for @numbers; my $avg = $sum / @numbers; ## 輸出結果 print "最大值: $max\n"; print "最小值: $min\n"; print "平均值: $avg\n"; close (DATA); 使用方式 perl max_min_avg.pl riseC 結果: 最大值:0.00323131 最小值: 0.00226739 平均值:0.002983495 riseC: "0.00264617, 0.00237069, 0.00230644, 0.00228424, 0.00227416, 0.00227032, 0.00226836, 0.00226739", "0.00322831, 0.00323131, 0.00316939, 0.00283283, 0.0025619, 0.00242233, 0.00235136, 0.002317", \ "0.00322562, 0.00322585, 0.00322684, 0.00321483, 0.00300823, 0.0026767, 0.00248122, 0.00238", "0.00322181, 0.00322257, 0.0032231, 0.00322229, 0.00322081, 0.00306827, 0.00272794, 0.00250753",\ "0.00321706, 0.00321843, 0.00321988, 0.00321986, 0.0032225, 0.0032165, 0.0030942, 0.00275446",\ "0.00321555, 0.00321851, 0.00321821, 0.00321952, 0.00322031, 0.00322318, 0.00321586, 0.00310252", "0.00321461, 0.00321901, 0.00321834, 0.00321678, 0.00321843, 0.00322075, 0.00321996, 0.00321428", "0.00321823, 0.00321797, 0.00321929, 0.0032173, 0.00321809, 0.00321879, 0.00321988, 0.00321961"

2025年1月19日 星期日

保留pin RETN{} block 跟mega_ 參數

#!/usr/bin/perl use strict; use warnings; # 檔案路徑 my $input_file = 'input.txt'; # 請將 'input.txt' 替換為你的檔案名稱 my $output_file = 'output.txt'; # 讀取檔案內容 open my $in_fh, '<', $input_file or die "無法打開檔案 $input_file: $!"; my @lines = <$in_fh>; close $in_fh; # 處理檔案內容 my $inside_block = 0; my @filtered_lines; foreach my $line (@lines) { if ($line =~ /pin \("RETN"\) \{/) { $inside_block = 1; # 開始進入區塊 } if ($inside_block || $line =~ /mega_/) { push @filtered_lines, $line; } if ($inside_block && $line =~ /xRxFxxx/) { $inside_block = 0; # 結束區塊 } } # 寫入處理後的內容到新檔案 open my $out_fh, '>', $output_file or die "無法創建檔案 $output_file: $!"; print $out_fh @filtered_lines; close $out_fh; print "已處理完成,結果存入 $output_file\n";

計算altos_veclist裡面有幾個vector並把數量寫在下面

#!/usr/bin/perl use strict; use warnings; # 檔案路徑 my $input_file = 'input.txt'; # 請將 'input.txt' 替換為你的檔案名稱 my $output_file = 'output.txt'; # 讀取檔案內容 open my $in_fh, '<', $input_file or die "無法打開檔案 $input_file: $!"; my @lines = <$in_fh>; close $in_fh; # 處理檔案內容 my @updated_lines; foreach my $line (@lines) { push @updated_lines, $line; #if ($line =~ /altos_veclist\(.*?\)/) { if ($line =~ /altos_veclist/) { # 計算 " 包住的字串總數 my $count = () = $line =~ /".*?"/g; # 在其下一行添加結果 push @updated_lines, "// 字串總數: $count\n"; } } # 寫入處理後的內容到新檔案 open my $out_fh, '>', $output_file or die "無法創建檔案 $output_file: $!"; print $out_fh @updated_lines; close $out_fh; print "已處理完成,結果存入 $output_file\n";

2024年10月20日 星期日

Regular Expression, regex

來源: https://tw.alphacamp.co/blog/regex Regex的基本元素 1. 字元匹配 .:匹配任何單個字元(除了換行符\n)。 \d:匹配任何數字,等同於[0-9]。 \D:匹配任何非數字字元,等同於[^0-9]。 \w:匹配任何字母數字字元,包括底線,等同於[A-Za-z0-9_]。 \W:匹配任何非字母數字字元。 \s:匹配任何空白字元(包括空格、製表符、換行符等)。 \S:匹配任何非空白字元。 2. 量詞 *:匹配前面的字元0次或多次。 +:匹配前面的字元1次或多次。 ?:匹配前面的字元0次或1次。 {n}:匹配前面的字元恰好n次。 {n,}:匹配前面的字元至少n次。 {n,m}:匹配前面的字元至少n次,但不超過m次。 3. 位置匹配 ^:匹配輸入字串的開始位置。 $:匹配輸入字串的結束位置。 \b:匹配一個字詞邊界。 \B:匹配非字詞邊界。 4. 字元集 [abc]:匹配任何一個列在方括號中的字元(此例中為”a”、”b”或”c”)。 [^abc]:匹配任何不在方括號中的字元。 5. 分組和引用 (abc):匹配並捕獲括號內的表達式(此例中為”abc”)。 (?:abc):匹配括號內的表達式但不捕獲匹配的字串。 \1:引用第一個捕獲組的匹配內容。 6. 或運算 |:匹配左側或右側的表達式。 Regex的應用範例 範例1:驗證電子郵件地址 假設我們需要確認一個字符串是否為有效的電子郵件地址,我們可以使用以下正規表達式: regexCopy code ^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$ ^ 表示匹配開始。 \w+ 匹配一個或多個字母、數字或底線。 ([\.-]?\w+)* 匹配0個或多個由點或連字符後跟一個或多個字母、數字或底線組成的序列。 @ 是字面量字符,匹配”@”。 \w+([\.-]?\w+)* 匹配域名部分。 (\.\w{2,3})+$ 匹配一個點後跟2到3個字母的頂級域名。 範例2:提取日期 如果我們有一串文本,需要從中提取出所有符合特定格式的日期(例如,YYYY-MM-DD),我們可以使用以下正規表達式: regexCopy code \b\d{4}-\d{2}-\d{2}\b \b 表示單詞邊界。 \d{4} 匹配4位數字(年份)。 - 是字面量字符,匹配”-“。 \d{2} 匹配2位數字(月份和日期)。 範例3:密碼強度檢查 為了確保用戶設定的密碼至少包含8個字符,且包含大小寫字母、數字和特殊字符,我們可以使用以下正規表達式: regexCopy code ^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$ ^ 和 $ 分別匹配字符串的開始和結束。 (?=.*[a-z]) 確保字符串中至少有一個小寫字母。 (?=.*[A-Z]) 確保至少有一個大寫字母。 (?=.*\d) 確保至少有一個數字。 (?=.*[@$!%*?&]) 確保至少有一個特殊字符。 透過這些範例,我們可以看到正規表達式如何在不同場景下提供強大的文本匹配和處理能力。掌握正規表達式不僅能夠幫助你更有效地處理文本數據,還能提升你的程式設計和數據分析技能。隨著練習和應用的深入,你將能夠解鎖正規表達式更多的潛力,將其應用到更廣泛的領域中。 dotAll Flag, /s ES 2019 新增 /s 的標籤,過去 . 可以用來匹配除了換行符號以外(\n, \r)的所有字元: // 過去 . 可以匹配到除了「換行符號」以外的所有字元 console.log(/./.test('\n')); // → false console.log(/./.test('\r')); // → false 過去雖然可以使用 [\w\W] 來匹配到換行符號,但這不是最好的做法: console.log(/[\w\W]/.test('\n')); // → true console.log(/[\w\W]/.test('\r')); // → true 在 ES 2019 中,只要最後有標記 /s 的標籤,如此 . 將也能夠匹配到換行符號: console.log(/./s.test('\n')); // → true console.log(/./s.test('\r')); // → true
#!/bin/csh touch exclude_cell_for_pvt.log foreach CELL_LDB (`ls A.ldb.gz/*.gz | sed -r "s/\x1B\[[0-9;]*[mK]//g"`) echo $CELL_LDB echo $CELL_LDB >> exclude_cell_for_pvt.log zgrep 'exclude_cell_for_pvt' $CELL_LDB | wc >> exclude_cell_for_pvt.log end

2024年10月17日 星期四

Keeping skeleton: remove values in LIB

use strict; use warnings; #輸入檔案和輸出檔案 my $input_file = $ARGV[0]; my $output_file = $input_file.". skeleton"; # 讀取輸入檔案的內容 open my $in, '<', $input_file or die "can't open file $input_file: $!"; my $content = do { local $/; <$in> }; close $in; #使用正規表示式處理跨行的 { ... } 區塊 #$content = s/values\s*\(.*?\); \s*//gs; #移除 vector (ccsp_template2) { } $contents/vector \(ccsp_template2\) {.*?)\s*//gs; #移除 (delay_template_8x8) ( ) $content = s/\(delay_template_8x8\) (.*?)\s*//gs; #移除 (power_template_8x8) ( ) $content =- s/\(power_template_8x8\) (.*?)\s*//gs; #將結果寫入輸出檔案 open my $out, >', $output_file or die "Can't write contents into file $output_file: $!"; print $out $content; close $out; print "Output data to new file $output_file\n";

2024年1月28日 星期日

正規化表示

https://ithelp.ithome.com.tw/articles/10251882 Day 25 正規化表示 在做搜尋條件的時候,有時候想找尋某個檔案,但只記得他的內容關鍵字,這時候正規表示法就非常方便,下關鍵字達到找尋最接近的結果。 grep 全名為 global regular expression print。 [root@localhost ~]# grep [參數] [關鍵字] [檔案或目錄] 參數 -A [行數] (After)顯示符合的那一行,同時顯示該行之後的內容。 -a 以二進位的檔案作為搜尋。 -B [行數] (Before)顯示符合的那一行,同時顯示該行即之前的內容。 -b 顯示符合條件的結果,總共多少 bytes。 -C [行數] (Context)顯示符合的那一行及前後內容。 -c 顯示符合條件的總行數。 -d [動作] 查詢目錄(忽略檔案)。 -E (Extend)使用正則表示式搜尋。 -e [符合條件的內容] 指定搜尋的檔案,通常用在避免partern用-開始。 -F 符合條件的內容作為固定字串的列表。 -f [範本檔案] 指定符合條件的內容,並且將每一行套用樣式。 -G 將樣式視為基本的正規表示法。 -H 在每個符合樣式的行,前面加上符合的檔案名稱或路徑。 -h 同 -H ,但輸出不顯示路徑。 -i (ignore case)不區分大小寫。 -L 不符合條件內容的檔案名稱。 -l 符合條件內容的檔案名稱。 -n (number)顯示符合條件的行數及路徑。 -o 顯示被模式比對到的條件。 -q 不顯示任何結果。 -r 遞迴,讀取每個目錄底下的檔案,同 -d recsuse。 -s 不顯示錯誤訊息或無法讀取的訊息。 -V (Version) 顯示 grep 版本資訊。 -v (recursive)顯示不符合條件的結果。 -w 只顯示文字完全符合的結果。 -x 只顯示全列都符合的列 --help 尋求幫助。 正規表示法特殊字符 正規表示法中的特殊符號,與原意思不相同,他們都有各自使用方式。 特殊符號 說明 ^ 搜尋規則前的「起頭」。意思代表「非」。 $ 搜尋規則後的「結尾」。 . 任意一個字元。 * 任意字元或任意字串,長度可以為0 .* 一起使用代表任意字串。 跳脫字符,將字串中特殊符號的動作去除。 + 一個或多個重複字元 ? 匹配正則表達式的結束行 (n,m) 連續 n 個 到 m個的字串。 < 從比對正則表達式的行開始。 > 到比對正則表達式的行結束。 [] 比對範圍內的字元或字串。 [^] 比對不再指定範圍內的字元。 [-] 範圍 ;如[A-Z]即A,B,C一直到Z都符合要求 國際模式比對字符 特殊符號 代表意義 [:alnum:] 英文大小寫字元及數字,亦即 0-9, A-Z, a-z [:alpha:] 任何英文大小寫字元,亦即 A-Z , a-z [:blank:] 空白鍵與 [Tab] 按鍵兩者 [:cntrl:] 鍵盤上面的控制按鍵,亦即包括 CR, LF, Tab, Del.. 等等 [:digit:] 數字而已,亦即 0-9 [:graph:] 除了空白字元 (空白鍵與 [Tab] 按鍵) 外的其他所有按鍵 [:lower:] 小寫字元,亦即 a-z [:print:] 任何可以被列印出來的字元 [:punct:] 標點符號 (punctuation symbol),亦即:" ' ? ! ; : # $... [:upper:] 大寫字元,亦即 A-Z [:space:] 任何會產生空白的字元,包括空白鍵, [Tab], CR 等等 [:xdigit:] 16 進位的數字類型,因此包括: 0-9, A-F, a-f 的數字與字元 實際操作 多檔案或目錄搜尋 [root@localhost ~]# grep [參數] [關鍵字] [檔案或目錄1] [檔案或目錄2] [檔案或目錄3] ... 搜尋的關鍵字,以顏色特別標註 --color [root@localhost ~]# grep [參數] [關鍵字] --color [檔案或目錄] 遞迴尋找 root 目錄下的檔案,須符合 美女的字串。 [root@localhost ~]# grep -r "美女" /root/ /root/demo.sh: echo "美女您好"

2023年9月20日 星期三

calculate_sigma

#!/usr/bin/perl
$input_library = $ARGV[0];
$timing_flag=0; $timing_type_flag=0; $get_value_flag=0; $table_count=0;

open(LIB,"<$input_library");
open(NEW, ">hold_sigma.lib") || die "Can not open the file : temp.txt \n";

while(<LIB>){
      print NEW "$_";
      chop $_;
      $table_count++;
      #if(/timing \(\) {/){
  #    #  $timing_flag=1;
  #        #  print "$_ \n";
  #            #}
  #
    if(/timing_type : hold_rising/ || /timing_type : hold_falling/){
        $timing_type_flag=1;
#print "$_ \n";
}
if(/values \( / && ($timing_type_flag=="1")){
$get_value_flag=1; $timing_type_flag=0;
$table_count=0;
#print "$_ \n";
}
    if($get_value_flag==1 && $table_count>0){
        #print "start to get values: $table_count\n";
$_ =~ s/", \\//; $_ =~ s/" \\//; $_ =~ s/"//; $_ =~ s/,//g; #removed unnecessary symbols
@ary=split(" ",$_);
for ($i=0; $i<5; $i++) {
$table_array[(($table_count-1)*5)+$i]=$ary[$i];
}
#print NEW "$_\n";
if($table_count>79){
$table_count=0; $get_value_flag=0; $timing_type_flag=0;
#print NEW @table_array; print NEW "\n";
print NEW "ADD sigma table\n";
for ($j=0; $j<25; $j++) {
$sigma=((($table_array[125+$j]**2)+($table_array[175+$j]**2)+($table_array[225+$j]**2)+($table_array[275+$j]**2)+($table_array[325+$j]**2)+($table_array[375+$j]**2))**0.5);
print NEW "$sigma ";
if((($j+1)%5)=="0"){print NEW "\n";}
}
print NEW "\n";
}
}
}
close(LIB);
close(NEW);

######################################################################

#!/usr/bin/perl                                                                                                                                                                                                    

# input file cell.ldb 
# output add on sigma for mpw

$input_library = $ARGV[0];
$timing_flag=0; $timing_type_flag=0; $get_value_flag=0; $table_count=0;

open(LIB,"<$input_library");
open(NEW, ">mpw_sigma.ldb") || die "Can not open the file : temp.txt \n";

while(<LIB>){
      print NEW "$_";
          chop $_;
              $table_count++;
                  #if(/timing \(\) {/){
                  #    #  $timing_flag=1;
                  #        #  print "$_ \n";
                  #            #}
                  #
    if(/timing_type : min_pulse_width/){
            $timing_type_flag=1;
            #print "$_ \n";
            }
    if(/values \( / && ($timing_type_flag=="1")){
    $get_value_flag=1; $timing_type_flag=0;
    $table_count=0;
    #print "$_ \n";
    }
    if($get_value_flag==1 && $table_count>0){
            #print "start to get values: $table_count\n";
            $_ =~ s/", \\//; $_ =~ s/" \\//; $_ =~ s/"//; $_ =~ s/,//g; #removed unnecessary symbols
            @ary=split(" ",$_);
            #save 5X1 values into a array
            for ($i=0; $i<5; $i++) {
            $table_array[(($table_count-1)*5)+$i]=$ary[$i];
            }
            #print NEW "$_\n";
            if($table_count>15){
            $table_count=0; $get_value_flag=0; $timing_type_flag=0;
            #print NEW @table_array; print NEW "\n";
            print NEW "ADD sigma table\n";
            for ($j=0; $j<5; $j++) {
            $sigma=((($table_array[25+$j]**2)+($table_array[35+$j]**2)+($table_array[45+$j]**2)+($table_array[55+$j]**2)+($table_array[65+$j]**2)+($table_array[75+$j]**2))**0.5);
            print NEW "$sigma ";
            $sigma_plus_nominal[$j]=($sigma*3)+($table_array[15+$j]);
            #if((($j+1)%5)=="0"){print NEW "\n";}
            }
            print NEW "\n";
            print NEW "ADD 3sigma+nominal table\n";
            for ($k=0; $k<5; $k++) {
            print NEW "$sigma_plus_nominal[$k] ";
            }
            print NEW "\n";
        }
    }
}
            
        close(LIB);
        close(NEW);               

2023年8月24日 星期四

AWK

1. 用","當作分隔,取出某一欄位
 cat *.csv | awk -V FS="," '{print $11}'

2. 比較某一欄的值是否大於或小於某個值
使用方法: cat *.txt | awk -f max.awk

BEGIN {
    max = 0.005;
    min = -0.005;
    FS="[,]";
    }
    {
if (FNR > 1) {
    if ($11>max) {
        # print NR;  -->印出行號
        print $0; -->印出該行內容
            }
    if ($11<min) {
        # print NR;
        print $0;
            }
}
}
END {
    printf("max = %f min = %f ", max,min);

3. grep comparison results 
grep -A 2 Pass */*diff.cmp.txt | grep % | awk -F "|" '{print $5}' | xargs



2023年8月11日 星期五

vimdiff


摺疊的命令:
zo : open fold
zc : close fold
zr : reducing folding level
zm : more folding level
zR : reduce completel folding
zM : fold Most

重新計算diff :
:diffupdate or :diffu

同步滾動:
:set scrollbind
:set noscrollbind


2023年6月26日 星期一

Check spike current for CCST waveform

 #! /usr/local/bin/perl 

### input all simulation waveforms then export values which have spike current
### generate a shell script (check_waveform.sh) to plot waveforms in gnuplot for examination

open (AA, "ls analyze_ccs/*/*/*/waveforms/waveform simulation.txt |") or die;
    while (<AA>){
        chomp;
        push @libs, $_;
        }
close AA; 

$out = "check_waveform.sh";
open (BB,">$out") or die;
foreach $lib (@libs){
    open (AA, $lib) or die;
    #print "file: $lib ";
    $i=0; $previous_current=le-8; $present_current=le-8;
    #$dir=`basename $lib`;
    $dir=`dirname $lib`;
    chomp($dir);
    #print "dir path is $dir \n";
    while (<AA>){
        chomp;
        if ($i>"1"){
            @current=split(" ",$_);
            $present_current=$current[1];}
        if ($i=="2"){
            $previous_current=$current[1]; $present_current=$current[1];}
$rel_diff=abs($previous_current/$present_current) ;
#print "Rel diff is $rel_diff , previous is $previous_current , present is $present_current \n";
#export waveform values which have large differences (X10000)
        if ($rel_diff > 10000 || $rel_diff < 0.0001){
            print "file: $lib has spike at line $i, Rel diff is $rel_diff, previous is $previous_current, present is $present_current\n";
            $time_axis=$current[0]+le-10;
            print BB "sed -i '/set datafile missing/i";
            print BB "set xrange [0:$time_axis]";
            print BB "gnuplot $dir/gnuplot.cmd\n";
            print BB "gnuplot $dir/gnuplot.cmd\n";
            }
        $previous_current=$present_current ;
        $i++;
        }
close AA; 
}
close BB;

2022年2月12日 星期六

ETF實戰週記

 0050的進場時機

各位一定要先有兩個認知:
大盤日 K<20買K>80賣
空頭市場(大盤跌破季線超過一個月)大盤日 K<10買K>70賣

時間管理入門

 1.今天就開始您餘生的第一天。

2.時間管理是:控制自己的時間與工作,而不是讓它們控制自己
3.誰有清晰的目標,並追求它,也就能將他的潛能在實際行動上發揮出來(自我鼓勵與自我規律)。目標有助於將力量匯聚在眞正的重點上。問題不在於您作什麼事,而在您爲什麼做那些事情。設定目標是時間管理成功的先決條件與秘訣。
4.您必須嚴肅地把您的行事曆冊,您要
。設定優先順序
。化繁爲簡
。授權。
其餘的事必須順延、取消或加班處理。
5.如果一件事轉載記錄了很多次,將會造成困擾。這時有兩種可行性:
逮住它,現在就把它解決。
取消它,因爲已經没事了。
6.檢查《授權規則〉(快速分析法)
該作什麼?(內容)
誰該作?(人)
為什麼他該作?(動機,目標)
他該怎麼作?(範圍,細節)
什麼時候他該完成?(時限)

2021年9月1日 星期三

如何把變數帶入到sed內

foreach N (488 489 490 491 492 493 494 495) 

sed -i "$N s/^/#/g" test.tcl  --> 要用" " 不要用' ' ; $N後面要空格
                ^
liberate --trio test.tcl >& test.log
liberate --trio check.tcl >& check.log
mkdir Test$N ; mv test.log check.log TEST* Test$N ; rm -rf deck_TEST
end 


2021年4月27日 星期二

貪食蛇程式分析

 #include <iostream>

#include <string>

#include <stdlib.h>

#include <time.h>

using namespace std;


class Point{ // 與位置相關的類別

private: // 宣告私有資料成員

int x;

int y;

public: // 宣告公用資料成員

Point(int a,int b) // 宣告公用成員函數,有傳值時x=a,y=b沒有傳

{

x=a;

y=b;

}

Point() // 宣告公用成員函數,沒有傳值時x=0,y=0

{

x=0;

y=0;

}

void setPoint(int a,int b) // 設定x,y的位置函數

{

x=a;

y=b;

}

int getX() // 取得X方向的位置函數

{

return x;

}

int getY() // 取得y方向的位置函數

{

return y;

}

};


class SnakeGame{ // 與位置相關的類別

private:

char area[10][10]; //定義遊戲範圍為10X10的二維陣列 

Point head; //定義"頭"的資料型態為Point 

Point body[64]; //定義"身體" 

Point tail; //定義"尾巴" 

Point food; //定義"食物" 

int Length; //定義"長度"為整數

public:

SnakeGame()

{

Length=5;

// 設定蛇與食物的初始位置

head.setPoint(4,3);

body[0].setPoint(4,4);

body[1].setPoint(4,5);

body[2].setPoint(4,6);

body[3].setPoint(4,7);

tail.setPoint(4,7);

food.setPoint(4,1);

for(int i=0;i<10;i++) // 利用二維迴圈劃出遊戲範圍

{

for(int j=0;j<10;j++){

if(i==0||i==9||j==0||j==9)

area[i][j]='#';

else

area[i][j]=' ';

}

}

// 畫出蛇與食物位置

area[head.getX()][head.getY()]='O';

area[body[0].getX()][body[0].getY()]='O';

area[body[1].getX()][body[1].getY()]='O';

area[body[2].getX()][body[2].getY()]='O';

area[tail.getX()][tail.getY()]='O';

area[food.getX()][food.getY()]='*';

}

bool checkSpace(int step){ // 檢查蛇是否撞到牆壁或者回頭吃到自己的函數

if(step==76){  // 往左邊走一步,76是L的ascii碼

return !( area[head.getX() ][head.getY()-1]=='#'||area[head.getX()][head.getY()-1]=='O'); 

}

else if(step==85){ //往上面走一步,85是U的ascii碼 

return !(area[head.getX()-1][head.getY()]=='#'||area[head.getX()-1][head.getY()]=='O');

else if(step==82){ //往右邊走一步,82是R的ascii碼 

return !(area[head.getX()][head.getY()+1]=='#'||area[head.getX()][head.getY()+1]=='O');

}

else if(step==68){ //往下面走一步,68是D的ascii碼 

return !(area[head.getX()+1][head.getY()]=='#'||area[head.getX()+1][head.getY()]=='O');

}

}

void run(int step){ // 蛇移動時的處理函數

tail.setPoint(body[Length-2].getX(),body[Length-2].getY());

int tempX=tail.getX();

int tempY=tail.getY();

area[tail.getX()][tail.getY()]=' '; // 蛇移動後用空白將尾巴消除

// 蛇移動後身體往前移動一格

for(int i =Length-1;i>0;i--)

{body[i].setPoint(body[i-1].getX(),body[i-1].getY());}

body[0].setPoint(head.getX(),head.getY());

// 蛇頭移動後的處理方式

if(step==76){  //蛇頭往左邊移動一格

head.setPoint(head.getX(),head.getY()-1);}

else if(step==85){//蛇頭往上面移動一格

head.setPoint(head.getX()-1,head.getY());}

else if(step==82){//蛇頭往右邊移動一格

head.setPoint(head.getX(),head.getY()+1);}

else if(step==68){//蛇頭往下面移動一格 

head.setPoint(head.getX()+1,head.getY());}

for(int i =0;i<Length-2;i++)

{area[body[i].getX()][body[i].getY()]='O';}

area[head.getX()][head.getY()]='O';

Eatfood(tempX,tempY);

}

void printArea(){ // 畫出10X10範圍內的圖像函數

for(int i=0;i<10;i++){

for(int j=0;j<10;j++)

{cout<<area[i][j];}

cout<<endl;

}

}

void Foodset() // 設定食物位置的函數

{

int foodX,foodY;

srand((unsigned)time(NULL));

            // 亂數產生新的食物

foodX=(rand()%8)+1;

foodY=(rand()%8)+1;

for(int i =0;i<Length-2;i++) // 檢查亂數產生新的食物是否跟蛇的身體重疊

{

if(foodX != body[i].getX() && foodY != body[i].getY())

{if((foodX != head.getX() && foodY != head.getY()) ||( foodX!=0 && foodY!=0) || (foodX != tail.getX() && foodY != tail.getY()))

{food.setPoint(foodX,foodY);}}

}

area[food.getX()][food.getY()]='*';

}

void Eatfood(int tempX,int tempY){ // 蛇吃到食物的處理函數

if(head.getX()==food.getX()&&head.getY()==food.getY()) // 判斷蛇有沒有吃到食物

{

Length++; // 蛇長度+1

body[Length-1].setPoint(tempX,tempY);

area[body[Length-1].getX()][body[Length-1].getY()]='O';

Foodset(); // 產生新的食物

}

};


int main(int argc, char** argv) { // 主程式

SnakeGame sg;

char step;

while(1)

{

sg.printArea(); 

cout<<"請輸入移動方向(U/D/L/R):";

cin>>step;

if(step==76||step==85||step==82||step==68)

{

if(sg.checkSpace(step)) // 檢查蛇移動後是否違反規則

{sg.run(step); // 蛇移動

}

else{ // 蛇是撞到牆壁或者回頭吃到自己則結束程式

cout<<"GameOver"<<endl; 

break;}

system("cls");

}

return 0;

}

2021年4月22日 星期四

Plot @ gnuplot

 對於在Linux下工作的人,如果你經常要畫一些二維圖和簡單的三維圖的話,那麼,gnuplot無疑是一個非常好的選擇,不僅圖形漂亮,而且操作簡單。當

然如果需要品質更高的三維圖,請用其他的一些專業繪圖軟體。建議大家學會使用gnuplot。這個小軟體通常都是Redhat
Linux內建的,但內建的版本是3.7的,建議將其升級到4.0,新版本具有很多新功能。最新版本可以到
http://www.gnuplot.info/
下載。

些最基本的操作請大家看說明書。這裡總結一下我在使用過程中遇到的一些問題以及解決的辦法,目的是讓那些以前不會的或不熟練的能快速入門,會畫自己想要的
圖,因為原來的說明書很長,較難有針對性地很快找到自己想要的資訊。這裡簡單的總結不可能面面俱到,所以大家不要抱怨我寫的不全,更全面的瞭解還是請看說
明書,網上的資料也多的是。其實這也是我們從網上一點一點搜集和摸索出來的。我相信看完後,應該平時最常見的問題基本上都能在這裡找到答案。如果大家在使
用過程中摸索到了我沒有寫到的技巧和體會,或有其它建議,請大家提告訴我,以不斷完善這篇總結,謝謝。
一、基礎篇:
在linux命令提示字元下運行gnuplot命令啟動,輸入quit或q或exit退出。
1、plot命令
gnuplot> plot sin(x) with line linetype 3 linewidth 2 或
gnuplot> plot sin(x) w l lt 3 lw 2    %用線畫,線的類型(包括顏色與虛線的類型)是3,線的寬度是2,對函數sin(x)作圖
gnuplot> plot sin(x) with point pointtype 3 pointsize 2  或
gnuplot> plot sin(x) w p pt 3 ps 2    %用點畫,點的類型(包括顏色與點的類型)是3,點的大小是2
gnuplot> plot sin(x) title 'f(x)' w lp lt 3 lw 2 pt 3 ps 2    %同時用點和線畫,這裡title ‘f(x)’表示圖例上標'f(x)',如果不用則用預設選項
gnuplot> plot sin(x)    %此時所有選項均用預設值。如果缺某一項則將用預設值
gnuplot> plot ‘a.dat’ u 2:3  w l lt 3 lw 2 %利用資料檔案a.dat中的第二和第三列作圖
順便提一下,如這裡最前面的兩個例子所示,在gnuplot中,如果某兩個詞,按字母先後順序,前面某幾個字母相同,後面的不同,那麼只要寫到第一個不同的字母就可以了。如with,由於沒有其它以w開頭的詞,因此可以用 w 代替,line也可以用 l 代替。
2、同時畫多條曲線
gnuplot> plot sin(x) title ‘sin(x)’ w l lt 1 lw 2, cos(x) title ‘cos(x)’  w l lt 2 lw 2  %兩條曲線是用逗號隔開的。畫多條曲線時,各曲線間均用逗號隔開就可以了。
以上例子中是對函數作圖,如果對資料檔案作圖,將函數名稱換為資料檔案名即可,但要用單引號引起來。
3、關於圖例的位置
預設位置在右上方。
gnuplot> set key left  %放在左邊,有left 和right兩個選項
gnuplot> set key bottom  %放在下邊,只有這一個選項;預設在上邊
gnuplot> set key outside  %放在外邊,但只能在右面的外邊
以上三個選項可以進行組合。如:
gnuplot> set key left bottom  %表示左下邊
還可以直接用座標精確表示圖例的位置,如
gnuplot> set key 0.5,0.6  %將圖例放在0.5,0.6的位置處
4、關於座標軸
gnuplot> set xlabel ‘x’   %x軸標為‘x’
gnuplot> set ylabel ‘y’   %y軸標為’y’
gnuplot> set ylabel ‘DOS’ tc lt 3  %其中的tc lt 3表示’DOS’的顏色用第三種顏色。
gnuplot> set xtics 1.0    %x軸的主刻度的寬度為1.0,同樣可以為y軸定義ytics
gnuplot> set mxtics 3    %x軸上每個主刻度中畫3個分刻度,同樣可以為y軸定義mytics
gnuplot> set border 3 lt 3 lw 2 %設為第三種邊界,顏色類型為3,線寬為2
同樣可以為上邊的x軸(稱為x2)和右邊y(稱為y2)軸進行設定,即x2tics,mx2tics,y2tics,my2tics。
gnuplot> set xtics nomirror
gnuplot> unset x2tics     %以上兩條命令去掉上邊x2軸的刻度
gnuplot> set ytics nomirror
gnuplot> unset y2tics     %以上兩條命令去掉右邊y軸的刻度
5、在圖中插入文字
gnuplot> set label ‘sin(x)’ at 0.5,0.5  %在座標(0.5,0.5)處加入字串’sin(x)’。
在輸出為.ps或.eps檔案時,如果在set term 的語句中加入了enhanced選現,則可以插入上下標、希臘字母和特殊符號。上下標的插入和latex中的方法是一樣的。
6、在圖中添加直線和箭頭
gnuplot> set arrow from 0.0,0.0 to 0.6,0.8    %從(0.0,0.0)到(0.6,0.8)畫一個箭頭
gnuplot> set arrow from 0.0,0.0 to 0.6,0.8 lt 3 lw 2   %這個箭頭顏色類型為3,線寬類型為2
gnuplot> set arrow from 0.0,0.0 to 0.6,0.8 nohead lt 3 lw 2  %利用nohead可以去掉箭頭的頭部,這就是添加直線的方法。
注意,在gnuplot中,對於插入多個的label和arrow等等,系統會預設按先後順序分別對各個label或arrow進行編號,從1開始。如果以後要去掉某個label或arrow,那麼只要用unset命令將相應的去掉即可。如:
gnuplot> unset arrow 2
將去掉第二個箭頭。
7、圖的大小和位置
gnuplot>set size 0.5,0.5  %長寬均為預設寬度的一半,建議用這個取值,尤其是畫成ps或eps圖形的時候
gnuplot>set origin 0.0,0.5   %設定圖的最左下角的那一點在圖形面板中的位置。這裡圖將出現在左上方。
8、畫三維圖
gnuplot>splot ‘檔案名稱’ u 2:4:5  %以第二和第四列作為x和y座標,第五列為z座標。
9.將圖形輸出到檔案

gnuplot中,輸出檔案的格式是由terminal來控制的。預設的情況下,都是輸出到螢幕,即終端模式為X11。如果想輸出到檔案,則必須對
terminal進行設定。要瞭解有那些終端類型,可以輸入 set
terminal後斷行符號,所有支援的終端模式(或檔案格式)都列出來了。就我來說,輸出檔案的格式用得最多的是ps和eps檔案。這在運行畫圖命令
plot或splot前必須先運行如下兩條命令:
gnuplot>set term post eps color solid enh
gnuplot>set output ‘a.eps’

中第一條命令為設定終端模式,post即為postscript模式,這是輸出到ps或eps檔案必須有的。後面的eps,color,solid以及
enh選項均可以有或沒有,根據你的需要。eps表示輸出為eps檔案,沒有就輸出為ps檔案;color表示輸出圖形為彩色,不用就會儲存為黑白
的;solid表示輸出圖中的所有線都用實線,不用則除了第一條線為實線外,其它的均用不同的虛線;使用enh(enhanced)選項可以在圖中插入上
下標、希臘字母和特殊符號,不用則不能實現這些功能。後面的選項可以根據自己的需要選擇一個或幾個。
第二條命令對output的設定表示要輸出的檔案的名字。但是請注意,運行完這條命令後,還僅僅是定義了輸出檔案的名字,實際上,圖還沒畫到這個檔案裡去。因此運行這兩條命令還只是進行了必須的設定。然後運行如下命令
gnuplot>plot sin(x) w l

gnuplot>replot(假如前面已經運行過plot或replot命令的話)
這時,圖形就在上面指定的檔案中了。
要輸出為其它格式,同樣要進行這樣的設定,比如要輸出為jpg格式,則在運行畫圖命令前先運行如下命令:
gnuplot>set term jpeg
gnuplot>set output ‘a.jpg’
如果要由其它模式再返回到輸出到螢幕,則運行如下命令:
gnuplot>set term X11
二、提高篇:

1、如何在同一張圖裡同時畫多個圖

gnuplot>set multiplot   %設定為多圖模式
gnuplot>set origin 0.0,0.5   %設定第一個圖的原點的位置
gnuplot>set size 0.5,0.5  %設定第一個圖的大小
gnuplot>plot “a1.dat”
gnuplot>set origin 0.5,0.5   %設定第二個圖的原點的位置
gnuplot>set size 0.5,0.5   %設定第二個圖的大小
gnuplot>plot “a2.dat”
gnuplot>set origin 0.0,0.0   %設定第三個圖的原點的位置
gnuplot>set size 0.5,0.5  %設定第三個圖的大小
gnuplot>plot “a3.dat”
gnuplot>set origin 0.5,0.0   %設定第四個圖的原點的位置
gnuplot>set size 0.5,0.5  %設定第四個圖的大小
gnuplot>plot “a4.dat”
當然,如果後一個圖中的某個量的設定和前一個的相同,那麼後一個中的這個量的設定可以省略。例如上面對第二、第三和第四個圖的大小的設定。前一個圖中對某個量的設定也會在後一個圖中起作用。如果要取消在後面圖中的作用,必須用如下命令,如取消label,用
gnuplot>unset label
2、作二維圖時,如何使兩邊座標軸的單位長度等長
gnuplot> set size square    %使圖形是方的
gnuplot> set size 0.5,0.5    %使圖形是你要的大小
gnuplot> set xrange[-a:a]
gnuplot> set yrange[-a:a]    %兩座標軸刻度範圍一樣
gnuplot> plot ‘a.dat’
3、如何在同一張圖裡利用左右兩邊的y軸分別畫圖
gnuplot> set xtics nomirror   %去掉上面座標軸x2的刻度
gnuplot> set ytics nomirror   %去掉右邊座標軸y2的刻度
gnuplot> set x2tics       %讓上面座標軸x2刻度自動產生
gnuplot> set y2tics     %讓右邊座標軸y2的刻度自動產生
gnuplot> plot sin(x),cos(x) axes x1y2    %cos(x)用x1y2座標,axes x1y2表示用x1y2座標軸
gnuplot> plot sin(x),cos(x) axes x2y2     %cos(x)用x2y2座標,axes x2y2表示用x2y2座標軸
gnuplot> set x2range[-20:20]   %設定x2座標的範圍
gnuplot> replot
gnuplot> set xrange[-5:5]  %設定x座標的範圍
gnuplot> replot
gnuplot> set xlabel 'x'
gnuplot> set x2label 't'
gnuplot> set ylabel 'y'
gnuplot> set y2label 's'
gnuplot> replot
gnuplot> set title 'The figure'
gnuplot> replot
gnuplot> set x2label 't' textcolor lt 3    %textcolor lt 3或tc lt 3設定座標軸名稱的顏色
4、如何插入希臘字母和特殊符號
一般只能在ps和eps圖中,且必須指定enhanced選項。在X11終端(即顯示器)中無法顯示。
gnuplot> set terminal postscript enhanced然後希臘字母就可以通過{/Symbol a}輸入。例如
gnuplot> set label ‘{/Symbol a}’
各種希臘字母與特殊符號的輸入方法請見安裝包中gnuplot-4.0.0/docs/psdoc目錄下的ps_guide.ps檔案。
另外還可參見:
http://t16web.lanl.gov/Kawano/gnuplot/label-e.html#4.3
5、gnuplot中如何插入Angstrom(埃)這個符號(A上面一個小圓圈)
指令碼中在插入前先加入
gnuplot>set encoding iso_8859_1
這個命令,然後就可以通過“{\305}”加入了。如橫座標要標上“k(1/?)”:
gnuplot>set xlabel 'k(1/{\305})
如果是multiplot模式,則這個命令必須放在
gnuplot>set multiplot
的前面。
如果後面還要插入別的逸出字元,那麼還要在插入字元後加入如下命令:
set encoding default
安裝包中gnuplot-4.0.0/docs/psdoc/ps_guide.ps檔案中的表中的‘E’代表那一列的所有符號都用這個方法輸入。
6、gnuplot畫等高線圖
gnuplot>splot  ‘檔案名稱.dat’  u 1:2:3  w  l   %做三維圖
gnuplot>set dgrid3d 100,100 %設定三維圖表面的網格的數目
gnuplot>replot
gnuplot>set contour    %設定畫等高線
gnuplot>set cntrparam  levels  incremental -0.2,0.01,0.2   %設定等高線的疏密和範圍,資料從   -0.2到0.2中間每隔0.01畫一條線
gnuplot>unset surface   去掉上面的三維圖形
最後用滑鼠拽動圖形,選擇合理的角度即可。或者直接設定(0,0)的視角也可以:
gnuplot>set view 0,0
gnuplot>replot
這裡注意,畫三維圖的資料檔案必須是分塊的,也就是x每變換一個值,y在其變化範圍內變化一周,這樣作為一塊,然後再取一個x值,y再變化一周,作為下一資料區塊,等等。塊與塊之間用一空行格開。
7、如何畫漂亮的pm3d圖
gnuplot> set pm3d                %設定pm3d模式
gnuplot> set isosamples 50,50       %設定網格點
gnuplot> splot x**2+y**2          %畫三維圖
gnuplot> splot x**2+y**2 w pm3d   %畫成pm3d模式,注意比較變化
gnuplot> set view 0,0              %設定視角,(0,0)將投影到底面上去
gnuplot> splot x**2+y**2 w pm3d   %重畫,注意看變化
gnuplot> unset ztics               %把z軸上的數字給去掉
gnuplot> set isosamples 200,200     %使網格變細
gnuplot> replot                   %重畫,注意看變化,主要是過渡更光滑
8、利用指令檔避免重複輸入
有時候對某個資料檔案做好一張圖後,下次可能還要利用這個資料檔案作圖,但某個或某些設定要作些細微變化。這時候,可以把第一次作圖時的命令全部寫到一個檔案裡,如a.plt,下次只要將相應的設定做修改後,用下面的命令就會自動運行檔案所有的命令而最後得到你要的圖:
gnuplot>load ‘a.plt’
作為一個例子,假設檔案名稱為a.plt,裡面的內容為:
set pm3d 
set view 0,0 
unset ztics 
set isosamples 200,200 
splot x**2+y**2 w pm3d
set term post color
set output ‘a.ps’
replot
那麼啟動gnuplot後,只要運行如下命令就可以了:
gnuplot>load ‘a.plt’
如果我們要得到的僅僅是.ps或.eps圖,那也可以在linux命令提示字元下直接運行如下命令:
[zxh@theory zxh]$gnuplot a.plt
9、在gnuplot模式下運行linux命令
在gnuplot提示符下也可以運行linux命令,但必須在相應的命令前面加上 ! 號。例如,假設很多參量都已經設定好了,但需要對某個資料檔案a.dat進行修改後再畫圖,則可以用如下方式
gnuplot>!vi a.dat
通過這種方式,所有的linux命令都可以在gnuplot環境裡運行。
另外,也可以在gnuplot的提示符後輸入shell,暫時性退出gnuplot,進入linux環境,做完要做的事情後,運行exit命令,又回到gnuplot環境下。
gnuplot>shell
[zxh@theory zxh]$vi a.f
[zxh@theory zxh]$f77 a.f
[zxh@theory zxh]$a.out    (假設產生a.dat資料檔案)
[zxh@theory zxh]$exit
gnuplot>plot ‘a.dat’ w l 
                    
                

標籤