当前位置: 首页> 文旅> 艺术 > 深圳市门户网站建设怎么样_双流海外网络推广_长春网站公司哪家好_十大接单推广平台

深圳市门户网站建设怎么样_双流海外网络推广_长春网站公司哪家好_十大接单推广平台

时间:2025/7/10 0:02:49来源:https://blog.csdn.net/zhongcongxu01/article/details/143311284 浏览次数:0次
深圳市门户网站建设怎么样_双流海外网络推广_长春网站公司哪家好_十大接单推广平台

【引言】

巧算24点是一个经典的数学游戏,其规则简单而富有挑战性:玩家需利用给定的四个数字,通过加、减、乘、除运算,使得计算结果等于24。本文将深入分析一款基于鸿蒙系统的巧算24点游戏的实现代码,并重点介绍其中所使用的算法及其工作原理。

【开发环境】

开发工具:DevEco Studio NEXT Beta1 Build Version: 5.0.3.814

工程版本:API 12

【算法分析】

1、递归搜索算法

递归搜索算法是一种用来穷举所有可能性的算法。在巧算24点游戏中,我们需要通过递归地尝试所有可能的运算组合,来寻找能够使四个数字的运算结果等于24的表达式。

• 在递归过程中,每次选择两个数字进行运算;

• 如果当前只留下一个数字,并且这个数字接近于24(在一定的误差范围内),则认为找到了一个解;

• 否则,继续对剩下的数字进行递归搜索;

• 对于减法和除法,还需要考虑运算顺序,因此需要额外处理。

searchSolutions(currentNumbers: number[], pathExpression: string) {if (this.solutions.length > 0) return;if (currentNumbers.length === 1) {if (Math.abs(currentNumbers[0] - 24) < this.accuracyThreshold) {this.solutions.push(pathExpression);}return;}for (let i = 0; i < currentNumbers.length - 1; i++) {for (let j = i + 1; j < currentNumbers.length; j++) {const tempNumbers = this.removeNumberFromArray(currentNumbers, i, j);for (let k = 0; k < 4; k++) {let tempPath = pathExpression.length > 0 ? `${pathExpression}, ` : '';tempPath += `(${currentNumbers[i]} ${this.getOperationSymbol(k)} ${currentNumbers[j]})`;tempNumbers.push(this.operations[k](currentNumbers[i], currentNumbers[j]));this.searchSolutions(tempNumbers, tempPath);tempNumbers.pop();if (k === 2 || k === 3) {let tempPathSwapped = pathExpression.length > 0 ? `${pathExpression}, ` : '';tempPathSwapped += `(${currentNumbers[j]} ${this.getOperationSymbol(k)} ${currentNumbers[i]})`;tempNumbers.push(this.operations[k](currentNumbers[j], currentNumbers[i]));this.searchSolutions(tempNumbers, tempPathSwapped);tempNumbers.pop();}}}}
}

2、最大公约数算法

最大公约数算法用于简化分数表达式,确保分数处于最简形式。

• 迭代方式:不断交换两个数的位置,直至其中一个数变为0,此时另一个数即为最大公约数;

• 递归方式:如果b不为0,则递归调用自身,参数为b和a对b取模的结果,否则返回a。

迭代方式:

calculateIterativeGcd(a: number, b: number): number {while (b !== 0) {let temp = b;b = a % b;a = temp;}return a;
}

递归方式:

findGreatestCommonDivisor(a: number, b: number): number {return b === 0 ? a : this.findGreatestCommonDivisor(b, a % b);
}

3、连分数逼近算法

连分数逼近算法用于将一个小数转换成分数形式,适用于显示计算结果。

• 使用连分数逼近的方法,不断提取整数部分,并用其构建分数;

• 直到逼近的小数与原始小数相差小于某个容差或达到了最大迭代次数为止。

convertToFraction(decimal: number): string {let tolerance = 1.;let maxIterations = 1000;let iterationCount = 0;let currentDecimal = decimal;let pNumerator = 0, pDenominator = 1;let qNumerator = 1, qDenominator = 0;do {let integerPart = Math.floor(currentDecimal);let temp = pNumerator;pNumerator = integerPart * pNumerator + pDenominator;pDenominator = temp;temp = qNumerator;qNumerator = integerPart * qNumerator + qDenominator;qDenominator = temp;currentDecimal = 1 / (currentDecimal - integerPart);iterationCount++;} while (Math.abs(decimal - pNumerator / qNumerator) > decimal * tolerance && iterationCount < maxIterations);...
}

【完整代码】

