本學期有 HTML5 開發的課程,其期末考核方式為交一份「大作業」。得益於 HTML5 規範中新增的 canvas 標籤,程序員可以根據業務需要直接在網頁中通過代碼作畫,這讓網頁小遊戲的開發變得更加簡單了。許多人選擇開發一個小遊戲作為期末「大作業」,我自己的「大作業」就是一款貪吃蛇遊戲,同時,我還協(tì)助(dài)學習有困難的同學完成了他的期末大作業——掃雷遊戲。

我已將這兩個小遊戲上傳到本站伺服器上,供諸位體驗評析,提出高見。

貪吃蛇:進入遊戲

掃雷:進入遊戲

另外還有件事,就不單獨發文了,在此說一下,本站頁面頂部的「潘岸平的獨立博客」八個字前些天已替換成了我本人的手寫版本,因為我認為這樣能夠為本站注入靈魂。如果諸位訪客的瀏覽器裡顯示的還是原先的標題圖片,大致是 cache 在作祟,清空 cache 即可。

[問題描述]
  建立一棵二叉樹,判斷其是否為完全二叉樹,打印輸出判斷結果。

[基本要求] 
  從鍵盤接受輸入(先序),以二叉鏈表作為存儲結構,建立二叉樹(以先序來建立),並對其進行層次遍歷,並判斷它是否為完全二叉樹,然後打印輸出判斷結果。



//
//  main.swift
//  CompleteBinaryTreeTester
//
//  Created by 潘岸平 on 2017/11/22.
//  Copyright © 2017年 潘岸平. All rights reserved.
//

[查看全文]

[問題描述]
迷宮實驗是取自心理學的一個古典實驗。在該實驗中,把一隻老鼠從一個無頂大盒子的門放入,在盒中設置了許多牆,對行進方向形成了多處阻擋。盒子僅有一個出口處放置一塊奶酪,吸引老鼠在迷宮中尋找道路以到達出口。對同一隻老鼠重復進行上述實驗,一直到老鼠從入口到出口,而不走錯一步。老鼠經多次試驗終於得到它學習走通迷宮的路線。設計一個計算機程序對任意設定的迷宮,求出一條從入口到出口的通路,或得出沒有通路的結論。

[基本要求]
要求程序輸出:
(1)一條通路的二元組(i,j)數據序列,(i,j)表示通路上某一點的坐標。
(2)用一種標誌(如數字8)在二維數組中標出該條通路,並在屏幕上輸出二維數組。

本算法需要處理的數據主要是當前已走的路徑。經過反覆思考,我決定通過棧來實現。後附代碼中,結構體 Stack 保存了一個順序棧,其中 top 是棧頂元素的索引值,當棧為空時,其值為 -1 ;bottom 為一個指向棧所使用的空間的首地址的指針(棧底指針),當 InitStack 函數初始化一個棧的時候,會實際分配內存空間並使此指針指向分配的空間。此外,還有名為 Coord 的結構體用於保存一個迷宮中的位置和已經嘗試過的方向。在主函數內的死循環中,表示小老鼠的 current 結構體變量每嘗試下一格,都會將自身 push 到棧中保存起來。由於 Coord 結構體亦保存了已嘗試過的方向,回退後能夠緊接著上一次在此位置時的進度繼續向四面八方探索。


//
//  main.c
//  Maze
//
//  Created by 潘岸平 on 2017/10/31.
//  Copyright © 2017年 潘岸平. All rights reserved.
//

[查看全文]

本文介紹了一種通過觸發iOS作業系統在極端條件下的快取清理機制來釋放可達千兆位元組級存儲空間的方法。

目前市場保有的iPhone機型中,16GB版本數量龐大,筆者的就是。當iPhone內置存儲空間不足的時候,大多數人都會想到清除應用快取。在多數情況下,行此操作可獲得不錯的收效,但稍有經驗的用戶都可以察覺,距離上一次抹去iPhone的時間越長,清理應用快取以釋放存儲空間的收效就越差。這是因為,填滿iPhone存儲空間的無用文件並不全是應用快取,還有一些系統產生的垃圾。要清理這些垃圾,必須使iPhone處於存儲空間極度匱乏的極端條件下,讓iOS作業系統自動地清理這些文件。

為了在存儲空間尚有餘量時將其填滿,筆者通常採用的方法是,打開相機APP,瘋狂連拍照片,待相機提示「存儲空間已滿」時停止。這時,系統就會在後台默默清理掉一些無用的文件,包括日誌、快取、臨時文件等。待相機不再發出警告後,重複上述過程,直到僅連拍數十張照片後就會彈出警告為止。最後,刪除所有連拍的照片(記得清空「最近刪除」)並重新啟動iPhone,空間清理工作就算完成了。連拍照片的耗電量巨大,在連拍過程中,iPhone發熱屬於正常現象,若開始前或中途電量不足,則應先連接電源適配器,避免自動關機。

