2018年1月13日 星期六

小山的 C# 教學-第44課-五子棋小遊戲(五)-正確放置棋子

本課簡介

本課為五子棋系列第五課
此次的製作重點在於讓棋子能夠正確地出現在交叉點上

教學影片

注意:影片有高畫質 720P 的選項,可以看得更清楚喔!



重點提示


製作重點

  • 本課目標:讓棋子正確無誤地顯示在交叉點上
  • 注意若直接用滑鼠點按的座標來建立棋子,則棋子可能會有點歪歪的
  • 為了正確判斷是否同一個位置有放過棋子,棋盤必須要記錄之前放置的棋子
  • 若程式碼出現重複的模式,那就代表可能有可以寫得更簡潔的地方

製作步驟

  1. 新增一個 enum,並命名為 PieceType,裡面包含 BLACK 與 WHITE 兩種數值
  2. 在 Board 內新增一個 public method,PlaceAPiece(int x, int y, PieceType type),回傳 Piece
  3. 將 CanBePlaced 的內容複製到 PlaceAPiece 裡面
  4. 在 Board 內建立一個 9x9 的二維陣列 pieces
  5. 修改 PlaceAPiece 的內容
    1. 將 return false 改成 return null
    2. 加入利用 pieces 來判斷是否在某個交叉點上已經有放置棋子了
      1. 若已經被放棋子了,就回傳 null
    3. 根據輸入的 PieceType 建立一顆對應顏色棋子
    4. 把該棋子放在 pieces 中對應的位置
    5. 回傳剛才新增的棋子
  6. 在處理視窗滑鼠按下事件的 method 中 (影片中是「Form1_MouseDown」) 新增以下內容
    1. 呼叫 board.PlaceAPiece(...) 並根據 isBlack 給予對應的 PieceType
    2. 若回傳的棋子不是 null,就把棋子放進 this.Controls,並把 isBlack 的值反過來
  7. 因為剛剛寫的 MouseDown 內有重複的模式,所以這邊稍微優化一下
    1. 把 Form1 的 bool isBlack 改成 PieceType nextPieceType,預設是 PieceType.BLACK
    2. 只留下 MouseDown 中上半部的程式碼
    3. 改成把 nextPieceType 傳進 board.PlaceAPiece
    4. 把倒反 isBlack 的程式碼改成倒反 nextPieceType
  8. 在 Board 內加入一個 private method,convertToFormPosition(Point nodeId) 回傳 Point
    • 實作把 NodeId 轉換成視窗座標的功能
  9. 把 convertToFormPosition 加入 PlaceAPiece 中,讓他建立棋子時使用的是交叉點的座標

練習

  1. 怎麼解決滑鼠滑到右邊邊界時,程式會壞掉的問題?
  2. 如果讓程式判斷有五顆同樣顏色的棋子連成一條線?
這兩個問題將在下次課程中解答!

相關資訊連結


C# 教學第 37 課 - switch 與 enum
http://slmtsite.blogspot.tw/2016/10/c-37-switch-enum.html

C# 教學第 16 課 - Value 與 Reference Type
http://slmtsite.blogspot.tw/2013/03/c-16-value-reference-type.html

8 則留言:

  1. 小山老師你好,最近開始在學習C#,那看完你的影片後獲益不少,
    那最近在嘗試自行寫Serial Port的小程式試試,
    不過遇到些問題想請教,
    目前是程式是寫說利用TextBox.text來顯示接收到的資訊
    但因為接收到的資料是放在宣告為byte型別的陣列裡,
    想請問是否有方法可以將陣列裡所有資料轉為string後顯示
    ex:
    Receieve Data = {0x01, 0x02, 0x03, 0x04},
    納在TextBox上顯示"01020304"這樣
    不知小山老師是否有任何建議,謝謝

    回覆刪除
  2. = =
    我都照做但是後來連箭頭都不見了@@

    回覆刪除
  3. 謝謝小山老師,看您的視頻變成一名工程師了!!

    回覆刪除
  4. 謝謝小山老師的教學,但我把return quotient +=1;改成return quotient ++;就造成計算錯誤是為何呢?如下。
    private int findTheCloseNode(int pos)
    {
    if (pos < OFFSET - NODE_RADIUS)
    return -1;

    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 ++;
    else
    return -1;
    }

    回覆刪除
    回覆
    1. 因為小山老師,那一行的程式碼,其實是 return quotient + 1;
      返回的值是 quotient +1

      你使用return quotient++;
      那返回的值是 quotient而已,可以google一下,i++和++i差在哪邊
      如果你用return ++quotient; 才可以返回+1的值

      刪除
    2. 計算結果和預期不同時的Debug,小山老師第12課有教過
      用這個可以一步一步執行,從數值的變化,找出問題點

      刪除
  5. 小山老師,有一個問題請教
    發現五子棋這個例子,似乎不用實作判斷mousedown的位置,是否已有棋子
    在老師進行到那個步驟之前,棋子就已經不能重覆放了

    用老師教的debug方法測試,發現可能是因為棋子的大小比NODE_RADIUS還大
    所以放了一個棋子後,同一個位置沒辦法觸發mousedown,會被前方的棋子擋住
    是否是這個原因呢?
    承上,那是否有辦法讓我們add上去的物件,不要擋住後form1的事件觸發

    感謝

    回覆刪除
  6. Borgata Hotel Casino & Spa, Atlantic City - JTM Hub
    The Borgata Hotel Casino 전라남도 출장마사지 & Spa is a AAA Four Diamond Resorts hotel 진주 출장안마 located 의왕 출장샵 in Atlantic 포천 출장마사지 City, New Jersey, United States. 남양주 출장샵

    回覆刪除