【高心星出品】
文章目录
- 五子棋游戏(鸿蒙版)开发
- 运行效果
- 开发步骤
- 项目结构
- 核心代码
- 棋盘组件:
- 游戏逻辑处理:
- 主页面:
五子棋游戏(鸿蒙版)开发
五子棋是一款传统的两人策略型棋类游戏,游戏的目的是在棋盘上首先形成连续的五个同色棋子的玩家获胜。游戏规则简单,易于上手,但要达到高手水平则需要相当的策略和技巧。
基本规则:
- 棋盘 :五子棋通常在15×15的棋盘上进行。
- 棋子 :棋子分为黑白两色,双方各执一色。
- 开局 :黑方先行,之后轮流下子。
- 胜局 :第一个在棋盘上形成一个连续的五个同色棋子连线的玩家获胜。
特殊规则:
- 禁手规则 :在某些比赛规则中,黑方的第一步棋如果落在了棋盘的中心点,或者形成了特定的危险形态,可能会被判定为“禁手”,此时黑方需要接受惩罚,通常是白方可以提出和棋。
- 三连和四连 :在下棋过程中,形成三个或四个连续的棋子通常会获得优势,但需要防范对手利用这些情况形成更长的连子。
五子棋因其规则简单而深受各个年龄层的玩家喜爱,同时也因为其策略性而吸引了一批忠实的棋艺爱好者。希望这些信息能帮助您更好地了解五子棋游戏。
运行效果
开发步骤
项目结构
核心代码
棋盘组件:
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=0private 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.xconst 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.cellSizectx.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.cellSizectx.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.cellSizeconst y = this.boardPadding + j * this.cellSizectx.beginPath()ctx.arc(x, y, 3, 0, Math.PI * 2)ctx.closePath()ctx.fill()}}}
}
游戏棋盘组件(GameBoard.ets):
-
木色背景的棋盘
-
网格线和星位点
-
黑白棋子的显示
-
点击落子功能
-
游戏结束对话框
游戏逻辑处理:
/*** 游戏状态管理类*/
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的棋盘
-
黑白双方轮流落子
-
胜利判定(横向、纵向、对角线)
-
游戏状态管理
主页面:
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