import { promptAction } from '@kit.ArkUI' // 导入用于提示用户的工具包@ObservedV2// 装饰器,使类成为可观察对象
class Cell { // 定义一个Cell类,代表游戏中的一个单元格@Trace value: number // 使用装饰器标记value属性,使其成为追踪属性@Trace displayValue: string // 同上,用于显示的值@Trace isVisible: boolean // 同上,判断是否可见@Trace xPosition: number // 同上,x坐标位置@Trace yPosition: number // 同上,y坐标位置columnIndex: number // 列索引rowIndex: number // 行索引constructor(rowIndex: number, columnIndex: number) { // 构造函数this.rowIndex = rowIndex // 设置行索引this.columnIndex = columnIndex // 设置列索引this.xPosition = 0 // 初始化x坐标位置this.yPosition = 0 // 初始化y坐标位置this.value = 0 // 初始化数值this.displayValue = '' // 初始化显示值this.isVisible = true // 初始化可见性}setDefaultValue(value: number) { // 设置单元格的默认值this.value = value // 设置数值this.displayValue = `${value}` // 设置显示值this.isVisible = true // 设置为可见}performOperation(otherCell: Cell, operationName: string) { // 执行与其他单元格的操作switch (operationName) { // 根据操作名称进行不同的运算case "加": // 如果是加法this.value = otherCell.value + this.value // 计算新值break // 结束case块case "减": // 如果是减法this.value = otherCell.value - this.value // 计算新值break // 结束case块case "乘": // 如果是乘法this.value = otherCell.value * this.value // 计算新值break // 结束case块case "除": // 如果是除法if (this.value === 0) { // 检查除数是否为0promptAction.showToast({ message: '除数不能为0', bottom: 400 }) // 提示错误信息return false // 返回false,表示操作无效}this.value = otherCell.value / this.value // 计算新值break // 结束case块}otherCell.isVisible = false // 隐藏参与运算的另一个单元格this.displayValue = `${this.value >= 0 ? '' : '-'}${this.convertToFraction(Math.abs(this.value))}` // 更新显示值return true // 返回true,表示操作成功}findGreatestCommonDivisor(a: number, b: number): number { // 计算两个数的最大公约数return b === 0 ? a : this.findGreatestCommonDivisor(b, a % b) // 使用递归算法求最大公约数}convertToFraction(decimal: number): string { // 将小数转换为分数形式let tolerance = 1.0E-6 // 设置容差值let maxIterations = 1000 // 设置最大迭代次数let pNumerator = 1 // 分子初始化let pDenominator = 0 // 分母初始化let qNumerator = 0 // 辅助变量let qDenominator = 1 // 辅助变量let currentDecimal = decimal // 当前处理的小数let iterationCount = 0 // 迭代计数do { // 执行直到满足条件let integerPart = Math.floor(currentDecimal) // 取整部分let temp = pNumerator // 临时保存分子pNumerator = integerPart * pNumerator + pDenominator // 更新分子pDenominator = temp // 更新分母temp = qNumerator // 临时保存辅助变量qNumerator = integerPart * qNumerator + qDenominator // 更新辅助变量qDenominator = temp // 更新辅助变量currentDecimal = 1 / (currentDecimal - integerPart) // 更新小数部分iterationCount++ // 增加迭代计数} while (Math.abs(decimal - pNumerator / qNumerator) > decimal * tolerance &&iterationCount < maxIterations) // 继续迭代直到达到容差或最大迭代次数if (iterationCount >= maxIterations) { // 如果达到最大迭代次数return `${decimal}` // 返回原小数}let gcdValue = this.calculateIterativeGcd(pNumerator, qNumerator) // 计算分子和分母的最大公约数let reducedNumerator = pNumerator / gcdValue // 化简后的分子let reducedDenominator = qNumerator / gcdValue // 化简后的分母return `${reducedNumerator}${reducedDenominator !== 1 ? '/' + reducedDenominator : ''}` // 返回化简后的分数形式}calculateIterativeGcd(a: number, b: number): number { // 使用迭代方式计算两个数的最大公约数while (b !== 0) { // 当b不为0时继续let temp = b // 临时保存bb = a % b // 更新ba = temp // 更新a}return a // 返回最大公约数}
}class JudgePointSolution { // 定义JudgePointSolution类,用于寻找24点游戏的解solutions: string[] = [] // 存储找到的解accuracyThreshold = Math.pow(10, -6) // 设置精度阈值operations = [// 定义四种基本运算(a: number, b: number) => a + b, // 加法(a: number, b: number) => a * b, // 乘法(a: number, b: number) => a - b, // 减法(a: number, b: number) => a / b,// 除法]searchSolutions(currentNumbers: number[], pathExpression: string) { // 查找解的递归方法if (this.solutions.length > 0) { // 如果已经找到解,则返回return}if (currentNumbers.length === 1) { // 如果只剩下一个数if (Math.abs(currentNumbers[0] - 24) < this.accuracyThreshold) { // 如果该数等于24(在阈值范围内)this.solutions.push(pathExpression) // 将路径表达式作为解加入数组}return // 结束递归}for (let i = 0; i < currentNumbers.length - 1; i++) { // 对所有数进行两两组合for (let j = i + 1; j < currentNumbers.length; j++) { // 对所有数进行两两组合const tempNumbers = this.removeNumberFromArray(currentNumbers, i, j) // 创建新的数组,移除当前两个数for (let k = 0; k < 4; k++) { // 对四种运算分别尝试let tempPath = pathExpression.length > 0 ? `${pathExpression}, ` : '' // 格式化路径表达式tempPath += `(${currentNumbers[i]} ${this.getOperationSymbol(k)} ${currentNumbers[j]})` // 添加当前运算表达式到路径tempNumbers.push(this.operations[k](currentNumbers[i], currentNumbers[j])) // 计算结果并加入临时数组this.searchSolutions(tempNumbers, tempPath) // 递归查找解tempNumbers.pop() // 移除最后一个加入的结果if (k === 2 || k === 3) { // 如果是减法或除法let tempPathSwapped = pathExpression.length > 0 ? `${pathExpression}, ` : '' // 格式化路径表达式tempPathSwapped += `(${currentNumbers[j]} ${this.getOperationSymbol(k)} ${currentNumbers[i]})` // 添加当前运算表达式到路径tempNumbers.push(this.operations[k](currentNumbers[j], currentNumbers[i])) // 计算结果并加入临时数组this.searchSolutions(tempNumbers, tempPathSwapped) // 递归查找解tempNumbers.pop() // 移除最后一个加入的结果}}}}}find24Solutions(numbers: number[]): string[] { // 查找所有可能的解this.solutions = [] // 清空解数组this.searchSolutions(numbers, '') // 开始查找return this.solutions // 返回解数组}getOperationSymbol(index: number): string { // 获取运算符号const symbols = ['+', '*', '-', '/'] // 定义符号数组return symbols[index] // 返回对应的符号}removeNumberFromArray(array: number[], index1: number, index2: number): number[] { // 从数组中移除指定位置的元素const newArray: number[] = [] // 新数组for (let k = 0; k < array.length; k++) { // 遍历原始数组if (k !== index1 && k !== index2) { // 如果不是需要移除的位置newArray.push(array[k]) // 将元素加入新数组}}return newArray // 返回新数组}
}@Entry
@Component
struct GameIndex {@State randomNumbers: number[] = [] // 用于存储随机生成的游戏数字@State symbols: string[] = ["加", "减", "乘", "除"] // 存储游戏中可用的运算符号字符串数组@State cells: Cell[] = [// 存储游戏中的单元格实例数组new Cell(0, 0), // 创建位于第0行第0列的单元格new Cell(0, 1), // 创建位于第0行第1列的单元格new Cell(1, 0), // 创建位于第1行第0列的单元格new Cell(1, 1)// 创建位于第1行第1列的单元格]@State selectedNumberIndex: number = -1 // 存储选中的数字单元格的索引,默认为-1表示未选择@State selectedSymbolIndex: number = -1 // 存储选中的运算符号的索引,默认为-1表示未选择@State showSolution: boolean = false // 控制是否显示游戏的解决方案,默认为不显示cellWidth: number = 250 // 单个单元格的宽度cellMargin: number = 15 // 单元格之间的间距judgePoint24Util: JudgePointSolution = new JudgePointSolution() // 创建一个JudgePointSolution类的实例,用于寻找游戏的解isShowAnim: boolean = false //单元格是否正在移动,若移动中禁止操作以防闪退aboutToAppear(): void {this.resetGame()}resetGame() {this.randomNumbers = []for (let i = 0; i < this.cells.length; i++) {let randomValue = Math.floor(Math.random() * 13) + 1this.cells[i].setDefaultValue(randomValue)this.randomNumbers.push(randomValue)}this.selectedNumberIndex = -1this.selectedSymbolIndex = -1this.showSolution = falselet solutions = this.judgePoint24Util.find24Solutions(this.randomNumbers)console.info(`【${solutions}】`)if (solutions.length === 0) {console.info(`无解,重新循环`)this.resetGame()}}build() {Column({ space: 20 }) {// 显示/隐藏 解决方案Text(`${this.judgePoint24Util.find24Solutions(this.randomNumbers)}`).fontSize(20).fontColor(Color.White).backgroundColor("#ffa101").visibility(this.showSolution ? Visibility.Visible : Visibility.Hidden).padding(10).borderRadius(10)// 数字Row() {Flex({ wrap: FlexWrap.Wrap }) {ForEach(this.cells, (cell: Cell, index: number) => {Text(`${cell.displayValue}`).fontSize(`${this.cellWidth / 3}lpx`).width(`${this.cellWidth}lpx`).height(`${this.cellWidth}lpx`).fontColor(cell !== this.cells[this.selectedNumberIndex] ? "#ffffff" : "#fe4b00").backgroundColor(cell !== this.cells[this.selectedNumberIndex] ? "#ffa101" : "#fddf4b").borderRadius(`${this.cellMargin}lpx`).margin(`${this.cellMargin}lpx`).textAlign(TextAlign.Center).clickEffect({ level: ClickEffectLevel.LIGHT, scale: 0.8 }).visibility(cell.isVisible ? Visibility.Visible : Visibility.Hidden).translate({ x: `${cell.xPosition}lpx`, y: `${cell.yPosition}lpx` }).onClick(() => {if (this.selectedNumberIndex === -1) {this.selectedNumberIndex = index} else if (this.selectedNumberIndex === index) {this.selectedNumberIndex = -1} else if (this.selectedSymbolIndex === -1) {console.info(`未选择操作符,仅改变选中位置`)this.selectedNumberIndex = index} else {if (this.isShowAnim) {return}this.isShowAnim = trueanimateToImmediately({duration: 300,onFinish: () => {this.cells[this.selectedNumberIndex].xPosition = 0 // 动画结束后位置归0this.cells[this.selectedNumberIndex].yPosition = 0 // 动画结束后位置归0this.cells[index].performOperation(this.cells[this.selectedNumberIndex],this.symbols[this.selectedSymbolIndex])this.selectedNumberIndex = -1this.selectedSymbolIndex = -1// 统计结果let countVisibleCells: number = 0for (let i = 0; i < this.cells.length; i++) {if (this.cells[i].isVisible) {countVisibleCells++}}if (countVisibleCells === 1) { // 当前是最后一个promptAction.showDialog({title: '游戏结束',message: `${this.cells[index].value === 24 ? '【胜利】' : '【失败】'}`,buttons: [{ text: '重新开始', color: '#ffa500' }]}).then(() => {this.resetGame()})}this.isShowAnim = false},}, () => {let temp = this.cellWidth + this.cellMargin // 要移动的单元格距离let movingCell: Cell = this.cells[this.selectedNumberIndex]movingCell.xPosition = (cell.columnIndex - movingCell.columnIndex) * tempmovingCell.yPosition = (cell.rowIndex - movingCell.rowIndex) * temp})}})})}.width(`${this.cellWidth * 2 + this.cellMargin * 4}lpx`)}.width('100%').justifyContent(FlexAlign.Center)// 操作符Row() {Flex({ wrap: FlexWrap.Wrap }) {ForEach(this.symbols, (symbol: string, index: number) => {Text(`${symbol}`).fontSize(`${this.cellWidth / 4}lpx`).width(`${this.cellWidth / 2}lpx`).height(`${this.cellWidth / 2}lpx`).fontColor(this.selectedSymbolIndex !== index ? "#c16cf9" : "#fcfeff").backgroundColor(this.selectedSymbolIndex !== index ? Color.Transparent : "#c16cf9").borderRadius(`${this.cellMargin}lpx`).margin(`${this.cellMargin / 2}lpx`).textAlign(TextAlign.Center).clickEffect({ level: ClickEffectLevel.LIGHT, scale: 0.8 }).onClick(() => {if (this.selectedSymbolIndex === index) {this.selectedSymbolIndex = -1} else {this.selectedSymbolIndex = index}})})}.width(`${this.cellWidth * 2 + this.cellMargin * 4}lpx`)}.width('100%').justifyContent(FlexAlign.Center)// 重新开始 / 解决方案Row() {Button('重新开始').clickEffect({ level: ClickEffectLevel.LIGHT, scale: 0.8 }).onClick(() => {this.resetGame()})Button('解决方案').clickEffect({ level: ClickEffectLevel.LIGHT, scale: 0.8 }).onClick(() => {this.showSolution = !this.showSolution})}.width('100%').justifyContent(FlexAlign.SpaceEvenly)}.width('100%').height('100%').backgroundColor("#0d1015").padding(20)}
}

关键字:深圳市门户网站建设怎么样_双流海外网络推广_长春网站公司哪家好_十大接单推广平台

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: