HarmonyOS 5.0应用开发——五子棋游戏(鸿蒙版)开发

【高心星出品】

文章目录

五子棋游戏(鸿蒙版)开发

五子棋是一款传统的两人策略型棋类游戏,游戏的目的是在棋盘上首先形成连续的五个同色棋子的玩家获胜。游戏规则简单,易于上手,但要达到高手水平则需要相当的策略和技巧。

基本规则:

  1. 棋盘 :五子棋通常在15×15的棋盘上进行。
  2. 棋子 :棋子分为黑白两色,双方各执一色。
  3. 开局 :黑方先行,之后轮流下子。
  4. 胜局 :第一个在棋盘上形成一个连续的五个同色棋子连线的玩家获胜。

特殊规则:

  • 禁手规则 :在某些比赛规则中,黑方的第一步棋如果落在了棋盘的中心点,或者形成了特定的危险形态,可能会被判定为"禁手",此时黑方需要接受惩罚,通常是白方可以提出和棋。
  • 三连和四连 :在下棋过程中,形成三个或四个连续的棋子通常会获得优势,但需要防范对手利用这些情况形成更长的连子。

五子棋因其规则简单而深受各个年龄层的玩家喜爱,同时也因为其策略性而吸引了一批忠实的棋艺爱好者。希望这些信息能帮助您更好地了解五子棋游戏。

运行效果
开发步骤
项目结构
核心代码
棋盘组件:
javascript 复制代码
import { GameState } from '../model/GameState'
import { display } from '@kit.ArkUI'

@Preview
@Component
export struct GameBoard {
  @Link private gameState: GameState
  @State private boardSize: number = 0
  @State private cellSize: number = 0
  @State private boardPadding: number = 10
  @State private showGameOverDialog: boolean = false
  @State private winnerText: string = ''
   // 五子棋盘 大小,默认全屏
   zwidth:number=0

  private settings:RenderingContextSettings=new RenderingContextSettings(true)
  private canvascontext:CanvasRenderingContext2D=new CanvasRenderingContext2D(this.settings)

 aboutToAppear(): void {
   this.calculateBoardSize()
 }
  /**
   * 计算棋盘大小
   */
  private calculateBoardSize() {
   console.log('gxxt 计算')
    // 获取屏幕宽度
    const screenWidth =this.zwidth==0? px2vp(display.getDefaultDisplaySync().width):this.zwidth
    // 计算棋盘大小,留出边距
    this.boardSize = screenWidth - 2 * this.boardPadding
    // 计算每个格子的大小
    this.cellSize = this.boardSize / (this.gameState.getBoardSize() - 1)
  }
  
  /**
   * 处理点击事件
   * @param event 点击事件
   */
  private handleClick(event: ClickEvent) {
    if (this.gameState.isGameOver()) {
      return
    }
    
    // 计算点击位置对应的棋盘坐标
    const x = event.x
    const y = event.y

    // 计算行列
    const col = Math.round(x / this.cellSize)
    const row = Math.round(y / this.cellSize)
    
    // 尝试落子
    if (this.gameState.makeMove(row, col)) {
      // 检查游戏是否结束
      if (this.gameState.isGameOver()) {
        this.winnerText = this.gameState.getWinner() === 1 ? '黑子胜利!' : '白子胜利!'
        this.showGameOverDialog = true
      }
    }
  }
  
  /**
   * 重新开始游戏
   */
  private restartGame() {
    this.gameState.restart()
    this.showGameOverDialog = false
  }
  
  build() {
    Stack() {
      // 棋盘背景
      Rect()
        .width(this.boardSize + 2 * this.boardPadding)
        .height(this.boardSize + 2 * this.boardPadding)
        .fill('#DEB887') // 木色背景
        .radius(8)
      
      // 棋盘网格
      Canvas(this.canvascontext)
        .width(this.boardSize + 2 * this.boardPadding)
        .height(this.boardSize + 2 * this.boardPadding)
        .onReady(()=>{
          this.onDrawGrid(this.canvascontext)
        })
        .onClick(this.handleClick.bind(this))
      
      // 绘制棋子
      ForEach(this.gameState.getBoard(), (row:number[], rowIndex) => {
        ForEach(row, (cell:number, colIndex) => {
          if (cell !== 0) {
            Circle()
              .fill(cell === 1 ? '#000000' : '#FFFFFF')
              .stroke(cell === 1 ? '#000000' : '#CCCCCC')
              .strokeWidth(1)
              .width(this.cellSize * 0.9)
              .height(this.cellSize * 0.9)
              .position({
                x: this.boardPadding + colIndex * this.cellSize - this.cellSize * 0.45,
                y: this.boardPadding + rowIndex * this.cellSize - this.cellSize * 0.45
              })
          }
        })
      })
      
      // 游戏结束对话框
      if (this.showGameOverDialog) {
        Column() {
          Text(this.winnerText)
            .fontSize(24)
            .fontWeight(FontWeight.Bold)
            .margin({ bottom: 20 })
          
          Button('重新开始')
            .width(120)
            .height(40)
            .backgroundColor('#007DFF')
            .onClick(() => this.restartGame())
        }
        .width(260)
        .height(150)
        .backgroundColor('#FFFFFF')
        .borderRadius(8)
        .justifyContent(FlexAlign.Center)
        .position({
          x: (this.boardSize + 2 * this.boardPadding) / 2 - 130,
          y: (this.boardSize + 2 * this.boardPadding) / 2 - 75
        })
      }
    }
    .width(this.boardSize + 2 * this.boardPadding)
    .height(this.boardSize + 2 * this.boardPadding)
  }

