程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> C++完成簡略的掃雷游戲(掌握台版)

C++完成簡略的掃雷游戲(掌握台版)

編輯:關於C++

C++完成簡略的掃雷游戲(掌握台版)。本站提示廣大學習愛好者:(C++完成簡略的掃雷游戲(掌握台版))文章只能為提供參考,不一定能成為您想要的結果。以下是C++完成簡略的掃雷游戲(掌握台版)正文


在本篇文章中給出了三種完成日間/夜間形式切換的計劃,三種計劃綜合起來能夠招致文章的篇幅太長,請耐煩浏覽。

    1、應用 setTheme 的辦法讓 Activity 從新設置主題;

    2、設置 Android Support Library 中的 UiMode 來支撐日間/夜間形式的切換;

    3、經由過程資本 id 映照,回調自界說 ThemeChangeListener 接口來處置日間/夜間形式的切換。

1、應用 setTheme 辦法

我們先來看看應用 setTheme 辦法來完成日間/夜間形式切換的計劃。這類計劃的思緒很簡略,就是在用戶選擇夜間形式時,Activity 設置成夜間形式的主題,以後再讓 Activity 挪用 recreate() 辦法從新創立一遍就好了。

那就著手吧,在 colors.xml 中界說兩組色彩,分離表現日間和夜間的主題色:

<?xml version="1.0" encoding="utf-8"?>
<resources>
 <color name="colorPrimary">#3F51B5</color>
 <color name="colorPrimaryDark">#303F9F</color>
 <color name="colorAccent">#FF4081</color>

 <color name="nightColorPrimary">#3b3b3b</color>
 <color name="nightColorPrimaryDark">#383838</color>
 <color name="nightColorAccent">#a72b55</color>
</resources>

以後在 styles.xml 中界說兩組主題,也就是日間主題和夜間主題:

<resources>

 <!-- Base application theme. -->
 <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
  <!-- Customize your theme here. -->
  <item name="colorPrimary">@color/colorPrimary</item>
  <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
  <item name="colorAccent">@color/colorAccent</item>
  <item name="android:textColor">@android:color/black</item>
  <item name="mainBackground">@android:color/white</item>
 </style>

 <style name="NightAppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
  <!-- Customize your theme here. -->
  <item name="colorPrimary">@color/nightColorPrimary</item>
  <item name="colorPrimaryDark">@color/nightColorPrimaryDark</item>
  <item name="colorAccent">@color/nightColorAccent</item>
  <item name="android:textColor">@android:color/white</item>
  <item name="mainBackground">@color/nightColorPrimaryDark</item>
 </style>

</resources>

在主題中的 mainBackground 屬性是我們自界說的屬性,用來表現配景色:

<?xml version="1.0" encoding="utf-8"?>
<resources>
 <attr name="mainBackground" format="color|reference"></attr>
</resources>

接上去就是看一下結構 activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:tools="http://schemas.android.com/tools"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:background="?attr/mainBackground"
 android:paddingBottom="@dimen/activity_vertical_margin"
 android:paddingLeft="@dimen/activity_horizontal_margin"
 android:paddingRight="@dimen/activity_horizontal_margin"
 android:paddingTop="@dimen/activity_vertical_margin"
 tools:context="com.yuqirong.themedemo.MainActivity">

 <Button
  android:id="@+id/btn_theme"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:text="切換日/夜間形式" />

 <TextView
  android:id="@+id/tv"
  android:layout_below="@id/btn_theme"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:gravity="center_horizontal"
  android:text="經由過程setTheme()的辦法" />

</RelativeLayout>

在 <RelativeLayout> 的 android:background 屬性中,我們應用 "?attr/mainBackground" 來表現,如許就代表著 RelativeLayout 的配景色會去援用在主題中事前界說好的 mainBackground 屬性的值。如許就完成了日間/夜間形式切換的換色了。

最初就是 MainActivity 的代碼:

public class MainActivity extends AppCompatActivity {

