一区二区三区三上|欧美在线视频五区|国产午夜无码在线观看视频|亚洲国产裸体网站|无码成年人影视|亚洲AV亚洲AV|成人开心激情五月|欧美性爱内射视频|超碰人人干人人上|一区二区无码三区亚洲人区久久精品

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

鴻蒙元服務(wù)實(shí)戰(zhàn)-笑笑五子棋(4)

萬(wàn)少 ? 來(lái)源:jf_22972444 ? 作者:jf_22972444 ? 2025-03-31 09:31 ? 次閱讀

鴻蒙元服務(wù)實(shí)戰(zhàn)-笑笑五子棋(4)

我們?cè)谶@一章節(jié)主要實(shí)現(xiàn)五子棋的基本邏輯

核心目錄結(jié)構(gòu)

├─ets
│ ├─entryability
│ │ EntryAbility.ets
│ │
│ ├─entryformability
│ │ EntryFormAbility.ets
│ │
│ ├─pages
│ │ Index.ets
│ │
│ ├─views
│ │ About.ets
│ │ Home.ets
│ │
│ └─widget
│ └─pages
│ WidgetCard.ets

└─resources
├─base
│ ├─element
│ │ color.json
│ │ float.json
│ │ string.json
│ │
│ ├─media
│ │ right.svg
│ │ startIcon.png
│ │
│ └─profile
│ form_config.json
│ main_pages.json

├─en_US
│ └─element
│ string.json

├─rawfile
└─zh_CN
└─element
string.json

## 沉浸式設(shè)計(jì)