  /**
   * 绘制棋盘网格
   * @param ctx Canvas上下文
   */
  private onDrawGrid(ctx: CanvasRenderingContext2D) {
    const size = this.gameState.getBoardSize()

    // 设置线条样式
    ctx.strokeStyle = '#000000'
    ctx.lineWidth = 1

    // 绘制横线
    for (let i = 0; i < size; i++) {
      const y = this.boardPadding + i * this.cellSize
      ctx.beginPath()
      ctx.moveTo(this.boardPadding,y)
      console.log('gxxt start ',this.boardPadding,'  ',y)
      ctx.lineTo(this.boardPadding + (size - 1) * this.cellSize, y)
      console.log('gxxt end ',this.boardPadding + (size - 1) * this.cellSize,'  ',y)
      ctx.closePath()
      ctx.stroke()
    }

    // 绘制竖线
    for (let i = 0; i < size; i++) {
      const x = this.boardPadding + i * this.cellSize
      ctx.beginPath()
      ctx.moveTo(x, this.boardPadding)
      ctx.lineTo(x, this.boardPadding + (size - 1) * this.cellSize)
      ctx.closePath()
      ctx.stroke()
    }

    // 绘制天元和星位
    const starPoints = [3, 7, 11]
    ctx.fillStyle = '#000000'

    for (const i of starPoints) {
      for (const j of starPoints) {
        const x = this.boardPadding + i * this.cellSize
        const y = this.boardPadding + j * this.cellSize
        ctx.beginPath()
        ctx.arc(x, y, 3, 0, Math.PI * 2)
        ctx.closePath()
        ctx.fill()
      }
    }
  }
} 

游戏棋盘组件(GameBoard.ets):

  • 木色背景的棋盘

  • 网格线和星位点

  • 黑白棋子的显示

  • 点击落子功能

  • 游戏结束对话框

游戏逻辑处理:
java 复制代码
/**
 * 游戏状态管理类
 */
export class GameState {
  // 棋盘大小
  private static readonly BOARD_SIZE: number = 15;
  
  // 棋盘状态:0表示空,1表示黑子,2表示白子
  private board: number[][] = [];
  
  // 当前玩家:1表示黑子,2表示白子
  private currentPlayer: number = 1;
  
  // 游戏是否结束
  private gameOver: boolean = false;
  
  // 胜利者:0表示未结束,1表示黑子胜,2表示白子胜
  private winner: number = 0;
  
  constructor() {
    this.initBoard();
  }
  
  /**
   * 初始化棋盘
   */
  private initBoard(): void {
    this.board = [];
    for (let i = 0; i < GameState.BOARD_SIZE; i++) {
      this.board[i] = [];
      for (let j = 0; j < GameState.BOARD_SIZE; j++) {
        this.board[i][j] = 0;
      }
    }
    this.currentPlayer = 1;
    this.gameOver = false;
    this.winner = 0;
  }
  
  /**
   * 获取棋盘大小
   */
  public getBoardSize(): number {
    return GameState.BOARD_SIZE;
  }
  
  /**
   * 获取棋盘状态
   */
  public getBoard(): number[][] {
    return this.board;
  }
  
  /**
   * 获取当前玩家
   */
  public getCurrentPlayer(): number {
    return this.currentPlayer;
  }
  
  /**
   * 获取游戏是否结束
   */
  public isGameOver(): boolean {
    return this.gameOver;
  }
  
  /**
   * 获取胜利者
   */
  public getWinner(): number {
    return this.winner;
  }
  
  /**
   * 落子
   * @param row 行坐标
   * @param col 列坐标
   * @returns 是否落子成功
   */
  public makeMove(row: number, col: number): boolean {
    // 检查游戏是否已结束
    if (this.gameOver) {
      return false;
    }
    
    // 检查坐标是否有效
    if (row < 0 || row >= GameState.BOARD_SIZE || col < 0 || col >= GameState.BOARD_SIZE) {
      return false;
    }
    
    // 检查该位置是否已有棋子
    if (this.board[row][col] !== 0) {
      return false;
    }
    
    // 落子
    this.board[row][col] = this.currentPlayer;
    
    // 检查是否获胜
    if (this.checkWin(row, col)) {
      this.gameOver = true;
      this.winner = this.currentPlayer;
      this.currentPlayer = this.currentPlayer === 1 ? 2 : 1;
      return true;
    }
    
    // 切换玩家
    this.currentPlayer = this.currentPlayer === 1 ? 2 : 1;
    return true;
  }
  
