鸿蒙跨端古诗接龙游戏开发指南 原创

进修的泡芙
发布于 2025-6-22 16:55
浏览
0收藏

鸿蒙跨端古诗接龙游戏开发指南

一、系统架构设计

基于HarmonyOS的AI能力和分布式技术,构建古诗接龙游戏系统:
游戏逻辑层:管理游戏状态和规则

AI生成层:使用NLP模型生成古诗下一句

用户交互层:提供游戏界面和输入

跨端同步层:多设备间同步游戏状态和玩家信息

!https://example.com/harmony-poetry-game-arch.png

二、核心代码实现
游戏服务封装

// PoetryGameService.ets
import ai from ‘@ohos.ai’;
import distributedData from ‘@ohos.distributedData’;
import { PlayerInfo, GameState, PoetryLine } from ‘./PoetryTypes’;

class PoetryGameService {
private static instance: PoetryGameService = null;
private modelManager: ai.ModelManager;
private dataManager: distributedData.DataManager;
private gameListeners: GameListener[] = [];
private currentGame: GameState | null = null;

private constructor() {
this.initModelManager();
this.initDataManager();
public static getInstance(): PoetryGameService {

if (!PoetryGameService.instance) {
  PoetryGameService.instance = new PoetryGameService();

return PoetryGameService.instance;

private initModelManager(): void {

try {
  this.modelManager = ai.createModelManager(getContext());
  
  // 加载古诗生成模型
  this.modelManager.loadModel({
    modelName: 'poetry_generation',
    modelPath: 'resources/rawfile/poetry.model',
    callback: (err, data) => {
      if (err) {
        console.error('加载古诗模型失败:', JSON.stringify(err));

}

  });

catch (err) {

  console.error('初始化模型管理器失败:', JSON.stringify(err));

}

private initDataManager(): void {
this.dataManager = distributedData.createDataManager({
bundleName: ‘com.example.poetrygame’,
area: distributedData.Area.GLOBAL,
isEncrypted: true
});

this.dataManager.registerDataListener('game_state_sync', (data) => {
  this.handleSyncData(data);
});

public async createGame(players: PlayerInfo[]): Promise<GameState> {

try {
  // 随机选择一首古诗开头
  const openings = [
    "床前明月光",
    "春眠不觉晓",
    "白日依山尽",
    "红豆生南国",
    "锄禾日当午"
  ];
  const openingLine = openings[Math.floor(Math.random() * openings.length)];
  
  const gameState: GameState = {
    gameId: Date.now().toString(),
    players: players,
    currentPlayer: players[0].deviceId,
    poetryLines: [{
      text: openingLine,
      author: "系统",
      deviceId: "system"
    }],
    startTime: Date.now(),
    status: "playing"
  };
  
  this.currentGame = gameState;
  this.syncGameState(gameState);
  
  return gameState;

catch (err) {

  console.error('创建游戏失败:', JSON.stringify(err));
  throw err;

}

public async generateNextLine(previousLine: string): Promise<PoetryLine> {
try {
const input = {
previous_line: previousLine,
max_length: 10 // 生成最多10个字符
};

  const output = await this.modelManager.runModel({
    modelName: 'poetry_generation',
    input: input
  });
  
  return {
    text: output.result.line,
    author: "AI",
    deviceId: "ai"
  };

catch (err) {

  console.error('生成古诗失败:', JSON.stringify(err));
  throw err;

}

public async submitPlayerLine(line: string, player: PlayerInfo): Promise<GameState> {
if (!this.currentGame) {
throw new Error(‘当前没有进行中的游戏’);
const newLine: PoetryLine = {

  text: line,
  author: player.nickname,
  deviceId: player.deviceId
};

const updatedGame: GameState = {
  ...this.currentGame,
  poetryLines: [...this.currentGame.poetryLines, newLine],
  currentPlayer: this.getNextPlayerId(player.deviceId)
};

this.currentGame = updatedGame;
this.syncGameState(updatedGame);

return updatedGame;

private getNextPlayerId(currentPlayerId: string): string {

if (!this.currentGame) return currentPlayerId;

const currentIndex = this.currentGame.players.findIndex(

=> p.deviceId === currentPlayerId

);

const nextIndex = (currentIndex + 1) % this.currentGame.players.length;
return this.currentGame.players[nextIndex].deviceId;

private syncGameState(state: GameState): void {

this.dataManager.syncData('game_state_sync', {
  type: 'game_state',
  data: state,
  timestamp: Date.now()
});

private handleSyncData(data: any): void {

if (!data || data.type !== 'game_state') return;

this.currentGame = data.data;
this.notifyGameStateChanged(data.data);

private notifyGameStateChanged(state: GameState): void {

this.gameListeners.forEach(listener => {
  listener.onGameStateChanged?.(state);
});

public addListener(listener: GameListener): void {

if (!this.gameListeners.includes(listener)) {
  this.gameListeners.push(listener);

}

public removeListener(listener: GameListener): void {
this.gameListeners = this.gameListeners.filter(l => l !== listener);
}

interface GameListener {
onGameStateChanged?(state: GameState): void;
export const poetryGameService = PoetryGameService.getInstance();

主游戏界面

// GameScreen.ets
import { poetryGameService } from ‘./PoetryGameService’;
import { PlayerInfo, GameState, PoetryLine } from ‘./PoetryTypes’;

@Component
export struct GameScreen {
@State currentGame: GameState | null = null;
@State playerInput: string = ‘’;
@State isGenerating: boolean = false;
@State showAIResult: boolean = false;
@State aiGeneratedLine: PoetryLine | null = null;
@State currentPlayer: PlayerInfo | null = null;

// 模拟玩家信息(实际应从设备获取)
private localPlayer: PlayerInfo = {
deviceId: ‘device_001’,
nickname: ‘玩家1’,
avatar: ‘resources/rawfile/avatar1.png’
};

// 模拟其他玩家(实际应通过分布式能力发现)
private otherPlayers: PlayerInfo[] = [
deviceId: ‘device_002’,

  nickname: '玩家2',
  avatar: 'resources/rawfile/avatar2.png'
},

deviceId: ‘device_003’,

  nickname: '玩家3',
  avatar: 'resources/rawfile/avatar3.png'

];

aboutToAppear() {
poetryGameService.addListener({
onGameStateChanged: (state) => {
this.handleGameStateChanged(state);
});

this.startNewGame();

aboutToDisappear() {

poetryGameService.removeListener({
  onGameStateChanged: (state) => {
    this.handleGameStateChanged(state);

});

build() {

Column() {
  // 标题栏
  Row() {
    Text('古诗接龙')
      .fontSize(24)
      .fontWeight(FontWeight.Bold)
      .layoutWeight(1)
    
    Button('新游戏')
      .width(100)
      .onClick(() => {
        this.startNewGame();
      })

.padding(10)

  .width('100%')
  
  // 玩家信息
  if (this.currentGame) {
    Row() {
      ForEach(this.currentGame.players, (player) => {
        Column() {
          Image(player.avatar)
            .width(40)
            .height(40)
            .borderRadius(20)
            .border({
              width: player.deviceId === this.currentGame?.currentPlayer ? 2 : 0,
              color: '#409EFF'
            })
          
          Text(player.nickname)
            .fontSize(12)
            .maxLines(1)
            .textOverflow({ overflow: TextOverflow.Ellipsis })

.margin({ right: 15 })

        .opacity(player.deviceId === this.currentGame?.currentPlayer ? 1 : 0.6)
      })

.width(‘100%’)

    .margin({ bottom: 20 })

// 古诗接龙内容

  if (this.currentGame?.poetryLines) {
    Column() {
      ForEach(this.currentGame.poetryLines, (line, index) => {
        Column() {
          Row() {
            if (line.deviceId ! 'system' && line.deviceId ! 'ai') {
              Image(this.getPlayerAvatar(line.deviceId))
                .width(24)
                .height(24)
                .borderRadius(12)
                .margin({ right: 10 })

Text(line.text)

              .fontSize(18)
              .fontColor(line.deviceId === 'ai' ? '#888888' : '#333333')
            
            if (index === this.currentGame!.poetryLines.length - 1) {
              Text('___')
                .fontSize(18)
                .fontColor('#409EFF')
                .margin({ left: 5 })

}

          .margin({ bottom: 5 })
          
          Text(line.author)
            .fontSize(12)
            .fontColor('#888888')
            .margin({ left: line.deviceId === 'system' ? 0 : 34 })

.margin({ bottom: 15 })

      })

.width(‘100%’)

    .padding(15)
    .backgroundColor('#F9F9F9')
    .borderRadius(8)
    .margin({ bottom: 20 })

// 玩家输入区域

  if (this.currentGame?.currentPlayer === this.localPlayer.deviceId) {
    Column() {
      TextInput({ placeholder: '输入下一句古诗...', text: this.playerInput })
        .height(60)
        .width('100%')
        .fontSize(16)
        .onChange((value: string) => {
          this.playerInput = value;
        })
      
      Row() {
        Button('提交')
          .width(120)
          .height(50)
          .fontSize(18)
          .onClick(() => {
            this.submitLine();
          })
          .margin({ right: 15 })
        
        Button('AI提示')
          .width(120)
          .height(50)
          .fontSize(18)
          .onClick(() => {
            this.requestAIHelp();
          })

.margin({ top: 10 })

.width(‘100%’)

}

.width('100%')
.height('100%')
.padding(20)

// AI生成结果弹窗
if (this.showAIResult && this.aiGeneratedLine) {
  DialogComponent({
    title: 'AI生成建议',
    content: this.buildAIResultContent(),
    confirm: {
      value: '使用这句',
      action: () => this.useAILine()
    },
    cancel: {
      value: '换一句',
      action: () => this.requestAIHelp()

})

}

private buildAIResultContent(): void {
Column() {
Text(this.aiGeneratedLine!.text)
.fontSize(20)
.fontColor(‘#333333’)
.margin({ bottom: 20 })

  Text('AI生成,仅供参考')
    .fontSize(14)
    .fontColor('#888888')

.padding(20)

.width('100%')

private async startNewGame(): Promise<void> {

try {
  const players = [this.localPlayer, ...this.otherPlayers];
  this.currentGame = await poetryGameService.createGame(players);

catch (err) {

  console.error('开始新游戏失败:', JSON.stringify(err));
  prompt.showToast({ message: '开始游戏失败,请重试' });

}

private async submitLine(): Promise<void> {
if (!this.playerInput.trim()) {
prompt.showToast({ message: ‘请输入诗句’ });
return;
try {

  await poetryGameService.submitPlayerLine(
    this.playerInput,
    this.localPlayer
  );
  this.playerInput = '';

catch (err) {

  console.error('提交诗句失败:', JSON.stringify(err));
  prompt.showToast({ message: '提交失败,请重试' });

}

private async requestAIHelp(): Promise<void> {
if (!this.currentGame || this.currentGame.poetryLines.length === 0) return;

this.isGenerating = true;

try {
  const lastLine = this.currentGame.poetryLines[
    this.currentGame.poetryLines.length - 1
  ].text;
  
  this.aiGeneratedLine = await poetryGameService.generateNextLine(lastLine);
  this.showAIResult = true;

catch (err) {

  console.error('获取AI提示失败:', JSON.stringify(err));
  prompt.showToast({ message: '获取提示失败,请重试' });

finally {

  this.isGenerating = false;

}

private async useAILine(): Promise<void> {
if (!this.aiGeneratedLine) return;

try {
  await poetryGameService.submitPlayerLine(
    this.aiGeneratedLine.text,
    this.localPlayer
  );
  this.showAIResult = false;
  this.aiGeneratedLine = null;

catch (err) {

  console.error('使用AI诗句失败:', JSON.stringify(err));
  prompt.showToast({ message: '提交失败,请重试' });

}

private handleGameStateChanged(state: GameState): void {
this.currentGame = state;
this.currentPlayer = state.players.find(
=> p.deviceId === state.currentPlayer

) || null;

private getPlayerAvatar(deviceId: string): string {

const player = this.currentGame?.players.find(p => p.deviceId === deviceId);
return player?.avatar || 'resources/rawfile/default_avatar.png';

}

类型定义

// PoetryTypes.ets
export interface PlayerInfo {
deviceId: string;
nickname: string;
avatar: string;
export interface PoetryLine {

text: string;
author: string;
deviceId: string;
export interface GameState {

gameId: string;
players: PlayerInfo[];
currentPlayer: string;
poetryLines: PoetryLine[];
startTime: number;
status: “waiting” “playing”
“finished”;

三、项目配置与权限
权限配置

// module.json5
“module”: {

"requestPermissions": [

“name”: “ohos.permission.USE_AI”,

    "reason": "使用AI模型生成古诗"
  },

“name”: “ohos.permission.DISTRIBUTED_DATASYNC”,

    "reason": "同步游戏状态"

],

"abilities": [

“name”: “MainAbility”,

    "type": "page",
    "visible": true

]

}

四、总结与扩展

本古诗接龙游戏系统实现了以下核心功能:
多人联机游戏:支持多设备玩家实时参与

AI智能提示:为玩家提供古诗接龙建议

回合制游戏:按照顺序轮流接龙

跨设备同步:实时同步游戏状态和玩家操作

扩展方向:
难度分级:根据玩家水平设置不同难度

诗词库扩展:支持更多诗词类型和朝代

评分系统:评估玩家接龙的诗句质量

社交分享:分享游戏过程和精彩诗句

历史记录:保存经典接龙对局

语音输入:支持语音输入诗句

通过HarmonyOS的AI能力和分布式技术,我们构建了一个寓教于乐的古诗接龙游戏,既能让玩家感受中华诗词的魅力,又能体验多设备协同游戏的乐趣。

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
收藏
回复
举报
回复
    相关推荐