中國曾經流行一種在iTunes中下載大電影來逼迫iOS釋放快取空間的方法。但中國人思想僵化,愚笨至極,知其然而不知其所以然。事實上,稍有常識的人都可以看出,只要將iPhone的存儲空間佔滿,都可以觸發系統的快取清理機制。下載大電影的速度取決於ISP所提供的網路帶寬,完成一次空間清理通常比本文介紹的方法慢十倍以上,徒費光陰。我們何不自己大量寫入數據來達到相同的效果呢? 

package com.papwin;

[查看全文]

#include<iostream>

#include<math.h>

using namespace std;

void Hashima(int*, int*, int*, int*, int*, int*, int*, int*, int*);

struct Point

{

int x;

int y;

};

int main(int argc, char** argv)

{

int m, n, k1, k2, x = 0, y = 0, i = 1, result = 0;

cout<<"Input n,m,k1,k2。"<<endl;

do

{

cin>> n >> m >> k1 >> k2;

}

while(n * m % 2 != 0 || k1 < 0 || k2 < 0);

int grid[n][m];

for(int i = 0; i < n; ++i)

{

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

{

grid[i][j] = 0x00;

}

}

Hashima(grid[0], &x, &y, &n, &m, &i, &k1, &k2, &result);

cout<<"The result is:"<<result<<endl;

cin.get();

return 0;

}

Point FindHashima(int hashimaIndex, int* grid, int* n, int* m)

{

Point hashima;

for(int y = 0; y < *n; ++y)

{

for(int x = 0; x <= *m; ++x)

{

if(*(grid + y * *m + x) == hashimaIndex)

{

hashima.x = x;

hashima.y = y;

}

}

}

return hashima;

}

void Hashima(int* grid, int* x, int* y, int* n, int* m, int* i, int* k1, int* k2, int* result)

{

*(grid + *y * *m + *x) = *i;

if(*i == *n * *m)

{

int maxXumingTime = 0, xumingTime;

for(int hashimaA = 1; hashimaA <= *m * *n / 2; hashimaA++)

{

Point A = FindHashima(hashimaA, grid, n, m);

Point B = FindHashima(hashimaA + *m * *n / 2, grid, n, m);

xumingTime = *k1 * abs(A.y - B.y) + *k2 * abs(A.x - B.x);

if(xumingTime > maxXumingTime)

{

maxXumingTime = xumingTime;

}

}

if(*result == 0 || maxXumingTime < *result)

{

*result = maxXumingTime;

}

}

else

{

if(*x + 1 <= *m - 1 && !(*(grid + *y * *m + *x + 1)))

{

*i += 1;

*x += 1;

Hashima(grid, x, y, n, m, i, k1, k2, result);

*x -= 1;

*i -= 1;

}

if(*y + 1 <= *n - 1 && !(*(grid + *y * *m + *x + *m)))

{

*i += 1;

*y += 1;

Hashima(grid, x, y, n, m, i, k1, k2, result);

*y -= 1;

*i -= 1;

}

if(*x - 1 >= 0 && !(*(grid + *y * *m + *x - 1)))

{

*i += 1;

*x -= 1;

Hashima(grid, x, y, n, m, i, k1, k2, result);

*x += 1;

*i -= 1;

}

if(*y - 1 >= 0 && !(*(grid + *y * *m + *x - *m)))

{

*i += 1;

*y -= 1;

Hashima(grid, x, y, n, m, i, k1, k2, result);

*y += 1;

*i -= 1;

}

}

*(grid + *y * *m + *x) = 0;

return;

}

2014年的時候,我發表過《使用七牛云存储加速下载Gravatar头像的方法》,其中利用的是七牛雲存儲的鏡像存儲功能。我當时之所以選擇七牛,是因為很多人也在用七牛。這其實是一種跟風的劣根的體現,需要自省。

此話怎講?

七牛雲存儲,是一種對象存儲服務,顧名思義,是用來存儲對象用的,類似於阿里雲的對象存儲(OSS)。其中,「對象」的定義比較狹義,就七牛與阿里雲的實現來看,存儲的「對象」是文件,也就是要有惟一的前綴(目錄)與文件名,不能含有參數。即使用戶請求的URI含有參數,回源抓取後存儲的文件的文件名也是不含參數的。當用戶再次請求並命中緩存後,URI中的參數就會被自動忽略。

也正是因此,使用七牛雲存儲加速Gravatar頭像的獲取會出現一些詭異的問題。眾所周知,Gravatar提供了數種默認頭像,均可以在用戶未上傳對應頭像圖片時用以臨時填充,而決定具體採用哪一種默認頭像的,則正是向Gravatar頭像圖片接口傳送的URI參數。對參數的忽略,就是對具體請求內容的忽略。從這個意義上來講,七牛雲存儲是不適合用來加速含有有效參數的圖片資源的獲取的。

按照這個思路,加速Gravatar頭像的獲取不能用「(對象)存儲」一類的雲服務,而應該用為緩存某個固定URI而生的CDN類服務。CDN類服務除了存儲的「對象」的性質與對象存儲類服務不同外,還具有的一項特性是「緩存」。與以七牛為代表的對象存儲服務不同,「緩存」是有期限的,目標的「緩存」可以在到期後自動移除,覆蓋以最新的內容(如果可能)。頭像是會更新的,CDN類服務的這一特性恰好迎合了加速Gravatar頭像的獲取的需求。所以,CDN類服務纔是加速Gravatar頭像的獲取的最優選擇。

恰逢中國政府對互聯網自由的壓制不斷加強,Gravatar頭像的官方獲取接口幾乎被全部封鎖,其中苟延殘喘的「cn.gravatar.com」速度也不理想,我們得以應用這項技術,加速Gravatar頭像的獲取。這也算是一種無聲的對抗罷。使用阿里雲CDN為Gravatar頭像獲取接口建立鏡像非常容易,下面介紹大致的方法。

首先,你要有一個阿里雲賬戶和一個通過阿裡雲接入並完成ICP備案的域名,然後在阿里雲的管理控制臺的「CDN」選項卡中添加一個加速域名,加速域名就是要用來訪問的域名,可以是一個二級域名,如我用的「gcache.papwin.com」,源站填寫一個已有的穩定可靠的非官方Gravatar頭像獲取接口(要確保中國內地可以正常訪問),提交並通過審核後,將回源域名設置為源站域名,再將加速域名以CNANE的方式解析到阿里雲提供的CDN域名上去。最後,在緩存規則中添加一條「/avatar」目錄,緩存時間可以稍設長一些,我設置的是一個月。至此,基於阿里雲CDN的Gravatar加速鏡像就建立好了。

一些虛擬主機或其類似物,如阿里雲的「彈性Web託管」,是不支持通過常規方法為不同域名分別指定根目錄的,給需要將多個不同域名的網站託管在一處的客戶帶來不便。一般來說,虛擬主機或其類似物的終端客戶不具有母機的控制權,一定程度上制約了伺服器軟體(如Apache)功能的發揮,好在Apache提供了一種用戶在其可及之目錄下編纂「.htaccess」文件來局部應用某些設定的方法,我們可以藉此啟用mod_rewrite,通過自訂重寫規則來為多個域名分別「虛構」各自的根目錄。稍有常識的人對Apache的mod_rewrite都不陌生,它常用於偽靜態的實現,它的實質其實是一個在客戶端請求被接受後、伺服器腳本被執行或直接返回對應靜態文件前竄改請求的文件名的「插件」,具有多種應用方向,是生產生活中不可或缺的法寶。

下面以本站為例,介紹分別為imgsrc.papwin.com、verify.papwin.com和cee.papwin.com三個子域名虛構根目錄的代碼。

<IfModule mod_rewrite.c>

RewriteEngine On
RewriteBase /

# wordpress 之偽靜態實現,與本文內容無干
RewriteRule ^index.php$ - [L]
RewriteCond %{HTTP_HOST} ^(www.)?papwin.com$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]

#為 imgsrc.papwin.com 虛構根目錄
RewriteCond %{HTTP_HOST} ^imgsrc.papwin.com$
RewriteCond %{REQUEST_URI} !^/imgsrc/
RewriteRule ^(.*)$ /imgsrc/$1 [L]

#為 verify.papwin.com 虛構根目錄
RewriteCond %{HTTP_HOST} ^verify.papwin.com$
RewriteCond %{REQUEST_URI} !^/verify/
RewriteRule ^(.*)$ /verify/$1 [L]

#為 cee.papwin.com 虛構根目錄
RewriteCond %{HTTP_HOST} ^cee.papwin.com$
RewriteCond %{REQUEST_URI} !^/cee/
RewriteRule ^(.*)$ /cee/$1 [L]

</IfModule>

本站的訪客過濾系統已上線並已穩定運行。為造福人民,現將訪客過濾系統的源碼放出來。這套系統編寫於2014年暑假,旨在保障網站信息安全,亦可用於ICP報備時屏蔽管局所在地的訪問請求,確保備案順利通過審核。

本套系統設計精良,功能完備,不僅可以直接屏蔽固定的IP位址(滋詞正則表達式),還可以輸入要屏蔽的地區(國、省、市、縣,亦滋詞正則表達式)、運營商的名稱(還是滋詞正則表達式),由該系統自動查詢IP位址歸屬地並實施屏蔽。本系統甚至還附帶了防止用戶瘋狂F5的功能。因我編寫該套系統時畢竟圖樣,代碼可能略顯笨拙,請勿見笑。

本系統的具體原理、配置方式請自行研究,部分代碼也可能需要修改以適配不同的需求。我沒時間精力註解了,見諒。

下載:本地下載

近期,我发现本站部分文章页面打开速度奇慢,在文章正文等内容都显示出来后标签页上的加载标志还在转啊转,要数秒后才加载完成。奇怪的是,文章里既没有插入图片,也没有引用其他需要长时间加载的资源,且有的文章页加载得快,有些文章页加载得慢,这是为什么呢?为了查明原因,我使用Chrome自带的开发者工具跟踪页面的加载过程,终于发现了问题所在。原来,加载速度慢的文章下有较多的评论,而每个评论者都有头像,WordPress使用Gravatar头像,而WordPress采用的4个Gravatar头像服务器都在美国,连接和传输数据都较慢。机智的我想到了可以巧妙利用七牛云存储来缓存头像文件,以达到提高Gravatar头像下载速度的目的。

[查看全文]