学习笔记--分布式数字华容道(下)

想了解更多内容,学习下请访问:

和华为官方合作共建的笔记鸿蒙技术社区

https://harmonyos.51cto.com

前言

我又来了。最近比较忙,分布导致这一篇文章拖了好久还没写,式数只能趁着国庆放假抽空写一写了。字华继前两篇文章的容道铺垫,我们这一篇文章就来实现分布式数字华容道的学习下双人模式。前面的笔记请参考学习笔记–分布式数字华容道(中)。

那现在就先开始我们今天的分布学习吧。

正文

那我们在双人模式中呢,式数怎么进行同步就是字华一个最重要的问题了。那我们这个游戏呢,容道就运用分布式数据库来进行我们两台设备数据的学习下同步了。

那要实现出一个分布式数据库的笔记话,我们就需要先定义一些变量。分布

private static final HiLogLabel TAG = new HiLogLabel(HiLog.LOG_APP,0x12345,"signal");   private static int difficulty = 3;   private DirectionalLayout layout;   private static int length;   private static final int interval = 5;   private static final int left = 32;   private static final int top = 300;   private static final int margin = 15;   private static int length1;   private static final int left1 = 32;   private static final int top1 = 1350;   private static final int margin1 = 10;   private static int row_a0;   private static int column_a0;   private static int row_b0;   private static int column_b0;   private float startX;   private float startY;   private static Timer timer;   private static Timer updatetimer;   private static Timer restarttimer;   private static Timer backtimer;   private static Text timetext ;   private static Text maxtext;   private static Text wintext;   private static int hour;   private static int min;   private static int sec;   private static int msec;   private static int restart = 0;   private static int back = 0;   private static int maxhour = 23;   private static int maxmin = 59;   private static int maxsec = 59;   private static int maxmsec = 99;   private static int[][] grids_a;   private static int[][] grids_b;   private static final String STROE_ID = "data";   private static String randomstr = "";   private static String winner = "";   private static KvManager kvManager;   private static String strhour = "";   private static String strmin = "";   private static String strsec = "";   private static String strmsec = "";   private static String text = "暂停";   private SingleKvStore singleKvStore;   private static Button button_moveback;   private static Boolean isLocal; 

 接下来就是写一个分布式数据库

private KvManager createManger() { //辅助类      KvManager manager = null;      try{           KvManagerConfig config = new KvManagerConfig(this);          manager = KvManagerFactory.getInstance().createKvManager(config);      } catch (KvStoreException exception) {           HiLog.info(TAG,"ERROR");      }      return manager;  }  private SingleKvStore createDb(KvManager kvManager) { //数据库      SingleKvStore kvStore = null;      try{           Options options = new Options();          options.setCreateIfMissing(true).setEncrypt(false).setKvStoreType(KvStoreType.SINGLE_VERSION);          kvStore = kvManager.getKvStore(options,STROE_ID);      } catch (KvStoreException exception) {           HiLog.info(TAG,"ERROR");      }      return kvStore;  }  private void subscribeDb(SingleKvStore singleKvStore) { //订阅      class KvStoreObserveClient implements KvStoreObserver {           @Override          public void onChange(ChangeNotification notification) {           }      }      KvStoreObserver kvStoreObserverClient = new KvStoreObserveClient();      singleKvStore.subscribe(SubscribeType.SUBSCRIBE_TYPE_ALL,kvStoreObserverClient);  }  private void initDbManager() {       kvManager = createManger();      singleKvStore = createDb(kvManager);      subscribeDb(singleKvStore);  } 

 再写两个写入数据库的函数还有读取的函数。

private int queryContact_int(String key) {       try {           return singleKvStore.getInt(key);      } catch (KvStoreException exception) {           HiLog.info(TAG,"int error" + exception.getMessage());          return -1;      }  }  private String queryContact_String(String key) {       try {           return singleKvStore.getString(key);      } catch (KvStoreException exception) {           HiLog.info(TAG,"String error" + exception.getMessage());          return null;      }  }  private void writeData_String(String key , String value) {       if (key == null || key.isEmpty() || value == null || value.isEmpty())          return;      singleKvStore.putString(key,value);  }  private void writeData_int(String key,int value) {       if (key == null || key.isEmpty()) {           return;      }      singleKvStore.putInt(key,value);  } 

 那接下里我们就写一个在数据库中读取记录的函数,当开始游戏的时候,会读取该阶数中的最快的云服务器提供商记录。

public void getrecord() {          if (queryContact_int("hour" + difficulty) != -1)             maxhour = queryContact_int("hour" + difficulty);         else             maxhour = 23;         if (queryContact_int("min" + difficulty) != -1)             maxmin = queryContact_int("min" + difficulty);         else             maxmin = 59;         if (queryContact_int("sec" + difficulty) != -1)             maxsec = queryContact_int("sec" + difficulty);         else             maxsec = 59;         if (queryContact_int("msec" + difficulty) != -1)             maxmsec = queryContact_int("msec" + difficulty);         else             maxmsec = 99;     } 

 接下来我们就开始初始化我们的数组了,然后把一台设备初始化完了的数组写到数据库中,让另外一台设备来读取数据库中的数据,再用来初始化该设备的数组。

public void createGrids() {         randomstr = "";        if (isLocal) {             int random;            int i = 0;            while(i < difficulty * difficulty * 5) {                 random = (int)Math.floor(Math.random() *4 );                randomstr += random;                int temp_row = row_a0;                int tem_column = column_a0;                if(random == 0){                     changeGrids(row_a0 - 1, column_a0);                }else if(random == 1){                     changeGrids(row_a0 + 1, column_a0);                }else if(random == 2){                     changeGrids(row_a0, column_a0 - 1);                }else if(random == 3){                     changeGrids(row_a0, column_a0 + 1);                }                if(temp_row != row_a0 || tem_column != column_a0){                     i++;                }            }            HiLog.info(TAG,randomstr);            writeData_String("randomstr",randomstr);        } else {             while (true) {                 if (queryContact_String("randomstr") != null && !queryContact_String("randomstr").isEmpty()) {                     break;                }            }            randomstr = queryContact_String("randomstr");            HiLog.info(TAG,"randomstr: "+randomstr);            int random;            int i = 0;            while(i < randomstr.length()) {                 random = randomstr.charAt(i) - 0;                if(random == 0){                     changeGrids(row_a0 - 1, column_a0);                }else if(random == 1){                     changeGrids(row_a0 + 1, column_a0);                }else if(random == 2){                     changeGrids(row_a0, column_a0 - 1);                }else if(random == 3){                     changeGrids(row_a0, column_a0 + 1);                }                i++;            }            singleKvStore.putString("randomstr","");        }        for (int row = 0;row < difficulty; row++) {             for (int column = 0;column <difficulty; column++) {                 grids_b[row][column] = grids_a[row][column];            }        }        row_b0 = row_a0;        column_b0 = column_a0;        HiLog.info(TAG,"row_a0: "+ row_a0 + " column_a0: " + column_a0);    } 

 那接下去就是把数组中的数字给画出来了。

public void drawGrids() {        layout.setLayoutConfig((new ComponentContainer.LayoutConfig(ComponentContainer.LayoutConfig.MATCH_PARENT, ComponentContainer.LayoutConfig.MATCH_PARENT)));       Component.DrawTask task = new Component.DrawTask() {            @Override           public void onDraw(Component component, Canvas canvas) {                Paint paint = new Paint();               Color backcolor = new Color(Color.rgb(151,75,49));               paint.setColor(backcolor);               RectFloat rect = new RectFloat(left - margin, top - margin, length * difficulty + interval * (difficulty - 1) + left + margin, length * difficulty + interval * (difficulty - 1) + top + margin);               canvas.drawRect(rect, paint);               for (int row = 0; row < difficulty; row++) {                    for (int column = 0; column < difficulty; column++) {                        Color backgroundcolor = new Color(Color.rgb(229,188,132));                       paint.setColor(backgroundcolor);                       RectFloat rectFloat = new RectFloat(left + column * (length + interval), top + row * (length + interval), left + length + column * (length + interval), top + length + row * (length + interval));                       canvas.drawRect(rectFloat, paint);                       Color numbercolor = new Color(Color.rgb(140,85,47));                       paint.setColor(numbercolor);                       paint.setTextSize(length / 2);                       if(grids_a[row][column] != 0){                            if(grids_a[row][column] < 10){                                canvas.drawText(paint,Integer.toString(grids_a[row][column]),left + column * (length + interval) + length / 12 * 5,top + row * (length + interval) + length / 3 * 2);                           }else{                                canvas.drawText(paint,Integer.toString(grids_a[row][column]),left + column * (length + interval) + length / 12 * 3,top + row * (length + interval) + length / 3 * 2);                           }                       }                   }               }               paint.setColor(backcolor);               length1 = 600 / difficulty - interval;               RectFloat rect1= new RectFloat(left1 - margin1, top1 - margin1, length1 * difficulty + interval * (difficulty - 1) + left1 + margin1, length1 * difficulty + interval * (difficulty - 1) + top1 + margin1);               canvas.drawRect(rect1, paint);               for (int row = 0; row < difficulty; row++) {                    for (int column = 0; column < difficulty; column++) {                        Color backgroundcolor1 = new Color(Color.rgb(229,188,132));                       paint.setColor(backgroundcolor1);                       RectFloat rectFloat = new RectFloat(left1 + column * (length1 + interval), top1 + row * (length1 + interval), left1 + length1 + column * (length1 + interval), top1 + length1 + row * (length1 + interval));                       canvas.drawRect(rectFloat, paint);                       Color numbercolor1 = new Color(Color.rgb(140,85,47));                       paint.setColor(numbercolor1);                       paint.setTextSize(length1 / 2);                       if(grids_b[row][column] != 0){                            if(grids_b[row][column] < 10){                                canvas.drawText(paint,Integer.toString(grids_b[row][column]),left1 + column * (length1 + interval) + length1 / 12 * 5,top1 + row * (length1 + interval) + length1 / 3 * 2);                           }else{                                canvas.drawText(paint,Integer.toString(grids_b[row][column]),left1 + column * (length1 + interval) + length1 / 12 * 3,top1 + row * (length1 + interval) + length1 / 3 * 2);                           }                       }                   }               }           }       };       layout.addDrawTask(task);       setUIContent(layout);   } 

 接下来就是把我们的时间还有按钮这些给画出来了。

public void draw() {        maxtext = new Text(this);       setMaxtext();       maxtext.setTextSize(80);       maxtext.setMarginTop(40);       maxtext.setMarginLeft(140);       layout.addComponent(maxtext);       timetext = new Text(this);       timetext.setText("time: 00:00:00:00");       timetext.setTextSize(80);       timetext.setMarginTop(10);       timetext.setMarginLeft(230);       layout.addComponent(timetext);       ShapeElement background = new ShapeElement();       background.setRgbColor(new RgbColor(138,70,50));       background.setCornerRadius(100);       Button button_again = new Button(this);       button_again.setText("重新开始");       button_again.setTextAlignment(TextAlignment.CENTER);       button_again.setTextColor(Color.WHITE);       button_again.setTextSize(100);       button_again.setMarginTop(1150);       button_again.setMarginLeft(730);       button_again.setPadding(30, 0, 30, 0);       button_again.setBackground(background);       button_again.setClickedListener(new Component.ClickedListener() {            @Override           public void onClick(Component component) {                getrecord();               writeData_int("restart",1);           }       });       layout.addComponent(button_again);       Button button_back = new Button(this);       button_back.setText("返回");       button_back.setTextAlignment(TextAlignment.CENTER);       button_back.setTextColor(Color.WHITE);       button_back.setTextSize(100);       button_back.setMarginLeft(730);       button_back.setMarginTop(90);       button_back.setPadding(30, 0, 30, 0);       button_back.setBackground(background);       button_back.setClickedListener(new Component.ClickedListener() {            @Override           public void onClick(Component component) {            }       });       layout.addComponent(button_back);       setUIContent(layout);   } 

这就是我们的效果图,你们也可以运行查看一下是否完全一样。保证一样了之后才继续跟着一步一步慢慢走。

我们这已经算是完成了最开始同步的问题了,这算是比较重要的一个问题了,那我们接下来就要继续先完成我们的游戏功能,那在完成游戏功能之前,我们需要先写一个判断游戏是否成功的函数。服务器租用

public boolean gamesuccess() {        int[][] Grids = new int[difficulty][difficulty];       for (int row = 0; row < difficulty; row++){            for (int column = 0; column < difficulty; column++){                Grids[row][column] = difficulty * row + column + 1;           }       }       Grids[difficulty - 1][difficulty - 1] = 0;       for (int row = 0; row < difficulty; row++){            for (int column = 0; column < difficulty; column++){                if(grids_a[row][column] != Grids[row][column]){                    return false;               }           }       }       return true;   } 

 那接下来再写一个判断当前时间是否比最短时间要快的函数,并且写一个将当前时间写到数据库的函数。

public boolean compare() {         int nowtime = hour * 36000 + min * 6000 + sec * 100 + msec;        int maxtime = maxhour * 36000 + maxmin * 6000 + maxsec * 100 + maxmsec;        return nowtime > maxtime;    }    public void Write() {         if (!compare()) {             writeData_int("hour" + difficulty, hour);            writeData_int("min" + difficulty, min);            writeData_int("sec" + difficulty,sec);            writeData_int("msec" + difficulty, msec);        }    } 

 那现在我们就可以来完成的我们的游戏功能了,并且我们要实现出在这一台设备上玩游戏,要将数据写入数据库,让另外一台设备来读取数据,实现数据的同步。

public void swipeGrids(){         layout.setTouchEventListener(new Component.TouchEventListener() {             @Override            public boolean onTouchEvent(Component component, TouchEvent touchEvent) {                 MmiPoint point = touchEvent.getPointerScreenPosition(0);                switch (touchEvent.getAction()) {                     case TouchEvent.PRIMARY_POINT_DOWN:                        startX = point.getX();                        startY = point.getY();                        String str_row = String.valueOf(Math.floor((startY - top - 80) / (length + interval)));                        String str2_column = String.valueOf(Math.floor((startX - left) / (length + interval)));                        if (!gamesuccess()) {                             writeData_int("row" + isLocal ,str_row.charAt(0)-0);                            writeData_int("column" + isLocal ,str2_column.charAt(0)-0);                            changeGrids(str_row.charAt(0)-0, str2_column.charAt(0)-0);                            drawGrids();                            if(gamesuccess()){                                 getrecord();                                setMaxtext();                                HiLog.info(TAG,Integer.toString(maxmsec));                                timer.cancel();                                updatetimer.cancel();                                if (!compare()) {                                     maxhour = hour;                                    maxmin = min;                                    maxsec = sec;                                    maxmsec = msec;                                    Write();                                    setMaxtext();                                    setUIContent(layout);                                }                            }                        }                        break;                }                return true;            }        });    } 

 那数据同步了之后,我们是还没将数据写呈现出来。那我们现在就需要将数组b中的内容给画出来了,那我们就来写另外一个时间线程,来实现这个功能。

public void update() {        updatetimer = new Timer();       updatetimer.schedule(new TimerTask() {            @Override           public void run() {                getUITaskDispatcher().asyncDispatch(() -> {                    drawGrids();               });           }       },0,500);   } 

 那我们还需要在订阅函数中去添加一个数据同步的操作。

if (queryContact_int("row" + !isLocal)!=-1 && queryContact_int("column" + !isLocal)!=-1)            changeGrids_b(queryContact_int("row"+ !isLocal),queryContact_int("column"+ !isLocal)); 

 那我们接下来就去写一个函数让我们的时间开始动起来。

public void runing(){       timer = new Timer();      timer.schedule(new TimerTask() {           @Override          public void run() {               getUITaskDispatcher().asyncDispatch(()->{                   msec++;                  if (msec >= 100){                       sec++;                      msec = msec % 100;                      if (sec >= 60) {                           min++;                          sec = sec % 60;                          if (min >= 60) {                               hour++;                              min = min % 60;                          }                      }                  }                  String strhour = "";                  String strmin = "";                  String strsec = "";                  String strmsec = "";                  if (msec < 10) {                       strmsec = "0" + Integer.toString(msec);                  } else if (msec >= 10) {                       strmsec = Integer.toString(msec);                  }                  if (sec < 10){                       strsec = "0" + Integer.toString(sec);                  } else if (sec >= 10) {                       strsec = Integer.toString(sec);                  }                  if (min < 10){                       strmin = "0" + Integer.toString(min);                  } else if (min >= 10) {                       strmin = Integer.toString(min);                  }                  if (hour < 10){                       strhour = "0" + Integer.toString(hour);                  } else if (hour >= 10) {                       strhour = Integer.toString(hour);                  }                  timetext.setText("time: "+ strhour +":"+strmin+":"+strsec+":"+strmsec);              });          }      },0,10);  } 

 同样的也是需要在订阅函数中实现数据的同步 

if (queryContact_int("hour"+difficulty) != -1)                  maxhour = queryContact_int("hour"+difficulty);              if(queryContact_int("min"+difficulty)!=-1)                  maxmin = queryContact_int("min"+difficulty);              if(queryContact_int("sec"+difficulty)!=-1)                  maxsec = queryContact_int("sec"+difficulty);              if (queryContact_int("msec"+difficulty)!=-1)                  maxmsec = queryContact_int("msec"+difficulty); 

 那这样子我们就已经是完成了游戏功能了,接下去就来做返回按钮的点击事件吧。

timer.cancel();                 updatetimer.cancel();                 terminate(); 

 那接下来我们就来写重新开始的点击事件了。亿华云计算那为了两台设备能同时重新开始,我就在点击重新开始的时候往数据库里面写一个信号,然后还是用一个时间线程来检测这个信号,检测到了,就重新开始游戏。

public void restarting() {        restarttimer = new Timer();       restarttimer.schedule(new TimerTask() {            @Override           public void run() {                getUITaskDispatcher().asyncDispatch(() ->{                    if (restart == 1){                        timer.cancel();                       updatetimer.cancel();                       restart = 0;                       initialize();                       runing();                       update();                   }               });           }       },0,25);   } 

 那到这里我们的游戏也就完成了。我们也可以利用这些分布式能力来创建更多双人小游戏了。

文章相关附件可以点击下面的原文链接前往下载

https://harmonyos.51cto.com/resource/1294

想了解更多内容,请访问:

和华为官方合作共建的鸿蒙技术社区

https://harmonyos.51cto.com

数据库
上一篇:注册域名要了解几大点?新手有什么方式注册域名?
下一篇:评估域名涉及的行业规模与发展状况成正比。