 // 默許是日間形式
 private int theme = R.style.AppTheme;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
 // 斷定能否有主題存儲
  if(savedInstanceState != null){
   theme = savedInstanceState.getInt("theme");
   setTheme(theme);
  }
  setContentView(R.layout.activity_main);

  Button btn_theme = (Button) findViewById(R.id.btn_theme);
  btn_theme.setOnClickListener(new View.OnClickListener() {
   @Override
   public void onClick(View v) {
    theme = (theme == R.style.AppTheme) ? R.style.NightAppTheme : R.style.AppTheme;
    MainActivity.this.recreate();
   }
  });
 }

 @Override
 protected void onSaveInstanceState(Bundle outState) {
  super.onSaveInstanceState(outState);
  outState.putInt("theme", theme);
 }

 @Override
 protected void onRestoreInstanceState(Bundle savedInstanceState) {
  super.onRestoreInstanceState(savedInstanceState);
  theme = savedInstanceState.getInt("theme");
 }
}

MainActivity 中有幾點要留意一下:

     1、挪用 recreate() 辦法後 Activity 的性命周期會挪用 onSaveInstanceState(Bundle outState) 來備份相干的數據,以後也會挪用 onRestoreInstanceState(Bundle savedInstanceState) 來復原相干的數據,是以我們把 theme 的值保留出來,以便 Activity 從新創立後應用。

     2、我們在 onCreate(Bundle savedInstanceState) 辦法中復原獲得了 theme 值後,setTheme() 辦法必定要在 setContentView() 辦法之前挪用,不然的話就看不到後果了。

     3、recreate() 辦法是在 API 11 中添加出去的,所以在 Android 2.X 中應用會拋異常。

貼完下面的代碼以後,我們來看一下該計劃完成的後果圖:

2、應用 Android Support Library 中的 UiMode 辦法

應用 UiMode 的辦法也很簡略,我們須要把 colors.xml 界說為日間/夜間兩種。以後依據分歧的形式會去選擇分歧的 colors.xml 。在 Activity 挪用 recreate() 以後,就完成了切換日/夜間形式的功效。

說了這麼多,直接上代碼。上面是 values/colors.xml :

<?xml version="1.0" encoding="utf-8"?>
<resources>
 <color name="colorPrimary">#3F51B5</color>
 <color name="colorPrimaryDark">#303F9F</color>
 <color name="colorAccent">#FF4081</color>
 <color name="textColor">#FF000000</color>
 <color name="backgroundColor">#FFFFFF</color>
</resources>

除 values/colors.xml 以外,我們還要創立一個 values-night/colors.xml 文件,用來設置夜間形式的色彩,個中 <color> 的 name 必需要和 values/colors.xml 中的絕對應:

<?xml version="1.0" encoding="utf-8"?>
<resources>
 <color name="colorPrimary">#3b3b3b</color>
 <color name="colorPrimaryDark">#383838</color>
 <color name="colorAccent">#a72b55</color>
 <color name="textColor">#FFFFFF</color>
 <color name="backgroundColor">#3b3b3b</color>
</resources>

在 styles.xml 中去援用我們在 colors.xml 中界說好的色彩:

<resources>

 <!-- Base application theme. -->
 <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
  <!-- Customize your theme here. -->
  <item name="colorPrimary">@color/colorPrimary</item>
  <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
  <item name="colorAccent">@color/colorAccent</item>
  <item name="android:textColor">@color/textColor</item>
  <item name="mainBackground">@color/backgroundColor</item>
 </style>

</resources>

activity_main.xml 結構的內容和下面 setTheme() 辦法中的相差無幾,這裡就不貼出來了。以後的工作就變得很簡略了,在 MyApplication 中先選擇一個默許的 Mode :

public class MyApplication extends Application {

 @Override
 public void onCreate() {
  super.onCreate();
  // 默許設置為日間形式
  AppCompatDelegate.setDefaultNightMode(
    AppCompatDelegate.MODE_NIGHT_NO);
 }

}

要留意的是,這裡的 Mode 有四品種型可以選擇:

    1、MODE_NIGHT_NO: 應用亮色(light)主題,不應用夜間形式;

    2、MODE_NIGHT_YES:應用暗色(dark)主題,應用夜間形式;

    3、MODE_NIGHT_AUTO:依據以後時光主動切換 亮色(light)/暗色(dark)主題;

    4、MODE_NIGHT_FOLLOW_SYSTEM(默許選項):設置為追隨體系,平日為 MODE_NIGHT_NO

當用戶點擊按鈕切換日/夜間時,從新去設置響應的 Mode :

public class MainActivity extends AppCompatActivity {

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);

  Button btn_theme = (Button) findViewById(R.id.btn_theme);
  btn_theme.setOnClickListener(new View.OnClickListener() {
   @Override
   public void onClick(View v) {
    int currentNightMode = getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
    getDelegate().setLocalNightMode(currentNightMode == Configuration.UI_MODE_NIGHT_NO
      ? AppCompatDelegate.MODE_NIGHT_YES : AppCompatDelegate.MODE_NIGHT_NO);
    // 異樣須要挪用recreate辦法使之失效
    recreate();
   }
  });
 }

}

我們來看一下 UiMode 計劃完成的後果圖:

就前兩種辦法而言,設置裝備擺設比擬簡略,最初的完成後果也都根本上是一樣的。然則缺陷就是須要挪用 recreate() 使之失效。而讓 Activity 從新創立就必需觸及到一些狀況的保留。這就增長了一些難度。所以,我們一路來看看第三種處理辦法。

經由過程資本 id 映照,回調接口

第三種辦法的思緒就是依據設置的主題去靜態地獲得資本 id 的映照,然後應用回調接口的方法讓 UI 去設置相干的屬性值。我們在這裡先劃定一下:夜間形式的資本在定名上都要加上後綴 “_night” ,好比日間形式的配景色定名為 color_background ,那末絕對應的夜間形式的配景資本就要定名為 color_background_night 。好了,上面就是我們的 Demo 所須要用到的 colors.xml :

<?xml version="1.0" encoding="utf-8"?>
<resources>
 
 <color name="colorPrimary">#3F51B5</color>
 <color name="colorPrimary_night">#3b3b3b</color>
 <color name="colorPrimaryDark">#303F9F</color>
 <color name="colorPrimaryDark_night">#383838</color>
 <color name="colorAccent">#FF4081</color>
 <color name="colorAccent_night">#a72b55</color>
 <color name="textColor">#FF000000</color>
 <color name="textColor_night">#FFFFFF</color>
 <color name="backgroundColor">#FFFFFF</color>
 <color name="backgroundColor_night">#3b3b3b</color>
 
</resources>

可以看到每項 color 都邑有對應的 “_night” 與之婚配。

看到這裡,確定有人會問,為何要設置對應的 “_night” ?究竟是經由過程甚麼方法來設置日/夜間形式的呢?上面就由 ThemeManager 來為你解答:

public class ThemeManager {

 // 默許是日間形式
 private static ThemeMode mThemeMode = ThemeMode.DAY;
 // 主題形式監聽器
 private static List<OnThemeChangeListener> mThemeChangeListenerList = new LinkedList<>();
 // 夜間資本的緩存,key : 資本類型, 值<key:資本稱號, value:int值>
 private static HashMap<String, HashMap<String, Integer>> sCachedNightResrouces = new HashMap<>();
 // 夜間形式資本的後綴,好比日件形式資本名為:R.color.activity_bg, 那末夜間形式就為 :R.color.activity_bg_night
 private static final String RESOURCE_SUFFIX = "_night";

 /**
  * 主題形式,分為日間形式和夜間形式
  */
 public enum ThemeMode {
  DAY, NIGHT
 }

 /**
  * 設置主題形式
  *
  * @param themeMode
  */
 public static void setThemeMode(ThemeMode themeMode) {
  if (mThemeMode != themeMode) {
   mThemeMode = themeMode;
   if (mThemeChangeListenerList.size() > 0) {
    for (OnThemeChangeListener listener : mThemeChangeListenerList) {
     listener.onThemeChanged();
    }
   }
  }
 }

 /**
  * 依據傳入的日間形式的resId獲得響應主題的resId,留意:必需是日間形式的resId
  *
  * @param dayResId 日間形式的resId
  * @return 響應主題的resId,若為日間形式,則獲得dayResId;反之夜間形式獲得nightResId
  */
 public static int getCurrentThemeRes(Context context, int dayResId) {
  if (getThemeMode() == ThemeMode.DAY) {
   return dayResId;
  }
  // 資本名
  String entryName = context.getResources().getResourceEntryName(dayResId);
  // 資本類型
  String typeName = context.getResources().getResourceTypeName(dayResId);
  HashMap<String, Integer> cachedRes = sCachedNightResrouces.get(typeName);
  // 先從緩存中去取,假如有直接前往該id
  if (cachedRes == null) {
   cachedRes = new HashMap<>();
  }
  Integer resId = cachedRes.get(entryName + RESOURCE_SUFFIX);
  if (resId != null && resId != 0) {
   return resId;
  } else {
   //假如緩存中沒有再依據資本id去靜態獲得
   try {
    // 經由過程資本名,資本類型,包名獲得資本int值
    int nightResId = context.getResources().getIdentifier(entryName + RESOURCE_SUFFIX, typeName, context.getPackageName());
    // 放入緩存中
    cachedRes.put(entryName + RESOURCE_SUFFIX, nightResId);
    sCachedNightResrouces.put(typeName, cachedRes);
    return nightResId;
   } catch (Resources.NotFoundException e) {
    e.printStackTrace();
   }
  }
  return 0;
 }

 /**
  * 注冊ThemeChangeListener
  *
  * @param listener
  */
 public static void registerThemeChangeListener(OnThemeChangeListener listener) {
  if (!mThemeChangeListenerList.contains(listener)) {
   mThemeChangeListenerList.add(listener);
  }
 }

 /**
  * 反注冊ThemeChangeListener
  *
  * @param listener
  */
 public static void unregisterThemeChangeListener(OnThemeChangeListener listener) {
  if (mThemeChangeListenerList.contains(listener)) {
   mThemeChangeListenerList.remove(listener);
  }
 }

 /**
  * 獲得主題形式
  *
  * @return
  */
 public static ThemeMode getThemeMode() {
  return mThemeMode;
 }

 /**
  * 主題形式切換監聽器
  */
 public interface OnThemeChangeListener {
  /**
   * 主題切換時回調
   */
  void onThemeChanged();
 }
}

下面 ThemeManager 的代碼根本上都有正文,想要看懂其實不艱苦。個中最焦點的就是 getCurrentThemeRes 辦法了。在這裡說明一下 getCurrentThemeRes 的邏輯。參數中的 dayResId 是日間形式的資本id,假如以後主題是日間形式的話,就直接前往 dayResId 。反之以後主題為夜間形式的話,先依據 dayResId 獲得資本稱號和資本類型。好比如今有一個資本為 R.color.colorPrimary ,那末資本稱號就是 colorPrimary ,資本類型就是 color 。然後依據資本類型和資本稱號去獲得緩存。假如沒有緩存,那末就要靜態獲得資本了。這裡應用辦法的是

context.getResources().getIdentifier(String name, String defType, String defPackage)

name 參數就是資本稱號,不外要留意的是這裡的資本稱號還要加上後綴 “_night” ,也就是下面在 colors.xml 中界說的稱號;
defType 參數就是資本的類型了。好比 color,drawable等;

defPackage 就是資本文件的包名,也就是以後 APP 的包名。

有了下面的這個辦法,便可以經由過程 R.color.colorPrimary 資本找到對應的 R.color.colorPrimary_night 資本了。最初還要把找到的夜間形式資本參加到緩存中。如許的話今後就直接去緩存中讀取,而不消再次去靜態查找資本 id 了。

ThemeManager 中剩下的代碼應當都是比擬簡略的,信任年夜家都可以看得懂了。

如今我們來看看 MainActivity 的代碼:

public class MainActivity extends AppCompatActivity implements ThemeManager.OnThemeChangeListener {

 private TextView tv;
 private Button btn_theme;
 private RelativeLayout relativeLayout;
 private ActionBar supportActionBar;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  ThemeManager.registerThemeChangeListener(this);
  supportActionBar = getSupportActionBar();
  btn_theme = (Button) findViewById(R.id.btn_theme);
  relativeLayout = (RelativeLayout) findViewById(R.id.relativeLayout);
  tv = (TextView) findViewById(R.id.tv);
  btn_theme.setOnClickListener(new View.OnClickListener() {
   @Override
   public void onClick(View v) {
    ThemeManager.setThemeMode(ThemeManager.getThemeMode() == ThemeManager.ThemeMode.DAY
      ? ThemeManager.ThemeMode.NIGHT : ThemeManager.ThemeMode.DAY);
   }
  });
 }

 public void initTheme() {
  tv.setTextColor(getResources().getColor(ThemeManager.getCurrentThemeRes(MainActivity.this, R.color.textColor)));
  btn_theme.setTextColor(getResources().getColor(ThemeManager.getCurrentThemeRes(MainActivity.this, R.color.textColor)));
  relativeLayout.setBackgroundColor(getResources().getColor(ThemeManager.getCurrentThemeRes(MainActivity.this, R.color.backgroundColor)));
  // 設置題目欄色彩
  if(supportActionBar != null){
   supportActionBar.setBackgroundDrawable(new ColorDrawable(getResources().getColor(ThemeManager.getCurrentThemeRes(MainActivity.this, R.color.colorPrimary))));
  }
  // 設置狀況欄色彩
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
   Window window = getWindow();
   window.setStatusBarColor(getResources().getColor(ThemeManager.getCurrentThemeRes(MainActivity.this, R.color.colorPrimary)));
  }
 }

 @Override
 public void onThemeChanged() {
  initTheme();
 }

 @Override
 protected void onDestroy() {
  super.onDestroy();
  ThemeManager.unregisterThemeChangeListener(this);
 }

}

在 MainActivity 中完成了 OnThemeChangeListener 接口,如許便可以在主題轉變的時刻履行回調辦法。然後在 initTheme() 中去從新設置 UI 的相干色彩屬性值。還有別忘了要在 onDestroy() 中移除 ThemeChangeListener 。

最初就來看看第三種辦法的後果吧:

或許有人會說和前兩種辦法的後果沒甚麼差別啊,然則細心看就會發明後面兩種辦法在切換形式的剎時會有長久黑屏景象存在,而第三種辦法沒有。這是由於前兩種辦法都要挪用 recreate() 。而第三種辦法不須要 Activity 從新創立,應用回調的辦法來完成。

三個辦法比較

到了這裡,依照套路應當是要總結的時刻了。那末就依據下面給的三種辦法來一個簡略的比較吧:

setTheme 辦法:可以設置裝備擺設多套主題,比擬輕易上手。除日/夜間形式以外,還可以有其他五彩缤紛的主題。然則須要挪用 recreate() ,切換剎時會有黑屏閃現的景象;

UiMode 辦法:長處就是 Android Support Library 中曾經支撐,簡略標准。然則也須要挪用 recreate() ,存在黑屏閃現的景象;

靜態獲得資本 id ,回調接口:該辦法應用起來比前兩個辦法龐雜,別的在回調的辦法中須要設置每項 UI 相干的屬性值。然則不須要挪用 recreate() ,沒有黑屏閃現的景象。

總結

以上就是這篇文章的全體內容了,願望能對列位Android開辟者們有所贊助。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved