【鸿蒙应用开发 Dev ECO Studio 5.0版本】从0到1!从无到有!最全!计算器------按钮动画、滑动退格、中缀表达式转后缀表达式、UI设计


计算器

效果图

首先,先给大家看一下计算器的效果图

  • 第一个是计算器的UI设计
  • 第二个是科学计算器的页面布局(科学计算器的相关功能还没有实现)
  • 第三个是退格设计:在计算式预览组件中滑动手指即可(左滑或者右滑)
    计算器首页

UI布局转换
退格

设计思路

UI设计

这个UI设计模仿的是苹果手机计算器风格,不能说很像但是还是挺像的,一眼看去可以发现主要有两种风格的按钮:一种是圆形按钮,另一种是数字‘0’所在的椭圆按钮,所以以此出发,我们可以构造两个子组件来完成按钮的设计,最后将他们使用Row组件和Column组件按照顺序排布即可

按钮功能分析

  1. 点击后可以将这个按钮对应的字符添加到计算式字符串中(详见下面代码的OnClick事件)
  2. 点击时透明度发生变化以实现点击动效(详见下面代码的OnTouch事件)
  3. 在计算式的Row组件中手指滑动实现退格(退位)操作(详见下面代码的On)
  4. 外观和谐美观

滑动退格实现原理思路

  1. 定义一个起始坐标(sta_x)、波尔类型的标记(flag==false)以及手指滑动过程中x坐标的偏移量(distance_x)
  2. 获得手指按下时的x坐标作为起始坐标(sta_x),并将flag改为true代表手指开始接触屏幕
  3. 手指滑动计算distance_x偏移量,如果偏移量大于某个值并且flag是true时就删除计算式字符串的最后一位,即实现退格操作,同时并把flag再次置为false使得如果不松手的话无论手指怎么滑动都只能进行一次退格。
  4. 手指离开时flag置为true,方便进行下一次滑动退格。
滑动退格源代码
  Row() {
          Text(`${this.cal}`)
            .fontSize(24)
            .fontColor(Color.White)
        }.height(70)
        .width('100%')
        .justifyContent(FlexAlign.End)
        .padding({ right: 35 })
        //通过onTouch事件来实现滑动退格
        .onTouch((Event:TouchEvent)=>{
          if(Event.type==TouchType.Down){
          //获得手指按下时的x坐标作为起始坐标
            this.sta_x = Event.touches[0].x
            this.Delete_bool = true;
          }
          if(Event.type==TouchType.Up){
              this.Delete_bool = true
          }
          if(Event.type==TouchType.Move){
          //移动过程中计算x轴上移动的距离
              this.distance_x = Math.abs(this.sta_x - Event.touches[0].x)
          //如果距离超过20就进行退格操作
            if(this.distance_x>20&&this.Delete_bool == true){
             this.cal = this.cal.slice(0,-1);
             this.Delete_bool = false;
            }
          }
        })
圆形按钮源代码(包含按钮动画)
@Component
export struct Button1{
  //计算式
  @Link cal:string
  //计算结果
  @Link result:string|undefined|number
  //是否已经按下等号的标记
  @Consume flag:boolean
  //按钮透明度设置
  @Link button_opacity_son:number
  //1为测试数据
  num:string = '1'
  //按钮颜色
  buttonColor:number = 0x333333
  //文本颜色
  textColor:number = Color.White
  //文本大小
  textSize:number = 28

  build() {
   Column(){
     Text(`${this.num}`)
       .fontColor(this.textColor)
       .fontWeight(FontWeight.Medium)
       .fontSize(this.textSize)
   }.justifyContent(FlexAlign.Center)
   //按下按钮时,按钮的透明度改变
   .onTouch((Event:TouchEvent)=>{
     if(Event.type==TouchType.Down){
       this.button_opacity_son = 0.5
     }
     if(Event.type==TouchType.Up){
       this.button_opacity_son = 1;
     }
   })
    .width(80)
    .height(80)
    .opacity(this.button_opacity_son)
    .alignItems(HorizontalAlign.Center)
    .backgroundColor(this.buttonColor)
    .borderRadius(40)
    .onClick(()=>{
      //’AC‘功能的实现
      if(this.num=='AC'){
        this.flag = true;
        this.cal='';
        this.result = '0';
        return
      }
      else if(this.num=='='){
        //如果第一次按下等号就显示等号
        if(this.flag == true) {
          this.flag = false;
          let EndExpression =SwitchMiddleToEnd(this.cal);
          EndExpression.print_queue()
          this.result = calculate_achieve(EndExpression);
        }
        //否则不显示等号
        else {
          let EndExpression = SwitchMiddleToEnd(this.cal);
          EndExpression.print_queue()
          this.result = calculate_achieve(EndExpression);
          this.result = String(roundToDecimal(this.result));
        }
      }
      //将按钮所对应的字符加到计算式后
      else {
        this.cal += this.num;
      }
    })
}
}
圆形按钮预览图

圆形按钮预览图

椭圆按钮源代码

和圆形按钮构造基本相同,只是宽度不同,注释看上面的圆形按钮注释即可

@Component
export struct Button2{
  @Link cal:string
  @Link button_opacity_son:number
    num:string = '0'
    buttonColor:number = 0x333333
    textColor:number = Color.White
    textSize:number = 28

  build() {
      Column(){
        Text(`${this.num}`)
          .fontColor(this.textColor)
          .fontWeight(FontWeight.Medium)
          .fontSize(this.textSize)
      }.justifyContent(FlexAlign.Center)
      .onTouch((Event:TouchEvent)=>{
        if(Event.type==TouchType.Down){
          this.button_opacity_son = 0.5
        }
        if(Event.type==TouchType.Up){
          this.button_opacity_son = 1;
        }
      })
      .width(170)
      .opacity(this.button_opacity_son)
      .height(80)
      .alignItems(HorizontalAlign.Center)
      .backgroundColor(this.buttonColor)
      .borderRadius(40)
    .onClick(()=>{
      this.cal+=this.num;
    })
    }
}
椭圆按钮预览图

椭圆按钮

计算逻辑的实现

我们先来看看,对于“9 + (3 - 1) × 3 + 10 ÷ 2”,这种表达式叫做中缀表达式,就是我们平时数学上遇到的算式,如果要用后缀表示法应该是这个样子“9 3 1 - 3 × 10 2 ÷ +”,叫后缀表达式的原因在于所有的符号都是在要运算数字的后面出现。显然这里没有了括号,对于从来没有接触过后缀表达式的同学来讲,这样的表述是很难受的,不过人不喜欢,机器却是很喜欢的,比如我们“聪明的计算机”。
因此我们现在应该干什么事呢?没错,现在需要将我们熟悉的数学算式改为计算机喜欢的式子(即:中缀表达式转化为后缀表达式),然后再根据数据结构中的栈和队列来实现这个运算逻辑,最后将结果显示在我们的屏幕上即可。
总结主要有以下几步:

  1. 中缀表达式转换为后缀表达式
  2. 利用栈完成对后缀表达式的计算并获得结果
  3. 最后将计算结果显示出来
中缀表达式转后缀表达式
  • 规则:从左到右遍历中缀表达式的每个数字和符号,若是数字就输出,即成为后缀表达式的一部分;若是符号,则判断其与栈顶符号的优先级,是右括号或者优先级不高于栈顶符号(乘除优先加减)则栈顶元素依次出栈并输出,并将当前符号进栈,一直到最终输出后缀表达式为止。
  • 做法:我们这里分别构造了一个队列和一个栈,栈根据以上规则进行获得后缀表达式,而队列用来存储后缀表达式,最后将这个存储着后缀表达式的队列返回。关于栈和队列的构建可以看下面两个博客:
    1. Typescript实现栈
    2. Typescript实现队列
代码部分(获得运算符优先级函数 && 中缀表达式转后缀表达式函数)
//获得运算符优先级等级的函数
function getPrecedence(item:string):number{
  switch(item){
    case '%':return 3
    case '×':return 2
    case '÷':return 2
    case '+':return 1
    case '-':return 1
    default:return 0
  }
}

//中缀表达式转后缀表达式函数
export function SwitchMiddleToEnd(cal:string){
  let queue = new queue_my();
  let first_fu:boolean = true
  let switchStack = new CharacterStack();
  let i =0;
  while(i<cal.length){
    //如果遍历到数字直接入队
    if(isNumber(cal[i])){
      let numberstring = '';
      while(isNumber(cal[i])){
        numberstring+=cal[i];
        i++
      }
      queue.enqueue(numberstring);
   //   console.log(`${numberstring}入队`);
      i--

    }
    //如果遇到第一个位置是左括号加-号
      else if(cal[0]=='('&&cal[1]=='-'&&first_fu){
        switchStack.push(cal[0]);
        let numberstring = '-'
        first_fu = false;
        i = 2
        while(isNumber(cal[i])){
          numberstring+=cal[i]
          i++
        }
        queue.enqueue(numberstring)
      i--
     // console.log(`${numberstring}入队`);
     // console.log(`此时遍历到了:${cal[i]}`)
    }
    else if(cal[0]=='-'&&isNumber(cal[1])&&first_fu){
      let numberstring = '-';
      first_fu = false;
      i=1;
      while(isNumber(cal[i])){
        numberstring+=cal[i];
        i++
      }
      queue.enqueue(numberstring);
   //   console.log(`${numberstring}入队`);
      i--;
    }
    //如果连按几次同一个操作符
      else if(!isNumber(cal[i])&&!isNumber(cal[i+1])&&cal[i]==cal[i+1]){
        i++;
    }
    //带括号的负数在中间的时候
      else if(cal[i]=='('&&cal[i+1]=='-'&&isNumber(cal[i+2])){
      let numberstring = '-';
      i = i+2;
      while(isNumber(cal[i])){
        numberstring+=cal[i];
        ++i
      }
      queue.enqueue(numberstring)
    //  console.log(`${numberstring}已经入队`)
    }

    //如果栈中为空或者遇到左括号直接入栈
    else if(switchStack.isEmpty()||cal[i]=='('){
   //   if(cal[i]=='(') console.log('遇到了左括号')
      switchStack.push(cal[i]);
    }
    //栈顶操作符优先级小于当前操作符优先级
    else if(cal[i]!=')'&&getPrecedence(switchStack.peek())<getPrecedence(cal[i])){
      switchStack.push(cal[i]);
    }
    //栈顶操作符优先级大于当前操作符优先级
    else if(cal[i]!=')'&&getPrecedence(switchStack.peek())>=getPrecedence(cal[i])){
        //栈顶元素出栈并且加到队列中去
        while(getPrecedence(cal[i])<=getPrecedence(switchStack.peek()))
        {queue.enqueue(String(switchStack.pop()))
          if(switchStack.isEmpty()){break}
        }
        switchStack.push(cal[i]);
    }
    //如果遇到了右括号
    else if(cal[i]==')') {
     // console.log('遇到了右括号')
      while (switchStack.peek() != '(') {
        let temp: string = String(switchStack.pop());
        queue.enqueue(temp);
      }
      //遇到左括号时直接将左括号弹出
      switchStack.pop()
     // console.log('左括号出栈')
    }
    i++;
  }
  //最后将剩余的操作符全部放到队列中
  while(!switchStack.isEmpty()) {
    queue.enqueue(String(switchStack.pop()))
  }
  return queue;
}
判断该字符是数字部分还是操作符部分

这里用了两个函数:

  • 判断这个字符是不是数字部分:
function isNumber(item:string):boolean{
  if(item=='0'||item=='1'||item=='2'||item=='3'||item=='4'||item=='5'||item=='6'||
    item=='7'||item=='8'||item=='9'||item=='.'){
    return true;
  }
  else return false;
}
  • 判断这个字符是不是操作符
function isCharacter(item:string):boolean{
  if(item=='+'||item=='-'||item=='÷'||item=='×'||item=='('||item==')'){
    return true;
  }
  else return false;
后缀表达式计算结果
  • 规则:从左到右遍历表达式的每个数字和符号,遇到是数字就入栈,遇到是符号,就将处于栈顶的两个数字出栈,进行运算,运算结果进栈,一直到最终获得结果。
代码部分(后缀表达式计算结果)
//后缀表达式计算函数
export function calculate_achieve(que:queue_my):string{
    let numberstack = new NumberStack();
    let i =0;
    let sum=que.size()
    while(i<sum){
      //如果遇到数字直接入栈并删除该元素
      if(!isCharacter(que.peek())){
        console.log(`${que.peek()}已经入栈`)
          numberstack.push(que.peek());
          que.dequeue()
          i++;
      }
      //如果遇到了操作符
      else{
        let num_up = numberstack.pop();
        let num_down = numberstack.pop();
        if(que.peek()=='+'){
          numberstack.push(String(Number(num_down)+Number(num_up)))
       //   console.log(`${String(Number(num_down)+Number(num_up))}入栈`)
        }
        else if(que.peek()=='-'){
          numberstack.push(String(Number(num_down)-Number(num_up)))
        //  console.log(`${String(Number(num_down)-Number(num_up))}入栈`)

        }
        //遇到‘3’时会出现精度问题,故这里解决的是精度问题
        else if(que.peek()=='×'){
          if(num_up=='3'||num_up=='6'||num_up=='9') {
            numberstack.push(String((Number(num_down)*(Number(num_up)*10000))/10000))
          }
          else{
            numberstack.push(String((Number(num_down) * Number(num_up) * 100) / 100))
          }
       //   console.log(`${String(Number(num_down)*Number(num_up))}入栈`)
        }
        else if(que.peek()=='÷'){
          if(num_up=='0') numberstack.push('不能除以0')
          else {
            numberstack.push(String(Number(num_down) / Number(num_up)))
          }
       //   console.log(`${String(Number(num_down)/Number(num_up))}入栈`)
        }
        que.dequeue();
        i++;
      }
    }
    return String(numberstack.pop());
}

总结及心得

到了这里,基本上这个计算器的主要组成部分已经大功告成了,在这次做这个计算器的时候遇到了不少困难,由于没有系统学习数据结构的知识,导致完成计算逻辑时不知道从何下手,查阅了大量资料后才明白了其中的道理,最后完成了这个仍然存在一些瑕疵的计算器。
虽然过程难了一点,不过好在结果是好的,所以我觉得当我们在学习计算机知识的时候切记一定不要急躁,要看清每一个细节,打牢每一个基础,这里引用初中政治老师常说的一句话:“基础不牢,地动山摇”,现在回头看这句话说的真的很对,无论哪个行业或者哪个学科都不是一蹴而就的,而是日积月累的,一个个细小的知识点(基础)才能构成稳固的知识体系。
下面是我做的计算器的全部代码分享给大家(注:科学计算器里面功能没有实现!!!),如果有什么改进的好想法可以发在评论区呢~

完整代码(多个子组件和父组件都写在里面,复制后不可直接使用,需要拆分以下 && 父组件中满足if条件后的代码不具有参考价值!!!)

import { Button1 } from '../model/Button1'
import { Button1_second } from '../model/Button1_second'
import { Button2_second } from '../model/Button2_second'
import { Button2 } from '../model/Button2'
import {CharacterStack} from '../model/CharacterStack'
import {NumberStack} from '../model/NumberStack'
import {queue_my} from '../model/Queue'

//科学计算器中‘0’按钮子组件】
export struct Button2_second{
  @Link cal:string
  @Link button_opacity_son:number
  num:string = '0'
  buttonColor:number = 0x333333
  textColor:number = Color.White
  textSize:number = 28

  build() {
    Column(){
      Text(`${this.num}`)
        .fontColor(this.textColor)
        .fontWeight(FontWeight.Medium)
        .fontSize(this.textSize)
    }.justifyContent(FlexAlign.Center)
    .onTouch((Event:TouchEvent)=>{
      if(Event.type==TouchType.Down){
        this.button_opacity_son = 0.5
      }
      if(Event.type==TouchType.Up){
        this.button_opacity_son = 1;
      }
    })
    .width(130)
    .opacity(this.button_opacity_son)
    .height(60)
    .alignItems(HorizontalAlign.Center)
    .backgroundColor(this.buttonColor)
    .borderRadius(40)
    .onClick(()=>{
      this.cal+=this.num;
    })
  }

}

//计算器主界面‘0’按钮子组件
export struct Button2{
  @Link cal:string
  @Link button_opacity_son:number
    num:string = '0'
    buttonColor:number = 0x333333
    textColor:number = Color.White
    textSize:number = 28

  build() {
      Column(){
        Text(`${this.num}`)
          .fontColor(this.textColor)
          .fontWeight(FontWeight.Medium)
          .fontSize(this.textSize)
      }.justifyContent(FlexAlign.Center)
      .onTouch((Event:TouchEvent)=>{
        if(Event.type==TouchType.Down){
          this.button_opacity_son = 0.5
        }
        if(Event.type==TouchType.Up){
          this.button_opacity_son = 1;
        }
      })
      .width(170)
      .opacity(this.button_opacity_son)
      .height(80)
      .alignItems(HorizontalAlign.Center)
      .backgroundColor(this.buttonColor)
      .borderRadius(40)
    .onClick(()=>{
      this.cal+=this.num;
    })
    }

}

//科学计算器圆形按钮子组件
import {calculate_achieve} from '../pages/Index'
import {SwitchMiddleToEnd} from '../pages/Index'
import {roundToDecimal} from '../pages/Index'
@Component
export struct Button1_second{
  @Link cal:string
  @Link result:string|undefined|number
  @Consume flag:boolean
  @Link button_opacity_son:number
  num:string = '1'
  buttonColor:number = 0x333333
  textColor:number = Color.White
  textSize:number = 24

  build() {
    Column(){
      Text(`${this.num}`)
        .fontColor(this.textColor)
        .fontWeight(FontWeight.Medium)
        .fontSize(this.textSize)
    }.justifyContent(FlexAlign.Center)
    .onTouch((Event:TouchEvent)=>{
      if(Event.type==TouchType.Down){
        this.button_opacity_son = 0.5
      }
      if(Event.type==TouchType.Up){
        this.button_opacity_son = 1;
      }
    })
    .width(60)
    .height(60)
    .opacity(this.button_opacity_son)
    .alignItems(HorizontalAlign.Center)
    .backgroundColor(this.buttonColor)
    .borderRadius(30)
    .onClick(()=>{
      if(this.num=='AC'){
        this.flag = true;
        this.cal='';
        this.result = '0';
        return
      }
      else if(this.num=='='){
        if(this.flag == true) {
          this.flag = false;
          let EndExpression =SwitchMiddleToEnd(this.cal);
          EndExpression.print_queue()
          this.result = calculate_achieve(EndExpression);
        }
        else {
          let EndExpression = SwitchMiddleToEnd(this.cal);
          EndExpression.print_queue()
          this.result = calculate_achieve(EndExpression);
          this.result = String(roundToDecimal(this.result));
        }
      }
      else {
        this.cal += this.num;
      }

    })
  }
}
//计算器主界面圆形按钮子组件
import {calculate_achieve} from '../pages/Index'
import {SwitchMiddleToEnd} from '../pages/Index'
export struct Button1{
  //计算式
  @Link cal:string
  //计算结果
  @Link result:string|undefined|number
  //是否已经按下等号的标记
  @Consume flag:boolean
  //按钮透明度设置
  @Link button_opacity_son:number
  //1为测试数据
  num:string = '1'
  //按钮颜色
  buttonColor:number = 0x333333
  //文本颜色
  textColor:number = Color.White
  //文本大小
  textSize:number = 28

  build() {
   Column(){
     Text(`${this.num}`)
       .fontColor(this.textColor)
       .fontWeight(FontWeight.Medium)
       .fontSize(this.textSize)
   }.justifyContent(FlexAlign.Center)
   //按下按钮时,按钮的透明度改变
   .onTouch((Event:TouchEvent)=>{
     if(Event.type==TouchType.Down){
       this.button_opacity_son = 0.5
     }
     if(Event.type==TouchType.Up){
       this.button_opacity_son = 1;
     }
   })
    .width(80)
    .height(80)
    .opacity(this.button_opacity_son)
    .alignItems(HorizontalAlign.Center)
    .backgroundColor(this.buttonColor)
    .borderRadius(40)
    .onClick(()=>{
      //’AC‘功能的实现
      if(this.num=='AC'){
        this.flag = true;
        this.cal='';
        this.result = '0';
        return
      }
      else if(this.num=='='){
        //如果第一次按下等号就显示等号
        if(this.flag == true) {
          this.flag = false;
          let EndExpression =SwitchMiddleToEnd(this.cal);
          EndExpression.print_queue()
          this.result = calculate_achieve(EndExpression);
        }
        //否则不显示等号
        else {
          let EndExpression = SwitchMiddleToEnd(this.cal);
          EndExpression.print_queue()
          this.result = calculate_achieve(EndExpression);
          this.result = String(roundToDecimal(this.result));
        }
      }
      //将按钮所对应的字符加到计算式后
      else {
        this.cal += this.num;
      }

    })
}
}

//数字栈
export class NumberStack{
    numberstack:string[];

  constructor() {
    this.numberstack = [];
  }

  push(item:string){
    this.numberstack.push(item);
  }

  pop(){
   return this.numberstack.pop()
  }

  peek(){
    return this.numberstack[this.numberstack.length-1]
  }

  isEmpty(){
    return this.numberstack.length ? false : true
  }

  clear(){
    this.numberstack = [];
  }

}

//操作符栈
export class CharacterStack{
  characterstack:string[];

  constructor() {
    this.characterstack = [];
  }

  push(item:string){
    this.characterstack.push(item);
  }

  pop(){
     return this.characterstack.pop()
  }

  length(){
    return this.characterstack.length;
  }

  peek(){
    return this.characterstack[this.characterstack.length-1]
  }

  isEmpty(){
    return this.characterstack.length ? false : true
  }

  clear(){
    this.characterstack = [];
  }

}

export class queue_my{
   items:string[]

  constructor(){
    this.items = [];
  }

  enqueue(item:string){
    this.items.push(item);
  }

  //删除第一个元素并且返回被删除的元素
  dequeue(){
    return this.items.shift();
  }

  //返回队列中的第一个元素
  peek(){
    return this.items[0];
  }

  //判断队列是否为空
  isEmpty(){
    return this.items.length ? false : true;
  }

  //返回队列大小
  size(){
    return this.items.length;
  }
  //打印队列中的元素
  print_queue(){
    for(let i =0;i<this.items.length;i++){
      console.log(this.items[i]);
    }
  }


}
//父组件(入口)
import { Button1 } from '../model/Button1'
import { Button1_second } from '../model/Button1_second'
import { Button2_second } from '../model/Button2_second'
import { Button2 } from '../model/Button2'
import {CharacterStack} from '../model/CharacterStack'
import {NumberStack} from '../model/NumberStack'
import {queue_my} from '../model/Queue'
@Entry
@Component
struct Index {
  @State cal:string = '';
  @State result:string|undefined|number = '';
  @Provide flag:boolean = true;
  @State rotate_icon:number = 0;
  sta_x = 0;
  distance_x = 0;
  @State UIstate:boolean = false;
  @State Delete_bool:boolean = false;
  @State button_opacity_0:number = 1
  @State button_opacity_1:number = 1
  @State button_opacity_2:number = 1
  @State button_opacity_3:number = 1
  @State button_opacity_4:number = 1
  @State button_opacity_5:number = 1
  @State button_opacity_6:number = 1
  @State button_opacity_7:number = 1
  @State button_opacity_8:number = 1
  @State button_opacity_9:number = 1
  @State button_opacity_10:number = 1
  @State button_opacity_11:number = 1
  @State button_opacity_12:number = 1
  @State button_opacity_13:number = 1
  @State button_opacity_14:number = 1
  @State button_opacity_15:number = 1
  @State button_opacity_16:number = 1
  @State button_opacity_17:number = 1
  @State button_opacity_18:number = 1
  @State button_opacity_19:number = 1
  @State button_opacity_20:number = 1
  @State button_opacity_21:number = 1
  @State button_opacity_22:number = 1
  @State button_opacity_23:number = 1
  @State button_opacity_24:number = 1
  build() {
      Column({space:10}) {
        Row() {
          Image($r('app.media.change'))
            .width(40)
            .height(40)
            .rotate({angle:this.rotate_icon})
            .animation({
              duration:300
            })
            .onClick(()=>{
              this.rotate_icon = this.rotate_icon+180;
              this.UIstate = !this.UIstate;
            })
        }.width('100%')
        .justifyContent(FlexAlign.End)
        .margin({top:10,right:15})

        Blank()
        Column() {
          Text(`${this.result}`)
            .fontSize(60)
            .fontColor(Color.White)
        }
        .alignItems(HorizontalAlign.End)
        .justifyContent(FlexAlign.End)
        .padding({ right: 30 })
        .width('100%')
        .height(100)

        Row() {
          Text(`${this.cal}`)
            .fontSize(24)
            .fontColor(Color.White)
        }.height(70)
        .width('100%')
        .justifyContent(FlexAlign.End)
        .padding({ right: 35 })
        .onTouch((Event:TouchEvent)=>{
          if(Event.type==TouchType.Down){
            this.sta_x = Event.touches[0].x
            this.Delete_bool = true;
          }
          if(Event.type==TouchType.Up){
              this.Delete_bool = true
          }
          if(Event.type==TouchType.Move){
              this.distance_x = Math.abs(this.sta_x - Event.touches[0].x)
           // console.log(`x轴的距离为:${this.distance_x}`)
           // console.log(`bool值为:${this.Delete_bool}`)
            if(this.distance_x>20&&this.Delete_bool == true){
             this.cal = this.cal.slice(0,-1);
             this.Delete_bool = false;
            }
          }
        })


		//*******************************************************
		//*******************************************************
		//下面满足if条件代码为科学器部分,不建议参考,有大瑕疵!!!!!!
		//else条件中的代码为计算器主界面代码,值得参考!!!
		//*******************************************************
		//*******************************************************
        if (this.UIstate == true) {
          Row({ space: 10 }) {
            Button1_second({
              cal: $cal,
              button_opacity_son: $button_opacity_0,
              result: $result,
              num: 'lg',
              textColor: Color.Black,
              buttonColor: 0xA5A5A5
            })
            Button1_second({
              cal: $cal,
              button_opacity_son: $button_opacity_0,
              result: $result,
              num: 'ln',
              textColor: Color.Black,
              buttonColor: 0xA5A5A5
            })
            Button1_second({
              cal: $cal,
              button_opacity_son: $button_opacity_0,
              result: $result,
              num: 'sin',
              textColor: Color.Black,
              buttonColor: 0xA5A5A5
            })
            Button1_second({
              cal: $cal,
              button_opacity_son: $button_opacity_0,
              result: $result,
              num: 'cos',
              textColor: Color.Black,
              buttonColor: 0xA5A5A5
            })
            Button1_second({
              cal: $cal,
              button_opacity_son: $button_opacity_0,
              result: $result,
              num: 'tan',
              textColor: Color.Black,
              buttonColor: 0xA5A5A5
            })
          }

          Row({ space: 10 }) {
            Button1_second({
              cal: $cal,
              button_opacity_son: $button_opacity_0,
              result: $result,
              num: 'AC',
              textColor: Color.Black,
              buttonColor: 0xA5A5A5
            })
            Button1_second({
              cal: $cal,
              button_opacity_son: $button_opacity_1,
              result: $result,
              num: '(',
              textColor: Color.Black,
              buttonColor: 0xA5A5A5
            })
            Button1_second({
              cal: $cal,
              button_opacity_son: $button_opacity_2,
              result: $result,
              num: ')',
              textColor: Color.Black,
              buttonColor: 0xA5A5A5
            })
            Button1_second({
              cal: $cal,
              button_opacity_son: $button_opacity_3,
              result: $result,
              num: '÷',
              buttonColor: 0xFF9F0B
            })
            Button1_second({
              cal: $cal,
              button_opacity_son: $button_opacity_4,
              result: $result,
              num: '%',
              textSize: 22,
              buttonColor: 0xFF9F0B
            })
          }

          Row({ space: 10 }) {
            Button1_second({
              cal: $cal,
              button_opacity_son: $button_opacity_4,
              result: $result,
              num: '7'
            })
            Button1_second({
              cal: $cal,
              button_opacity_son: $button_opacity_5,
              result: $result,
              num: '8'
            })
            Button1_second({
              cal: $cal,
              button_opacity_son: $button_opacity_6,
              result: $result,
              num: '9'
            })
            Button1_second({
              cal: $cal,
              button_opacity_son: $button_opacity_7,
              result: $result,
              num: '×',
              textSize: 30,
              buttonColor: 0xFF9F0B
            })
            Button1_second({
              cal: $cal,
              button_opacity_son: $button_opacity_7,
              result: $result,
              num: 'x!',
              textSize: 24,
              buttonColor: 0xFF9F0B
            })
          }

          Row({ space: 10 }) {
            Button1_second({
              cal: $cal,
              button_opacity_son: $button_opacity_8,
              result: $result,
              num: '4'
            })
            Button1_second({
              cal: $cal,
              button_opacity_son: $button_opacity_9,
              result: $result,
              num: '5'
            })
            Button1_second({
              cal: $cal,
              button_opacity_son: $button_opacity_10,
              result: $result,
              num: '6'
            })
            Button1_second({
              cal: $cal,
              button_opacity_son: $button_opacity_11,
              result: $result,
              num: '-',
              textSize: 30,
              buttonColor: 0xFF9F0B
            })
            Button1_second({
              cal: $cal,
              button_opacity_son: $button_opacity_11,
              result: $result,
              num: '1/x',
              textSize: 20,
              buttonColor: 0xFF9F0B
            })
          }

          Row({ space: 10 }) {
            Button1_second({
              cal: $cal,
              button_opacity_son: $button_opacity_12,
              result: $result,
              num: '1'
            })
            Button1_second({
              cal: $cal,
              button_opacity_son: $button_opacity_13,
              result: $result,
              num: '2'
            })
            Button1_second({
              cal: $cal,
              button_opacity_son: $button_opacity_14,
              result: $result,
              num: '3'
            })
            Button1_second({
              cal: $cal,
              button_opacity_son: $button_opacity_15,
              result: $result,
              num: '+',
              textSize: 30,
              buttonColor: 0xFF9F0B
            })
            Button1_second({
              cal: $cal,
              button_opacity_son: $button_opacity_15,
              result: $result,
              num: 'π',
              textSize: 24,
              buttonColor: 0xFF9F0B
            })
          }

          Row({ space: 10 }) {
            Button2_second({ cal: $cal, button_opacity_son: $button_opacity_16 })
            Button1_second({
              cal: $cal,
              button_opacity_son: $button_opacity_17,
              result: $result,
              num: '.'
            })
            Button1_second({
              cal: $cal,
              button_opacity_son: $button_opacity_18,
              result: $result,
              num: '=',
              textSize: 30,
              buttonColor: 0xFF9F0B
            })
            Button1_second({
              cal: $cal,
              button_opacity_son: $button_opacity_18,
              result: $result,
              num: '=',
              textSize: 30,
              buttonColor: 0xFF9F0B
            })
          }.margin({ bottom: 20 })
        }
//以上if中的代码不可参考!!!
//以下代码可参考!!!
        else {
          Row({ space: 10 }) {
            Button1({
              cal: $cal,
              button_opacity_son: $button_opacity_0,
              result: $result,
              num: 'AC',
              textColor: Color.Black,
              buttonColor: 0xA5A5A5
            })
            Button1({
              cal: $cal,
              button_opacity_son: $button_opacity_1,
              result: $result,
              num: '(',
              textColor: Color.Black,
              buttonColor: 0xA5A5A5
            })
            Button1({
              cal: $cal,
              button_opacity_son: $button_opacity_2,
              result: $result,
              num: ')',
              textColor: Color.Black,
              buttonColor: 0xA5A5A5
            })
            Button1({
              cal: $cal,
              button_opacity_son: $button_opacity_3,
              result: $result,
              num: '÷',
              buttonColor: 0xFF9F0B
            })
          }

          Row({ space: 10 }) {
            Button1({
              cal: $cal,
              button_opacity_son: $button_opacity_4,
              result: $result,
              num: '7'
            })
            Button1({
              cal: $cal,
              button_opacity_son: $button_opacity_5,
              result: $result,
              num: '8'
            })
            Button1({
              cal: $cal,
              button_opacity_son: $button_opacity_6,
              result: $result,
              num: '9'
            })
            Button1({
              cal: $cal,
              button_opacity_son: $button_opacity_7,
              result: $result,
              num: '×',
              textSize: 30,
              buttonColor: 0xFF9F0B
            })

          }

          Row({ space: 10 }) {
            Button1({
              cal: $cal,
              button_opacity_son: $button_opacity_8,
              result: $result,
              num: '4'
            })
            Button1({
              cal: $cal,
              button_opacity_son: $button_opacity_9,
              result: $result,
              num: '5'
            })
            Button1({
              cal: $cal,
              button_opacity_son: $button_opacity_10,
              result: $result,
              num: '6'
            })
            Button1({
              cal: $cal,
              button_opacity_son: $button_opacity_11,
              result: $result,
              num: '-',
              textSize: 30,
              buttonColor: 0xFF9F0B
            })
          }

          Row({ space: 10 }) {
            Button1({
              cal: $cal,
              button_opacity_son: $button_opacity_12,
              result: $result,
              num: '1'
            })
            Button1({
              cal: $cal,
              button_opacity_son: $button_opacity_13,
              result: $result,
              num: '2'
            })
            Button1({
              cal: $cal,
              button_opacity_son: $button_opacity_14,
              result: $result,
              num: '3'
            })
            Button1({
              cal: $cal,
              button_opacity_son: $button_opacity_15,
              result: $result,
              num: '+',
              textSize: 30,
              buttonColor: 0xFF9F0B
            })
          }

          Row({ space: 10 }) {
            Button2({ cal: $cal, button_opacity_son: $button_opacity_16 })
            Button1({
              cal: $cal,
              button_opacity_son: $button_opacity_17,
              result: $result,
              num: '.'
            })
            Button1({
              cal: $cal,
              button_opacity_son: $button_opacity_18,
              result: $result,
              num: '=',
              textSize: 30,
              buttonColor: 0xFF9F0B
            })
          }
          .margin({ bottom: 20 })
        }
      }
      .width('100%')
    .height('100%')
    .backgroundColor(Color.Black)

  }
}
//获得优先级等级的函数
function getPrecedence(item:string):number{
  switch(item){
    case '%':return 3
    case '×':return 2
    case '÷':return 2
    case '+':
     // console.log('读取到了+号')
      return 1
    case '-':return 1
    default:return 0
  }

}

//中缀表达式转后缀表达式函数
export function SwitchMiddleToEnd(cal:string){
  let queue = new queue_my();
  let first_fu:boolean = true
  let switchStack = new CharacterStack();
  let i =0;
  while(i<cal.length){
    //如果遍历到数字直接入队
    if(isNumber(cal[i])){
      let numberstring = '';
      while(isNumber(cal[i])){
        numberstring+=cal[i];
        i++
      }
      queue.enqueue(numberstring);
      console.log(`${numberstring}入队`);
      i--

    }
    //如果遇到第一个位置是左括号加-号
      else if(cal[0]=='('&&cal[1]=='-'&&first_fu){
        switchStack.push(cal[0]);
        let numberstring = '-'
        first_fu = false;
        i = 2
        while(isNumber(cal[i])){
          numberstring+=cal[i]
          i++
        }
        queue.enqueue(numberstring)
      i--
      console.log(`${numberstring}入队`);
      console.log(`此时遍历到了:${cal[i]}`)
    }
    else if(cal[0]=='-'&&isNumber(cal[1])&&first_fu){
      let numberstring = '-';
      first_fu = false;
      i=1;
      while(isNumber(cal[i])){
        numberstring+=cal[i];
        i++
      }
      queue.enqueue(numberstring);
      console.log(`${numberstring}入队`);
      i--;
    }
    //如果连按几次同一个操作符
      else if(!isNumber(cal[i])&&!isNumber(cal[i+1])&&cal[i]==cal[i+1]){
        i++;
    }
    //带括号的负数在中间的时候
      else if(cal[i]=='('&&cal[i+1]=='-'&&isNumber(cal[i+2])){
      let numberstring = '-';
      i = i+2;
      while(isNumber(cal[i])){
        numberstring+=cal[i];
        ++i
      }
      queue.enqueue(numberstring)
      console.log(`${numberstring}已经入队`)
    }

    //如果栈中为空或者遇到左括号直接入栈
    else if(switchStack.isEmpty()||cal[i]=='('){
      if(cal[i]=='(') console.log('遇到了左括号')
      switchStack.push(cal[i]);
    }
    //栈顶操作符优先级小于当前操作符优先级
    else if(cal[i]!=')'&&getPrecedence(switchStack.peek())<getPrecedence(cal[i])){
      switchStack.push(cal[i]);
    }
    //栈顶操作符优先级大于当前操作符优先级
    else if(cal[i]!=')'&&getPrecedence(switchStack.peek())>=getPrecedence(cal[i])){
        //栈顶元素出栈并且加到队列中去
        while(getPrecedence(cal[i])<=getPrecedence(switchStack.peek()))
        {queue.enqueue(String(switchStack.pop()))
          if(switchStack.isEmpty()){break}
        }
        switchStack.push(cal[i]);
    }
    //如果遇到了右括号
    else if(cal[i]==')') {
     // console.log('遇到了右括号')
      while (switchStack.peek() != '(') {
        let temp: string = String(switchStack.pop());
        queue.enqueue(temp);
      }
      //遇到左括号时直接将左括号弹出
      switchStack.pop()
     // console.log('左括号出栈')
    }
    i++;
  }
  //最后将剩余的操作符全部放到队列中
  while(!switchStack.isEmpty()) {
    queue.enqueue(String(switchStack.pop()))
  }
  return queue;
}
//后缀表达式计算函数
export function calculate_achieve(que:queue_my):string{
    let numberstack = new NumberStack();
    let i =0;
    let sum=que.size()
    while(i<sum){
      //如果遇到数字直接入栈并删除该元素
      if(!isCharacter(que.peek())){
        console.log(`${que.peek()}已经入栈`)
          numberstack.push(que.peek());
          que.dequeue()
          i++;
      }
      //如果遇到了操作符
      else{
        let num_up = numberstack.pop();
        let num_down = numberstack.pop();
        if(que.peek()=='+'){
          numberstack.push(String(Number(num_down)+Number(num_up)))
       //   console.log(`${String(Number(num_down)+Number(num_up))}入栈`)
        }
        else if(que.peek()=='-'){
          numberstack.push(String(Number(num_down)-Number(num_up)))
        //  console.log(`${String(Number(num_down)-Number(num_up))}入栈`)

        }
        else if(que.peek()=='×'){
          if(num_up=='3'||num_up=='6'||num_up=='9') {
            numberstack.push(String((Number(num_down)*(Number(num_up)*10000))/10000))
          }
          else{
            numberstack.push(String((Number(num_down) * Number(num_up) * 100) / 100))
          }
       //   console.log(`${String(Number(num_down)*Number(num_up))}入栈`)
        }
        else if(que.peek()=='÷'){
          if(num_up=='0') numberstack.push('不能除以0')
          else {
            numberstack.push(String(Number(num_down) / Number(num_up)))
          }
       //   console.log(`${String(Number(num_down)/Number(num_up))}入栈`)
        }
        que.dequeue();
        i++;
      }
    }
    return String(numberstack.pop());
}
//判断这个字符是不是数字
function isNumber(item:string):boolean{
  if(item=='0'||item=='1'||item=='2'||item=='3'||item=='4'||item=='5'||item=='6'||
    item=='7'||item=='8'||item=='9'||item=='.'){
    return true;
  }
  else return false;
}
//判断这个字符是不是操作符
function isCharacter(item:string):boolean{
  if(item=='+'||item=='-'||item=='÷'||item=='×'||item=='('||item==')'){
    return true;
  }
  else return false;
}


  • 26
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值