  /**
   * 检查是否获胜
   * @param row 最后落子的行坐标
   * @param col 最后落子的列坐标
   * @returns 是否获胜
   */
  private checkWin(row: number, col: number): boolean {
    const directions = [
      [1, 0],   // 水平
      [0, 1],   // 垂直
      [1, 1],   // 右下对角线
      [1, -1]   // 左下对角线
    ];
    
    for (const dd of directions) {
     const dx=dd[0]
      const dy=dd[1]
      let count = 1;
      
      // 正向检查
      for (let i = 1; i <= 4; i++) {
        const newRow = row + i * dx;
        const newCol = col + i * dy;
        if (this.isValidPosition(newRow, newCol) && this.board[newRow][newCol] === this.currentPlayer) {
          count++;
        } else {
          break;
        }
      }
      
      // 反向检查
      for (let i = 1; i <= 4; i++) {
        const newRow = row - i * dx;
        const newCol = col - i * dy;
        if (this.isValidPosition(newRow, newCol) && this.board[newRow][newCol] === this.currentPlayer) {
          count++;
        } else {
          break;
        }
      }
      
      if (count >= 5) {
        return true;
      }
    }
    
    return false;
  }
  
  /**
   * 检查坐标是否有效
   * @param row 行坐标
   * @param col 列坐标
   * @returns 是否有效
   */
  private isValidPosition(row: number, col: number): boolean {
    return row >= 0 && row < GameState.BOARD_SIZE && col >= 0 && col < GameState.BOARD_SIZE;
  }
  
  /**
   * 重新开始游戏
   */
  public restart(): void {
    this.initBoard();
  }
} 

游戏核心逻辑(GameState.ets):

  • 15x15的棋盘

  • 黑白双方轮流落子

  • 胜利判定(横向、纵向、对角线)

  • 游戏状态管理

主页面:
javascript 复制代码
import { GameBoard } from '../components/GameBoard'
import { GameState } from '../model/GameState'

@Entry
@Component
struct Index {
  @State private gameState: GameState = new GameState()
  build() {
    Column() {
      // 标题栏
      Row() {
        Text('五子棋')
          .fontSize(28)
          .fontWeight(FontWeight.Bold)
        
        Text(`当前玩家: ${this.gameState.getCurrentPlayer()==2?'黑子':'白字'}`)
          .fontSize(16)
          .margin({ left: 20 })
      }
      .width('100%')
      .height(60)
      .padding({ left: 20, right: 20 })
      .backgroundColor('#F5F5F5')
      
      // 游戏棋盘
      Column() {
        GameBoard({ gameState: this.gameState })
          .width('100%')
          .margin({ top: 20, bottom: 20 })
      }.width('100%')
      .height('80%')
      .justifyContent(FlexAlign.Center)

    }
    .width('100%')
    .height('100%')
    .backgroundColor('#FFFFFF')
    .justifyContent(FlexAlign.Center)
  }
} 

主页面(Index.ets):

  • 游戏标题

  • 当前玩家显示

  • 棋盘组件集成

完整项目代码:

https://gitee.com/gxx01/gobang

相关推荐
二狗哈5 小时前
制作一款打飞机游戏39:鼠标控制
游戏·计算机外设
windwind200013 小时前
发行基础:本地化BUG导致审核失败
游戏·青少年编程·编辑器·bug·创业创新·玩游戏
wgc2k16 小时前
Java游戏服务器开发流水账(4)游戏的数据持久化
java·服务器·游戏
IP管家1 天前
多级路由器如何避免IP冲突
网络·网络协议·tcp/ip·游戏·智能路由器·ip
Sui_Network1 天前
Sui Basecamp 2025 全栈出击
大数据·游戏·web3·去中心化·区块链
染指11101 天前
21.第二阶段x64游戏实战-分析采集物偏移
汇编·游戏·反游戏外挂·游戏逆向·x64dbg·x64游戏
wgc2k1 天前
Java游戏服务器开发流水账(3)游戏数据的缓存简介
服务器·游戏
EanoJiang1 天前
类刺客信条跑酷系统开发日记
游戏
惊鸿醉2 天前
Unity_JK框架【4】MonoSystem 和 协程工具类 的剖析与实践
游戏·unity·单例模式
wgc2k2 天前
Java游戏服务器开发流水账(2)开发中Maven的管理
java·服务器·游戏