本課簡介
來到五子棋系列第四課囉!這課的目標在於讓程式能夠辨識棋盤上的交叉點
讓程式能夠知道玩家是否正在將棋子放到正確的位置上
這對接下來的課程要實作的放棋子以及勝負判斷都很有幫助!
教學影片
注意:影片有高畫質 720P 的選項,可以看得更清楚喔!重點提示
製作重點
- 本課目標:判斷點按的位置是否為交叉點上或附近,並改變游標圖案提示使用者。
- 將棋盤的交叉點用二為座標表示。越往右,X 座標越高;越往下,Y 座標越高。
- 建議將預計完成的主要目標用註解寫進 method 裡面,再開始撰寫程式碼。
- 計算一個位置 X 靠近哪個點的方法如下 (Offset 代表棋盤到邊界的距離,Distance 代表相鄰兩點的距離,R 代表多靠近一個點會被判斷在「附近」):
- 首先計算 (X - Offset) ÷ Distance 取得商數與餘數,商數代表左邊的點的編號,餘數代表與左邊的點的距離。
- 判斷餘數是否小於等於 R,是的話代表 X 靠近左邊的點,回傳商數。
- 判斷餘數是否大於等於 Distance - R,是的話代表靠近右邊的點,回傳商數+1。
製作步驟
- 新增一個名為 Board 的 class 用來負責關於棋盤的操作,以下操作都在 Board 內進行。
- 新增一個 public method,CanBePlaced(int x, int y),回傳 bool。
- 新增一個 private method,FindTheClosetNode(int x, int y),回傳 Point。
- 新增一個 private method,FindTheClosetNode(int pos),回傳 int。
- 新增三個常數,int OFFSET = 75, int NODE_RADIUS = 10, int NODE_DISTANCE = 75。
- 在第 4 步驟新增的 method 中實作「製作重點」第 4 點中的演算法。
- 新增一個常數 Point NO_SUCH_NODE = new Point(-1, -1),代表沒有找到符合的交叉點。
- 在第 3 步驟新增的 method 中分別計算最靠近 x, y 的交叉點。
- 實作第 2 步驟新增的 method。
- 利用剛剛寫好的 method 找到最近的交叉點
- 沒有的話回傳 false,有的話回傳 true
- 在 Form1 中新增一個事件 MouseMove 的 method。
- 在 Form 1 新增一個 Board 物件。
- 在第 10 步新增的 method 中,藉由呼叫 board.CanBePlaced(x, y) 來判斷是否可以放棋子。
- 如果可以的話,將游標設為手。
- 如果不行的話,將游標設為預設圖案。
- 解決游標在邊界也會變成手的問題。
- 在 FindTheClosetNode 增加一個判斷,檢查座標是否在 (Offset - R) 之外。如果是的話就直接回傳 -1。
小山老師菩薩方便時可否隨附一下您的程式碼好供末學錄至VS研參。感恩感恩 南無阿彌陀佛
回覆刪除讚讚讚!
回覆刪除祈請小山老師菩薩有空也教教我們如何利用程式畫精準的棋盤吧 感恩感恩 南無阿彌陀佛
回覆刪除非常期待山神接下來五子棋的續集
回覆刪除一個月了,期待續集。
回覆刪除一個月了,期待續集。
回覆刪除小山老师好,直接使用鼠标事件的坐标应该是显示屏幕的坐标吧?项目应用的应该是窗体内的坐标,定义的offset =75 也是以窗体为参考系计算的吧?程序里面是怎么设置的?没有看到你的设置,我是这样处理后就正确了oint formPoint = this.PointToClient(Control.MousePosition);//设置窗体控件内的鼠标坐标
回覆刪除Board board = new Board();
if (board.CanBePlaced(formPoint.X, formPoint.Y))
{
this.Cursor = Cursors.Hand;
}
else
{
this.Cursor = Cursors.Default;
}
老師您好,請問return後面的quotient,為什麼顯示錯誤,「無法將類型int,隱含轉換成system.Drawing.point」,上網查詢後只有說要加using System.Drawing,這個我也有加了。
回覆刪除private Point FindTheClosetNode(int pos)
{
pos -= OFFSET;
int quotient = pos / NODE_DISTRANCE;
int remainder = pos % NODE_DISTRANCE;
if (remainder <= NODE_RADIUS)
return quotient;
else if (remainder >= NODE_DISTRANCE - NODE_RADIUS)
return quotient + 1;
else
return -1;
重新看完影片找到原因了,private Point FindTheClosetNode(int pos),這一段要宣告成int,private int FindTheClosetNode(int pos)。謝謝老師的教學。
刪除