日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

算法仿真----分治法找假币

發布時間:2023/12/18 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 算法仿真----分治法找假币 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

分治法找假幣

  • 介紹
  • 控制臺程序
    • 代碼結構
      • 成員類Coin
      • Main函數
      • CreateCoinArray函數
      • SearchCoin函數
      • Sum函數
      • RemoveData函數
  • Unity仿真
    • 實現思路
    • UI結構
      • InputPanel
      • CoinPanel
    • 腳本
      • Coin.cs
      • SCoinBasePanel.cs
      • SCoinInputPanel.cs
      • SCoinCoinPanel.cs
      • SearchCoinCanvasCtrl.cs
    • 演示圖片
      • 輸入面板
      • 初始面板和查找過程演示

介紹

有一堆金幣,其中有一個假幣。編寫程序在其中找到假幣。
根據題目先寫出控制臺程序實現的找假幣。之后在考慮使用unity做可視化仿真。

控制臺程序

這一個題目使用分治法來解。

代碼結構

成員類Coin

Main函數

獲取用戶輸入的數組大小,調用函數生成硬幣數組,調用函數查找假幣,輸出找到的假幣的下標。

static void Main(string[] args){//聲明一個List數組List<Coin> coins = new List<Coin>();Console.WriteLine("請輸入硬幣數組大小");var size = int.Parse(Console.ReadLine());//創建一個硬幣數組CreateCoinArray(size,out coins);//輸出找到的假幣序號Console.WriteLine("找到的假幣下標為:" + SearchCoin(coins));}

CreateCoinArray函數

這個函數內容簡單,就是創建一個硬幣類的List數組

static void CreateCoinArray(int nums, out List<Coin> coins) {//返回的數組List<Coin> cs = new List<Coin>();//生成一個隨機數作為假幣的序號Random random = new Random();var CounterfeitCoinId = random.Next(0, nums - 1);//生成硬幣幣數組for (int i = 0; i < nums; i++) {if (i == CounterfeitCoinId) {Coin c = new Coin(1, i);cs.Add(c);continue;}cs.Add(new Coin(2, i));}//賦值傳回coins = cs;//輸出假幣id,與找到的假幣id做對比Console.WriteLine("初始定義的假幣下標:" + CounterfeitCoinId);}

SearchCoin函數

這是該程序的核心函數,自己設定一個5枚硬幣數組按照分治的思想一步步寫。不糾結if判斷,到對應數目的情況時再考慮對應的if判斷。

static int SearchCoin(List<Coin> coins) {//參數定義int delta, len;len = coins.Count;//數組等于1,基本已經找到if (coins.Count == 1) {if (coins[0].weight == 1) return coins[0].index;else return -1;}//如果數組元素的數目不是偶數的情況if (coins.Count % 2 != 0) {//比較末尾兩枚硬幣的重量,這里設定的是假幣比真幣輕delta = coins[len - 2].weight - coins[len - 1].weight;//根據情況進行不同的操作if (delta > 0){return coins[len - 1].index;}else if (delta < 0){return coins[len - 2].index;} else {coins.RemoveAt(len - 1);//移除最后一位len = coins.Count;}}//經過上一個if的處理后,到達這里的必是偶數數量的數組//對兩邊的元素求和做差對重的一方進行裁剪,之后遞歸調用delta = Sum(coins, 0, (len / 2) - 1) - Sum(coins, len / 2, len - 1);if (delta > 0){RemoveData(coins, 0, (len / 2) - 1);} else RemoveData(coins, len / 2, len - 1);return SearchCoin(coins);}

Sum函數

一個簡單的求和函數。

static int Sum(List<Coin> coins,int s,int e) {var sum = 0;for (int i = s; i <= e; i++) {sum += coins[i].weight;}return sum;}

RemoveData函數

裁剪數組的函數。由于List數組刪除元素后會自動擠掉對應的位置。
這里只需要每次刪除固定位置的元素并循環需要次數就夠了。

static void RemoveData(List<Coin> coins, int s, int e) {for (int i = s; i <= e; i++) {coins.RemoveAt(s);}}

Unity仿真

實現思路

首先確定輸入。我需要獲得
金幣數組的尺寸,
假幣是比真幣重還是輕
再是如何演示步驟。這個實現過程由于最初的思路問題走了不少彎路,這里就不贅述。講講最后成功的實現方式。
設置一個數組,每當執行刪除操作或者找到結果時用字符串將需要刪除的金幣序號保存為字符串存儲在數組中。
之后根據數組來一步步的刪除對應金幣,這就實現了找假幣的過程演示。

UI結構

InputPanel

獲取用戶的輸入。
一個標題、一個輸入框、一個提示按鈕、一個開始按鈕、兩個Toggle

InputPanel

WeightSelectTG


兩個Toggle

CoinPanel

主要是使用GridLayoutGroup組件實現金幣的有序排布。
對Content里添加生成的金幣初始化金幣,刪除金幣演示步驟。

成員

CoinPanel

Content

腳本

一共五個腳本,實現主要功能的是SCoinCoinPanel腳本。
這里對Panel類型和假幣重量設置了兩個枚舉。
Panel類型的枚舉作為索引值,Panel面板的canvasGroup作為組件。兩者成為一個字典的元素。
Toggle變換當前假幣重量的枚舉類型。

Coin.cs

using UnityEngine;public class Coin : MonoBehaviour {//硬幣的重量internal int weight;//硬幣在數組中的序號internal int index;public UnityEngine.UI.Text IndexText;public void Init(int w, int id) {weight = w;index = id;IndexText.text = index.ToString();} }

SCoinBasePanel.cs

using UnityEngine;public class SCoinBasePanel : MonoBehaviour {public SearchCoinCanvasCtrl.PanelType Type;//當前Panel的類型protected CanvasGroup myCanvasGroup;//當前panel的CanvasGroup組件protected void Awake(){//獲取自身的Canvas組件if (myCanvasGroup == null) {myCanvasGroup = this.GetComponent<CanvasGroup>();}}public void Start(){//初始化SearchCoinCanvasCtrl里的字典,并將自身注冊到字典里去SearchCoinCanvasCtrl.Instance.InitSCoinPanels();SearchCoinCanvasCtrl.Instance.SCoinPanels.Add(Type, this.GetComponent<CanvasGroup>());} }

SCoinInputPanel.cs

using UnityEngine; using UnityEngine.UI;public class SCoinInputPanel : SCoinBasePanel {//輸入組件public InputField input;//提示輸入正確與否的圖片public Image debugimg;//檢查輸入,合法則開始找假幣算法的步驟演示public void OnConfirmBD(){if (input.text == ""){debugimg.color = Color.yellow;return;}var GoldNum = int.Parse(input.text);if (GoldNum < 2 || GoldNum > 42){debugimg.color = Color.red;//audioSource.PlayOneShot(errorSound);return;}debugimg.color = Color.green;//隱藏自身myCanvasGroup.alpha = 0;myCanvasGroup.blocksRaycasts = false;CanvasGroup CoinPanel;SearchCoinCanvasCtrl.Instance.SCoinPanels.TryGetValue(SearchCoinCanvasCtrl.PanelType.CoinPanel, out CoinPanel);//顯示CoinPanelCoinPanel.alpha = 1;CoinPanel.blocksRaycasts = true;//生成金幣SCoinCoinPanel.Instance.CreateCoins(GoldNum);print("csnum:" + SCoinCoinPanel.Instance.Coins.Count);//查找假幣var cs = SCoinCoinPanel.Instance.Coins;SCoinCoinPanel.Instance.SearchCoin(cs);//調用協程函數演示過程StartCoroutine(SCoinCoinPanel.Instance.StepByStep());}//變換假幣的重量條件,Toggle的綁定事件public void SwitchWeightType(){SearchCoinCanvasCtrl.Instance.weightType = (SearchCoinCanvasCtrl.Instance.weightType == CoinWeightType.heavy) ? CoinWeightType.light : CoinWeightType.heavy;} }

SCoinCoinPanel.cs

using System.Collections; using System.Collections.Generic; using UnityEngine;public class SCoinCoinPanel : SCoinBasePanel {public Transform Cotent;//生成金幣的父物體public GameObject CoinPre;//金幣預制體internal List<Coin> Coins = new List<Coin>();//金幣數組,這個有點多余,一開始寫的,到后面就感覺用處不大了/// <summary>/// 存放硬幣序號與對應游戲體的字典/// </summary>internal Dictionary<int, GameObject> CoinGODic = new Dictionary<int, GameObject>();bool GoAhead = false;//前進bool變量List<string> RemoveList = new List<string>();//存儲刪除金幣序號的字符串數組public static SCoinCoinPanel Instance;//單例模式變量public GameObject RestartBt;//重新開始按鈕private void Awake(){//繼承使用父類的Awake方法base.Awake();//單例賦值if (Instance == null)Instance = this;}private void Start(){//繼承使用父類的Atart方法base.Start();//如果自己的Type是CoinPanel,將自己的透明度設為0,遮罩設falseif (Type == SearchCoinCanvasCtrl.PanelType.CoinPanel){myCanvasGroup.alpha = 0;myCanvasGroup.blocksRaycasts = false;}//初始不顯示重新開始按鈕RestartBt.SetActive(false);}/// <summary>/// 變換前進bool變量的值達到動態演示刪除步驟的效果/// </summary>public void GoAheadBD() {if (!GoAhead) GoAhead = true;}internal int deltaFactor = 1;//因為假幣的重量不定,需要一個差值因數乘以算法//里重量做差的值,使算法能同時處理兩種類型的問題internal int CounterfeitCoinW = 3;//假幣重量,默認為3/// <summary>/// 初始生成金幣/// </summary>/// <param name="size"></param>internal void CreateCoins(int size){//差值因數賦值,根據用戶選擇的假幣類型(比真幣重或輕)deltaFactor = (SearchCoinCanvasCtrl.Instance.weightType == CoinWeightType.heavy)? -1 : 1;//獲取假幣的輕重int CounterfeitCoinW = (SearchCoinCanvasCtrl.Instance.weightType == CoinWeightType.heavy)? 3 : 1;//隨機一個序號為假幣int CounterfeitCoinId = Random.Range(0, size - 1);//生成金幣for (int i = 0; i < size; i++){//實例化var c = Instantiate(CoinPre, Cotent);var CoinClass = c.GetComponent<Coin>();//假幣的情況if (i == CounterfeitCoinId){//初始化Coin腳本里的參數CoinClass.Init(CounterfeitCoinW, i);//金幣設置黑色作為區分c.GetComponent<UnityEngine.UI.Image>().color = Color.black;}else{//初始化Coin腳本里的參數CoinClass.Init(2, i);}//注冊Coins.Add(CoinClass);//注冊腳本CoinGODic.Add(i, c);//注冊游戲體}}//找假幣函數public int SearchCoin(List<Coin> coins){int delta, len;len = coins.Count;if (coins.Count == 1){if (coins[0].weight == CounterfeitCoinW)return coins[0].index;elsereturn -1;}if (coins.Count % 2 != 0 && coins.Count != 1){delta = coins[len - 2].weight - coins[len - 1].weight;if (delta * deltaFactor > 0){//獲取idint id = coins[len - 1].index;//移除自身coins.RemoveAt(len - 1);//添加進刪除數組AddRemoveList(coins);return id;}else if (delta * deltaFactor < 0){//獲取idint id = coins[len - 2].index;//移除自身coins.RemoveAt(len - 2);//添加進刪除數組AddRemoveList(coins);return id;}else{//獲取idstring id = coins[len - 1].index.ToString();//移除自身coins.RemoveAt(len - 1);//添加進刪除數組RemoveList.Add(id);len = coins.Count;}}//求兩邊的和值差delta = Sum(coins, 0, (len / 2) - 1) - Sum(coins, len / 2, len - 1);if (delta * deltaFactor > 0){RemoveData(coins, 0, (len / 2) - 1);}else RemoveData(coins, len / 2, len - 1);return SearchCoin(coins);}//求和函數int Sum(List<Coin> coins, int s, int e){var sum = 0;for (int i = s; i <= e; i++){sum += coins[i].weight;}return sum;}//移除數組元素函數void RemoveData(List<Coin> coins, int s, int e){ string removeStr = "";for (int i = s; i <= e; i++){if (i == s){print("in");removeStr = coins[s].index.ToString();}elseremoveStr += "," + coins[s].index.ToString();//刪除算法中的存儲信息coins.RemoveAt(s);}RemoveList.Add(removeStr);}//奇數情況下,假幣在末尾兩個之一時調用,將假幣之外的所有金幣移除public void AddRemoveList(List<Coin> coins) {print("inre");string str = "";int i = 1;foreach (var c1 in coins) {if (i == 1)str = c1.index.ToString();else {str += "," + c1.index.ToString();}i++;}RemoveList.Add(str);}//實現用戶控制步驟演示的函數public IEnumerator StepByStep() { foreach (var rstr in RemoveList) {yield return new WaitUntil(() => GoAhead == true);//解字符串var indexs = rstr.Split(',');foreach (var id in indexs) {yield return new WaitForSeconds(0.5f);//刪除字典中對應金幣id的游戲體Destroy(GetValue<int, GameObject>(CoinGODic, int.Parse(id)));}GoAhead = false;}//演示過程結束后才能重新開始RestartBt.SetActive(true);}//重新開始函數public void Restart() {//清空數據foreach (var g in CoinGODic)Destroy(g.Value);RemoveList.Clear();Coins.Clear();CoinGODic.Clear();//隱藏自身myCanvasGroup.alpha = 0;myCanvasGroup.blocksRaycasts = false;CanvasGroup InputPanel;SearchCoinCanvasCtrl.Instance.SCoinPanels.TryGetValue(SearchCoinCanvasCtrl.PanelType.InputPanel, out InputPanel);//顯示CoinPanelInputPanel.alpha = 1;InputPanel.blocksRaycasts = true;}//獲取字典value值的封裝函數,不在需要out。public T2 GetValue<T1, T2>(Dictionary<T1, T2> dic, T1 key){T2 value;dic.TryGetValue(key, out value);return value;} }

SearchCoinCanvasCtrl.cs

using System.Collections; using System.Collections.Generic; using UnityEngine; public enum CoinWeightType {light, heavy }public class SearchCoinCanvasCtrl : MonoBehaviour {public enum PanelType {InputPanel,CoinPanel,TipPanel}public GameObject TipPanel;//提示面板/// <summary>/// 假幣是比真幣重還是輕。默認是重/// </summary>internal CoinWeightType weightType = CoinWeightType.heavy;public static SearchCoinCanvasCtrl Instance;//單例變量internal Dictionary<PanelType, CanvasGroup> SCoinPanels;//各個面板的注冊字典private void Awake(){//初始化if (Instance == null)Instance = this;}//初始化字典public void InitSCoinPanels() {if (Instance.SCoinPanels == null) {Instance.SCoinPanels = new Dictionary<PanelType, CanvasGroup>();}}//提示按鈕的響應函數public void ShowTip() {StartCoroutine(ShowTip(0.5f));}public IEnumerator ShowTip(float time) {TipPanel.SetActive(true);yield return new WaitForSeconds(time);TipPanel.SetActive(false);} }

演示圖片

輸入面板

初始面板和查找過程演示





總結

以上是生活随笔為你收集整理的算法仿真----分治法找假币的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。