![image-20250105111010688](https://wsy996.obs.cn-east-3.myhuaweicloud.com/%E9%B8%BF%E8%92%99%E5%85%83%E6%9C%8D%E5%8A%A1%E5%AE%9E%E6%88%98-%E7%AC%91%E7%AC%91%E4%BA%94%E5%AD%90%E6%A3%8B/%E9%B8%BF%E8%92%99%E5%85%83%E6%9C%8D%E5%8A%A1%E5%AE%9E%E6%88%98-%E7%AC%91%E7%AC%91%E4%BA%94%E5%AD%90%E6%A3%8B%EF%BC%884%EF%BC%89/%E9%B8%BF%E8%92%99%E5%85%83%E6%9C%8D%E5%8A%A1%E5%AE%9E%E6%88%98-%E7%AC%91%E7%AC%91%E4%BA%94%E5%AD%90%E6%A3%8B%EF%BC%884%EF%BC%89.assets/image-20250105111010688.png?x-image-process=style/style-8860)

1. `entry/src/main/ets/entryability/EntryAbility.ets` 中統(tǒng)一設(shè)置

   ```javascript
     onWindowStageCreate(windowStage: window.WindowStage): void {
       windowStage.getMainWindow()
         .then(windowClass = > {
           // 設(shè)置沉浸式
           windowClass.setWindowLayoutFullScreen(true)

           // 頂部狀態(tài)欄
           const topAvoidArea = windowClass.getWindowAvoidArea(window.AvoidAreaType.TYPE_SYSTEM);
           const topRectHeight = topAvoidArea.topRect.height;
           // px轉(zhuǎn)vp
           const vpTopHeight = px2vp(topRectHeight)

           // 底部導(dǎo)航條
           const bottomAvoidArea = windowClass.getWindowAvoidArea(window.AvoidAreaType.TYPE_NAVIGATION_INDICATOR);
           const bottomRectHeight = bottomAvoidArea.bottomRect.height;
           const vpBottomHeight = px2vp(bottomRectHeight)

           AppStorage.setOrCreate('topRect', vpTopHeight)
           AppStorage.setOrCreate('bottomRect', vpBottomHeight)
         })
       windowStage.loadContent('pages/Index', (err) = > {
         // ...
       });
     }
  1. 頁(yè)面通過(guò) padding 避開頂部和底部

    @StorageProp("topRect")
      topRect: number = 0
      @StorageProp("bottomRect")
      bottomRect: number = 0
      build() {
        Column() {
    	// ...
        }
        .width('100%')
        .height('100%')
        .linearGradient({
          colors: [["#DEF9ED", 0], ["#F4F5F7", 0.4]]
        })
        .padding({
          top: this.topRect,
          bottom: this.bottomRect
        })
      }
    

    image-20250105111545129

AtomicServiceTabs

AtomicServiceTabs是元服務(wù)獨(dú)有的 tab 組件。Tabs組件后續(xù)不再支持在元服務(wù)中進(jìn)行使用。,對(duì) Tabs 組件一些不需提供給用戶自定義設(shè)計(jì)的屬性進(jìn)行簡(jiǎn)化,限制最多顯示 5 個(gè)頁(yè)簽,固定頁(yè)簽樣式,位置和大小。

image-20250105111747871

基本用法

AtomicServiceTabs({
  // 內(nèi)容
  tabContents: [
    () = > {
      // 自定義構(gòu)建函數(shù)
      this.tabContent1();
    },
    () = > {
      // 自定義構(gòu)建函數(shù)
      this.tabContent2();
    },
  ],
  // 標(biāo)題
  tabBarOptionsArray: [
    new TabBarOptions(
      $r("sys.media.save_button_picture"),
      "玩吧",
      "#666",
      "#07C160"
    ),
    new TabBarOptions($r("sys.media.AI_keyboard"), "關(guān)于", "#666", "#07C160"),
  ],
  // 標(biāo)題顯示的位置
  tabBarPosition: TabBarPosition.BOTTOM,
  // 背景顏色
  barBackgroundColor: 0xffffff,
});

Home 和 About

image-20250105112201927

Home 表示首頁(yè),用來(lái)顯示主要內(nèi)容

About 表示關(guān)于,用來(lái)存放項(xiàng)目的基本信息

他們目前都是普通的組件,分別放在 tabContent1 和 tabContent2 內(nèi)

引入 canvas

在 Home 中開始引入canvas

@Component
export struct Home {
  settings: RenderingContextSettings = new RenderingContextSettings(true);
  ctx: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings);

  build() {
    Column() {
      Canvas(this.ctx)
        .width(width)
        .height(width)
        .backgroundColor(Color.Orange)
    }
    .width("100%")
    .height("100%")
    .justifyContent(FlexAlign.Center)
  }
}

繪制棋盤

image-20250105145524700

繪制棋盤的思路如下:

  1. 確定要繪制多少個(gè)格子。
  2. 每一個(gè)格子多大

這里的想法比較簡(jiǎn)單:

  1. 確定要繪制的格子是 15 個(gè)。
    gridSize: number = 15;
    
  2. 每一個(gè)格多大,由屏幕寬度決定。比如屏幕寬度的 90%,然后分成 15 份。每一份就是格子的寬度
    // 獲取屏幕的寬度的 90%
    const width = px2vp(display.getDefaultDisplaySync().availableWidth) * 0.9;
    // 棋盤是正方形的,所以高度和寬度相等
    const height = width;
    
    cellSize: number = width / this.gridSize;
    
  3. 然后封裝描繪畫面的方法 drawBoard
// 繪制棋盤
drawBoard = () = > {
  this.ctx.clearRect(0, 0, width, height);
  // 繪制網(wǎng)格
  this.ctx.strokeStyle = "#000";
  this.ctx.lineWidth = 1;
  for (let i = 0; i < this.gridSize; i++) {
    this.ctx.beginPath();
    this.ctx.moveTo(this.cellSize * i, 0);
    this.ctx.lineTo(this.cellSize * i, height);
    this.ctx.stroke();

    this.ctx.beginPath();
    this.ctx.moveTo(0, this.cellSize * i);
    this.ctx.lineTo(width, this.cellSize * i);
    this.ctx.stroke();
  }
};
  1. canvas 準(zhǔn)備好的時(shí)候開始繪制
    Canvas(this.ctx)
      .width(width)
      .height(width)
      .backgroundColor(Color.Orange)
      .onReady(() = > {
        this.drawBoard();
      });
    

點(diǎn)擊下棋

點(diǎn)擊下棋要是做挺多的處理的,比如:

  1. 當(dāng)前是下黑棋還是白棋
  2. 下完這一子之后,勝利了還是繼續(xù)下。

我們開始吧:

  1. 初始化棋盤數(shù)據(jù),它是一個(gè)二維數(shù)組,下棋的時(shí)候,其實(shí)也是往里面填充內(nèi)容
    // 棋盤數(shù)據(jù)
      board: number[][] = []
    
  2. 初始化當(dāng)前下棋的角色 設(shè)定 1:黑旗 ,2:白旗
    currentPlayer: number = 1; // 當(dāng)前玩家 (1: 黑子, 2: 白子)
    
  3. 聲明初始化棋盤的函數(shù),負(fù)責(zé)初始化棋盤數(shù)據(jù)和描繪棋盤
    initGame = () = > {
        this.board = []
        for (let index = 0; index < this.gridSize; index++) {
          const arr: number[] = []
          for (let index2 = 0; index2 < this.gridSize; index2++) {
            //  0 表示當(dāng)前沒(méi)有人在下棋
            arr.push(0)
          }
          this.board.push(arr)
        }
        // this.currentPlayer = 1;
        // this.gameOver = false;
        // this.textContent = '輪到黑子落子';
        this.drawBoard();
      }
    
     -------------------
       Canvas(this.ctx)
        .width(width)
        .height(width)
        .backgroundColor(Color.Orange)
        .onReady(() = > {
          this.initGame()
        })
    
  4. 聲明點(diǎn)擊棋盤事件,事件中執(zhí)行下棋邏輯
    handleClick = async (event: ClickEvent) = > {
      const x = event.x;
      const y = event.y;
    
      const col = Math.floor(x / this.cellSize);
      const row = Math.floor(y / this.cellSize);
    
      if (this.board[row] && this.board[row][col] === 0) {
        this.board[row][col] = this.currentPlayer;
        this.drawBoard();
        this.currentPlayer = this.currentPlayer === 1 ? 2 : 1;
      } else {
        promptAction.showToast({ message: `請(qǐng)點(diǎn)擊中棋盤對(duì)位位置` });
      }
    };
    
  5. 調(diào)整 drawBoard 函數(shù),根據(jù) this.board[row][col] 描繪出旗子
    // 繪制棋盤
    drawBoard = () = > {
      this.ctx.clearRect(0, 0, width, height);
    
      // 繪制網(wǎng)格
      this.ctx.strokeStyle = "#000";
      this.ctx.lineWidth = 1;
      for (let i = 0; i < this.gridSize; i++) {
        this.ctx.beginPath();
        this.ctx.moveTo(this.cellSize * i, 0);
        this.ctx.lineTo(this.cellSize * i, height);
        this.ctx.stroke();
    
        this.ctx.beginPath();
        this.ctx.moveTo(0, this.cellSize * i);
        this.ctx.lineTo(width, this.cellSize * i);
        this.ctx.stroke();
      }
      // 繪制已落的棋子
      for (let row = 0; row < this.gridSize; row++) {
        for (let col = 0; col < this.gridSize; col++) {
          if (this.board[row][col] !== 0) {
            this.ctx.beginPath();
            this.ctx.arc(
              col * this.cellSize + this.cellSize / 2,
              row * this.cellSize + this.cellSize / 2,
              this.radius,
              0,
              2 * Math.PI
            );
            this.ctx.fillStyle = this.board[row][col] === 1 ? "black" : "white";
            this.ctx.fill();
            this.ctx.stroke();
          }
        }
      }
    };
    
  6. 效果
    PixPin_2025-01-05_15-20-57

判斷輸贏

五子棋判斷輸贏的方法比較簡(jiǎn)單,只需要知道是否有五子連珠就行

  1. 定義判斷輸贏的方法 checkWin

    // 判斷是否有五子連珠
        checkWin = (row: number, col: number) = > {
          // 定義一個(gè)接口abc,用于表示方向相關(guān)的偏移量,dr表示行方向的偏移量,dc表示列方向的偏移量
          interface abc {
            dr: number
            dc: number
          }
    
          // 定義一個(gè)包含四個(gè)方向偏移量信息的數(shù)組,分別對(duì)應(yīng)不同的檢查方向
          const directions: abc[] = [
            { dr: 0, dc: 1 }, // 水平方向,行偏移量為0,列偏移量為1,即向右檢查
            { dr: 1, dc: 0 }, // 垂直方向,行偏移量為1,列偏移量為0,即向下檢查
            { dr: 1, dc: 1 }, // 主對(duì)角線方向,行和列偏移量都為1,向右下方向檢查
            { dr: 1, dc: -1 }// 副對(duì)角線方向,行偏移量為1,列偏移量為 -1,即向右上方向檢查
          ];
    
          // 遍歷四個(gè)不同的方向,依次檢查每個(gè)方向上是否有五子連珠情況
          for (let i = 0; i < directions.length; i++) {
            const dr = directions[i].dr;
            const dc = directions[i].dc;
            let count = 1;
    
            // 向一個(gè)方向檢查(從當(dāng)前落子位置開始,沿著指定方向向前檢查)
            // 循環(huán)嘗試查找連續(xù)相同顏色的棋子,最多查找連續(xù)4個(gè)(因?yàn)橐呀?jīng)有當(dāng)前落子算1個(gè)了,湊夠5個(gè)判斷贏)
            for (let i = 1; i < 5; i++) {
              let r = row + dr * i;
              let c = col + dc * i;
              // 判斷當(dāng)前位置是否在棋盤范圍內(nèi),并且此位置的棋子顏色是否和當(dāng)前玩家的棋子顏色相同
              if (r >= 0 && r < this.gridSize && c >= 0 && c < this.gridSize && this.board[r][c] === this.currentPlayer) {
                count++;
              } else {
                break;
              }
            }
    
            // 向另一個(gè)方向檢查(從當(dāng)前落子位置開始,沿著指定方向的反方向檢查)
            // 同樣循環(huán)嘗試查找連續(xù)相同顏色的棋子,最多查找連續(xù)4個(gè)
            for (let i = 1; i < 5; i++) {
              let r = row - dr * i;
              let c = col - dc * i;
              if (r >= 0 && r < this.gridSize && c >= 0 && c < this.gridSize && this.board[r][c] === this.currentPlayer) {
                count++;
              } else {
                break;
              }
            }
    
            // 如果在當(dāng)前方向(正方向和反方向結(jié)合起來(lái))上連續(xù)相同顏色的棋子數(shù)量達(dá)到或超過(guò)5個(gè),則表示當(dāng)前玩家勝利
            if (count >= 5) {
              return true;
            }
          }
    
          // 如果遍歷完所有方向都沒(méi)有出現(xiàn)五子連珠的情況,則返回false,表示當(dāng)前落子未形成勝利局面
          return false;
        }
    
  2. 在點(diǎn)擊下棋時(shí) 判斷是否輸贏 handleClick

    if (this.board[row] && this.board[row][col] === 0) {
          this.board[row][col] = this.currentPlayer;
          this.drawBoard();
    
          if (this.checkWin(row, col)) {  // 執(zhí)行后續(xù)邏輯
    
  3. handleClick中判斷輸贏后,再做后續(xù)的一些小邏輯

    1. 如 還沒(méi)決定輸贏,繼續(xù)下棋
    2. 決定輸贏了,彈出對(duì)話框恭喜勝利者, 詢問(wèn)是否還要再下一盤。。
    3. 完整代碼
    // 處理玩家落子
    handleClick = async (event: ClickEvent) = > {
      if (this.gameOver) {
        return;
      }
    
      const x = event.x;
      const y = event.y;
    
      const col = Math.floor(x / this.cellSize);
      const row = Math.floor(y / this.cellSize);
    
      if (this.board[row] && this.board[row][col] === 0) {
        this.board[row][col] = this.currentPlayer;
        this.drawBoard();
    
        if (this.checkWin(row, col)) {
          this.textContent =
            this.currentPlayer === 1 ? "黑子勝利!" : "白子勝利!";
          this.gameOver = true;
          // AlertDialog.show({ message: this.textContent })
          const res = await promptAction.showDialog({
            title: this.textContent,
            message: "重新再來(lái)一盤嗎",
            buttons: [
              { text: "不了", color: "#000" },
              { text: "來(lái)吧", color: "#0094ff" },
            ],
          });
          if (res.index === 1) {
            this.initGame();
          }
        } else {
          this.currentPlayer = this.currentPlayer === 1 ? 2 : 1;
          this.textContent =
            this.currentPlayer === 1 ? "輪到黑子落子" : "輪到白子落子";
        }
      } else {
        promptAction.showToast({ message: `請(qǐng)點(diǎn)擊中棋盤對(duì)位位置` });
      }
    };
    
  4. 效果
    PixPin_2025-01-05_15-36-24

總結(jié)

本章節(jié)多了一些業(yè)務(wù)的具體實(shí)現(xiàn),尤其是下棋的一些邏輯處理上。

如果你興趣想要了解更多的鴻蒙應(yīng)用開發(fā)細(xì)節(jié)和最新資訊,歡迎在評(píng)論區(qū)留言或者私信或者看我個(gè)人信息,可以加入技術(shù)交流群。

審核編輯 黃宇

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • Canvas
    +關(guān)注

    關(guān)注

    0

    文章

    20

    瀏覽量

    11143
  • 鴻蒙
    +關(guān)注

    關(guān)注

    57

    文章

    2469

    瀏覽量

    43642
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    labview五子棋程序

    本帖最后由 桂花酒 于 2012-6-10 13:43 編輯 labview五子棋程序,想用的可以看看!本來(lái)是發(fā)的求助帖,找五子棋程序,不過(guò)剛才下了一個(gè),鑒于論壇上現(xiàn)在已經(jīng)搜不著了(我原來(lái)下過(guò),不過(guò)刪了)一起學(xué)習(xí)!
    發(fā)表于 06-10 13:16

    五子棋的棋盤怎么么做

    做課程設(shè)計(jì),五子棋的棋盤怎么做
    發(fā)表于 07-02 23:18

    五子棋主程序前面板怎么設(shè)計(jì)

    五子棋主程序前面板怎么設(shè)計(jì)?后面版有程序了
    發(fā)表于 07-03 16:39

    用Verilog寫的一個(gè)五子棋

    在期末EDA課答辯之際寫了一個(gè)五子棋的代碼,主要用到了VGA和PS2接口的外設(shè),因?yàn)樵谧约呵玫臅r(shí)候來(lái)網(wǎng)上找過(guò),沒(méi)找到有關(guān)的資料,所以自己寫好之后就想發(fā)上來(lái)和大家討論下?;緦?shí)現(xiàn)了雙人對(duì)戰(zhàn)五子棋的功能。感覺(jué)有很多紕漏,想請(qǐng)大家指點(diǎn)下。
    發(fā)表于 06-15 14:40

    五子棋

    求一個(gè)五子棋的程序
    發(fā)表于 06-26 16:09

    五子棋

    自己做的五子棋,說(shuō)不上有什么難的
    發(fā)表于 08-12 21:44

    labview 虛擬五子棋

    `一個(gè)簡(jiǎn)易的五子棋程序,喜歡的可以借鑒下`
    發(fā)表于 06-16 21:57

    怎樣去設(shè)計(jì)一種人機(jī)對(duì)弈五子棋程序

    五子棋游戲應(yīng)達(dá)到幾方面的要求?怎樣去設(shè)計(jì)一種人機(jī)對(duì)弈五子棋程序?
    發(fā)表于 09-29 07:26

    五子棋程序源代碼-Matlab實(shí)現(xiàn)

    五子棋程序源代碼-M
    發(fā)表于 07-04 16:15 ?50次下載

    用java語(yǔ)言編寫的智能五子棋源程序

    用java語(yǔ)言編寫的智能五子棋源程序
    發(fā)表于 10-30 10:31 ?98次下載
    用java語(yǔ)言編寫的智能<b class='flag-5'>五子棋</b>源程序

    C語(yǔ)言五子棋

    C語(yǔ)言五子棋,有趣的東西,值得玩玩,不用看著黑框發(fā)呆
    發(fā)表于 01-12 16:49 ?2次下載

    Delphi教程_使用DrawGrid控件制作五子棋

    Delphi教程使用DrawGrid控件制作五子棋,很好的Delphi的學(xué)習(xí)資料。
    發(fā)表于 03-16 14:55 ?19次下載

    C語(yǔ)言教程之五子棋游戲的問(wèn)題

    C語(yǔ)言教程之五子棋游戲的問(wèn)題,很好的C語(yǔ)言資料,快來(lái)學(xué)習(xí)吧。
    發(fā)表于 04-25 17:07 ?0次下載

    基于LabVIEW的五子棋博弈算法

    針對(duì)目前五子棋人機(jī)對(duì)弈多數(shù)基于電腦、手機(jī),缺少真實(shí)環(huán)境的問(wèn)題,提出一種基于LabVIEW的博弈算法,并運(yùn)用于真實(shí)的五子棋人機(jī)對(duì)弈。首先通過(guò)圖像采集系統(tǒng)獲取當(dāng)前狀態(tài)下棋盤及人機(jī)雙方棋子的位置信息;然后
    發(fā)表于 12-17 11:32 ?29次下載

    鴻蒙服務(wù)實(shí)戰(zhàn)-笑笑五子棋(1)

    鴻蒙服務(wù)實(shí)戰(zhàn)-笑笑五子棋(1) 前言 作為鴻蒙應(yīng)用的深度開發(fā)者都應(yīng)該知道,經(jīng)歷了 波瀾壯闊 1
    的頭像 發(fā)表于 03-31 09:23 ?182次閱讀
    <b class='flag-5'>鴻蒙</b><b class='flag-5'>元</b><b class='flag-5'>服務(wù)實(shí)戰(zhàn)</b>-<b class='flag-5'>笑笑</b><b class='flag-5'>五子棋</b>(1)