【高心星出品】
文章目录
五子棋游戏(鸿蒙版)开发
五子棋是一款传统的两人策略型棋类游戏,游戏的目的是在棋盘上首先形成连续的五个同色棋子的玩家获胜。游戏规则简单,易于上手,但要达到高手水平则需要相当的策略和技巧。
基本规则:
- 棋盘 :五子棋通常在15×15的棋盘上进行。
- 棋子 :棋子分为黑白两色,双方各执一色。
- 开局 :黑方先行,之后轮流下子。
- 胜局 :第一个在棋盘上形成一个连续的五个同色棋子连线的玩家获胜。
特殊规则:
- 禁手规则 :在某些比赛规则中,黑方的第一步棋如果落在了棋盘的中心点,或者形成了特定的危险形态,可能会被判定为"禁手",此时黑方需要接受惩罚,通常是白方可以提出和棋。
- 三连和四连 :在下棋过程中,形成三个或四个连续的棋子通常会获得优势,但需要防范对手利用这些情况形成更长的连子。
五子棋因其规则简单而深受各个年龄层的玩家喜爱,同时也因为其策略性而吸引了一批忠实的棋艺爱好者。希望这些信息能帮助您更好地了解五子棋游戏。
运行效果

开发步骤
项目结构

核心代码
棋盘组件:
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):
-
游戏标题
-
当前玩家显示
-
棋盘组件集成
完整项目代码: