zoukankan      html  css  js  c++  java
  • Minigui开发之遥控控制逻辑算法

      引言

      在开发公司的minigui产品时,需要用遥控器来切换显示屏上的图标和控件,这就涉及到一个问题,如何获得下一个选中的图标或控件呢?

      解决思路

      利用每个控件自身的ID号,建立一张类似矩阵的表,用坐标来定位每个控件,通过编写的查找算法,输入当前选择的控件ID号和遥控动作(上下左右),输出下一个选中的控件ID号。

      数据结构

        

    typedef struct{
        int id;
        int row;
        int col;
    }NODE_T;
    
    typedef struct{
        int nRow;
        int nCol;
        NODE_T *arrayList[MAX_LOGIN_NUM][MAX_LOGIN_NUM];
    }LIST_T;

      其中LIST_T中的,nRow和nCol代表目前矩阵表的最大行数和列数,NODE_T为每个元素的结构体数据,arrayList为二维指针数组,最大可保存MAX_LOGIN_NUM*MAX_LOGIN_NUM个元素地址。

      在NODE_T中,id即控件的ID号,row和col代表该元素在矩阵表中的坐标。

      初始化

      初始化过程非常简单,即将最大行数和列数设置为0,并初始化矩阵表,将指针设为NULL。

    void initList(LIST_T *list)
    {
        list->nRow = 0;
        list->nCol = 0;
    
        int i = 0;
        int j = 0;
    
        for(i = 0; i < MAX_LOGIN_NUM; i++)
        {
            for(j = 0; j < MAX_LOGIN_NUM; j++)
            {
                list->arrayList[i][j] = NULL;
            }
        }
    }

      添加节点

      添加节点的大体过程,即先判断需要存入的节点坐标,是否在已有矩阵表范围之外,如果在范围外,则需要扩充矩阵表的大小(即更改最大行数和列数),如果在范围内,则需要检查存入的坐标是否已经有节点存在了,在这里,如果该坐标已经有节点存在了,则执行添加节点失败,大家可以根据实际情况来处理。

    int addNode(LIST_T *list, int id, int row, int col)
    {
        int isNeedCheck = 1;        //0:需要检查该坐标是否存在节点 1:无需检查
        
        //数据合法校验
        int numOfRow = getNumOfRow(list);
        if(row > (numOfRow - 1))
        {
            list->nRow = row + 1;
            isNeedCheck = 0;
        }
    
        int numOfCol = getNumOfCol(list);
        if(col > (numOfCol - 1))
        {
            list->nCol = col + 1;
            isNeedCheck = 0;
        }
        
        int ret = 0;
    
        if(1 == isNeedCheck)
        {
            //插入位置是否存在节点,存在则不允许插入
            ret = isNodeExist(list, row, col);
            if(ret > 0)
            {
                printf("Node exist in (%d, %d)
    ", row, col);
                return (-1);
            }
        }
    
        NODE_T *tmp = (NODE_T *)calloc(sizeof(NODE_T), 1);
        tmp->row = row;
        tmp->col = col;
        tmp->id = id;
    
        //将节点插入到链表中
        list->arrayList[row][col] = tmp;
    
        return 0;
    }

      查找节点

      下面就是本文的重点,也是遥控逻辑算法的核心:如何查找到下一个选中的节点。

      

     

      如上图所示,当前有ABCD四个控件,即矩阵表中有四个元素,它们的坐标分别是 A(0, 0), B(0, 1), C(1, 2), D(2, 1)

      此时,用户选中的是控件A,如果用户按下遥控上的“右键”,按照此图,程序应该找到A右边的节点,即B节点。当然这是非常理想的一种情况,实际情况要比这个更加复杂。

      假如此时用户已经选择了B,再次按下“右键”时,程序应该有两种搜索方案:

      1.同一行循环搜索。即一直在B所在的行来搜索下一个节点,首先搜索的是B的右边,即(0, 2)这个点,如果该点存在元素即返回该元素,如果搜索到了行的尽头仍然没有搜索到,即调回到这一行的开头继续从左至右的搜索,直到找到一个节点(这里将找到A节点)。

      2.下跳一行搜索。过程和上述方法类似,都先找到行的尽头,不过这里将跳到下一行的开始,继续从左向右的搜索,直到找到一个节点(这里将找到C节点)。

      以上是按下“右键”的处理方式,如果用户按下“左键”,搜索方式大体相同,只不过是将搜索方向由“从左至右”改为“从右至左”。

      

      至于按下“上键”和“下键”的搜索方式,只是在以上两种情况上多加了一层处理,比如,用户当前选择了A节点,然后按下“下键”,首先搜寻的是A节点下方是否存在节点(即(1, 0)),若有则返回,如果没有搜寻到节点的话,则转为按下“右键”的搜寻方式,即在这里,算法将返回B节点。

      同理,“上键”的处理方式在找不到上方节点的情况下,将转化为按下“左键”的处理方式。

      还需补充一点的是,当搜索到行的尽头时,即第一行和最后一行,需要注意越界的问题,此时应跳转到具有有效数据的行(最后一行按下“下键”,跳到第一行搜索)

      下面是“左键”和“右键”的搜索方式,“上键”和“下键”刚刚已经说过,只是多了一层处理而已。

    int leftFind(LIST_T *list, int row, int col, int isCircle, int *outRow, int *outCol)
    {
        //从(row, col)开始向左寻找
        getCoordinate(list, row, col, LEFT, isCircle, &row, &col);
        
        int i = col;
    
        for(; i >= 0; i--)
        {
            if(list->arrayList[row][i] != NULL)
            {
                *outRow = list->arrayList[row][i]->row;
                *outCol = list->arrayList[row][i]->col;
    
                return 0;
            }
        }
    
        //尾递归调用
        leftFind(list, row, col, isCircle, outRow, outCol);
    
        return 0;
    }
    
    int rightFind(LIST_T *list, int row, int col, int isCircle, int *outRow, int *outCol)
    {
        //从(row, col)开始向右寻找
        getCoordinate(list, row, col, RIGHT, isCircle, &row, &col);
        
        int i = col;
    
        for(; i < getNumOfCol(list); i++)
        {
            if(list->arrayList[row][i] != NULL)
            {
                *outRow = list->arrayList[row][i]->row;
                *outCol = list->arrayList[row][i]->col;
    
                return 0;
            }
        }
    
        //尾递归调用
        rightFind(list, row, col, isCircle, outRow, outCol);
    
        return 0;
    }
  • 相关阅读:
    浅谈UML学习笔记之用例图
    浅谈UML学习笔记之类图
    浅谈UML学习笔记动态模型之序列图、协作图
    七天LLVM零基础入门(Linux版本)第一天
    浅谈UML学习笔记之构件图和部署图
    浅谈UML的概念和模型之UML类图关系
    浅谈UML的概念和模型之UML九种图
    浅谈UML学习笔记动态图之状态图和活动图
    Oracle Data Types
    Chapter 04Tuning the shared Pool
  • 原文地址:https://www.cnblogs.com/xyliao/p/4371512.html
Copyright © 2011-2022 走看看