2013年5月17日 星期五

猜數字遊戲關鍵技術紀錄

光要寫一個猜數字遊戲 就花了不少時間try啊!
終於完成並融會貫通全部的函式~有些書上根本不會說
來記錄一下之前思緒的集合吧

關於猜數字遊戲的 玩法
首先建立 100個button 
在建立完後同事 分配一個Thtead計時用
並調用控制項 SHOW出時間!

再利用Randon 亂數取直1~100其中之1
再由共同事件觸發邏輯判斷
Button 名稱是否大於 Random的值
如果大於R值 更改Button.text值為大
如果小於R值                                   小
如果 等於R值SHOW出多少秒?猜幾次? 才猜中

關於猜幾次的函式裡利用深度搜尋控制項目是否
為ebable 如果是 累加Count 計算值
之後需要時 取Count值

在按下BUTTON 瞬間
需同時加入 清除BUTTON函式
用於清除 玩完的BUTTON
好讓程序 重新建立100個BUTTON!

來看程式碼吧 比較好懂

首先 建立  全域的 thread 與 random 存放random值得 int整數型態

        Thread G_th;//定義多執行序物件叫G_th,稍後實體化G_TH物件
        Random G_random = new Random();//宣告 與實體化 亂數物件
        int G_int_num;//定義變數用於存放存機數





再來建立一個Button來讓遊戲開始
而Button處方的事件可多了 CODE如下
計時工作Thread並使用匿名方式 因為只叫用一次

private void btn_begin_Click(object sender, EventArgs e)//按下按鈕後
        {
            RemoveControl();//呼叫副程式,清空所有無用對像,玩完要清除玩過的畫面
            int p_int_x = 10;//X坐標預設值為10
            int p_int_y = 60;//Y坐標預設值為60
            for (int i = 0; i < 100; i++)//新增100個按鈕
            {
                Button bt = new Button();//宣告與實體化button按鈕
                bt.Text = (i + 1).ToString();//設定button按鈕的文字值
                bt.Name = (i + 1).ToString();//設定button按鈕的Name屬性
                bt.Width = 35;//設定button按鈕的寬
                bt.Height = 35;//設定button按鈕的高
                bt.Location = new Point(p_int_x, p_int_y);//設定button按鈕的位置
                bt.Click += new EventHandler(bt_Click);//定義button按鈕的事件
                p_int_x += 36;//設定下一個按鈕的位置,右移36
                if ((i + 1) % 10 == 0)//設定換行10/10=於0換下一行
                {
                    p_int_x = 10;//換行後重新設定X坐標,左移回到10
                    p_int_y += 36;//換行後重新設定Y坐標,下移36
                }
                Controls.Add(bt);//button設定好後放入Controls中
            }
            G_th = new System.Threading.Thread
                //實體化G_TH 並且
                //利用多執行續 來執行委派,這裡委派使用匿名方式
                (delegate()
                {
                    //http://www.dotblogs.com.tw/yc421206/archive/2009/02/16/7206.aspx
                    int P_int_count = 0;//初始化計數器
                    while (true)//開始無限循環
                    {//計數累加1之後做判斷,三元判斷
                        P_int_count = ++P_int_count > 100000000 ? 0 : P_int_count;
                        this.Invoke(//將程式碼交給主線程執行
                            (MethodInvoker)delegate//使用匿名方法
                            {
                                label6.Text += 1;
                                lb_time.Text = //視窗中顯示計數
                                    P_int_count.ToString();
                            }
                            );
                        System.Threading.Thread.Sleep(1000);//線程睡眠1秒
                    }
                }
                );
            G_th.IsBackground = true;//設定線程為後台線程
            G_th.Start();//開始執行線程
            G_int_num = G_random.Next(1, 100);//產生隨機數1~到100
            btn_begin.Enabled = false;//停用開始按鈕
        }



再來是一個 RESET BUTTON的工作 來清楚之前玩過的按鈕
在上面BUTTON中被呼叫的RemoveControl() CODE如下
將會開始搜尋 控制項KEY索引直 在羅技判斷 名子是否為1~100如果是 刪除!
void RemoveControl()
        {
            for (int i = 0; i < 100; i++)//開始深度搜尋100個按鈕
            {
                //如果ContainsKey索引 會搜尋controls中text叫1~100的按鈕
                if (Controls.ContainsKey((i + 1).ToString()))//如果找到k值繼續執行
                {
                    for (int j = 0; j < Controls.Count; j++)//j<控制項的種集合數量;j++
                    {   ////搜尋索引值1~100的text是否有叫1的
                        if (Controls[j].Name ==(i + 1).ToString())
                        {//刪除指定控制向的索引值 RemoveAt(索引值)
                            Controls.RemoveAt(j);//刪除指定按鈕
                            break;//終止j迴圈
                        }
                    }
                }
            }
        }

再來是一個事件觸發的動作
這100個BUTTON中 雖然觸發同一個事件叫bt_Click
但是每一個BUTTON的名子不一樣
然而sender 傳來的是一個Text=1~100的屬性值
利用它來做按了哪一個按鈕做判斷

void bt_Click(object sender, EventArgs e)
        {
            Control P_control = sender as Control;//將sender轉換為control類型對像
            if (int.Parse(P_control.Name) > G_int_num)
            {
                P_control.BackColor = Color.Red;//設定按鈕背景為紅色
                P_control.Enabled = false;//設定按鈕停用
                P_control.Text = "大";//更改按鈕文字
            }
            if (int.Parse(P_control.Name) < G_int_num)
            {
                P_control.BackColor = Color.Red;//設定按鈕背景為紅色
                P_control.Enabled = false;//設定按鈕停用
                P_control.Text = "小";//更改按鈕文字
            }
            if (int.Parse(P_control.Name) == G_int_num)
            {
                G_th.Abort();//終止計數線程
                MessageBox.Show(string.Format(//顯示遊戲訊息
                    "恭喜你猜對了!共猜了{0}次 用時{1}秒",
                    GetCount(), lb_time.Text), "恭喜!");
                btn_begin.Enabled = true;//啟用開始按鈕
            }
        }


再來最後一個則是紀錄 按了幾次的副程式
用於搜尋視窗中Enable屬性為False控制元件的數量
用於計算玩家有多少次沒有猜中
返回沒有猜中數量
CODE如下

string GetCount()
        {
            int P_int_temp = 0;//初始化計數器
            foreach (Control c in Controls)//深度搜尋控制元件集合
            {
                if (!c.Enabled)
                {
                    P_int_temp++;//計數器累加
                }
            }
            return P_int_temp.ToString();//返回計數器訊息
        }




完整程式碼如下

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
namespace NumGame
{
    public partial class Frm_Main : Form
    {
        public Frm_Main()
        {
            InitializeComponent();
        }
        Thread G_th;//定義多執行序物件叫G_th,稍後實體化G_TH物件
        Random G_random = new Random();//宣告 與實體化 亂數物件
        int G_int_num;//定義變數用於存放存機數
        private void btn_begin_Click(object sender, EventArgs e)//按下按鈕後
        {
            RemoveControl();//呼叫副程式,清空所有無用對像,玩完要清除玩過的畫面
            int p_int_x = 10;//X坐標預設值為10
            int p_int_y = 60;//Y坐標預設值為60
            for (int i = 0; i < 100; i++)//新增100個按鈕
            {
                Button bt = new Button();//宣告與實體化button按鈕
                bt.Text = (i + 1).ToString();//設定button按鈕的文字值
                bt.Name = (i + 1).ToString();//設定button按鈕的Name屬性
                bt.Width = 35;//設定button按鈕的寬
                bt.Height = 35;//設定button按鈕的高
                bt.Location = new Point(p_int_x, p_int_y);//設定button按鈕的位置
                bt.Click += new EventHandler(bt_Click);//定義button按鈕的事件
                p_int_x += 36;//設定下一個按鈕的位置,右移36
                if ((i + 1) % 10 == 0)//設定換行10/10=於0換下一行
                {
                    p_int_x = 10;//換行後重新設定X坐標,左移回到10
                    p_int_y += 36;//換行後重新設定Y坐標,下移36
                }
                Controls.Add(bt);//button設定好後放入Controls中
            }
            G_th = new System.Threading.Thread
                //實體化G_TH 並且
                //利用多執行續 來執行委派,這裡委派使用匿名方式
                (delegate()
                {
                    int P_int_count = 0;//初始化計數器
                    while (true)//開始無限循環
                    {//計數累加1之後做判斷,三元判斷
                        P_int_count = ++P_int_count > 100000000 ? 0 : P_int_count;
                        this.Invoke(//將程式碼交給主線程執行
                            (MethodInvoker)delegate//使用匿名方法
                            {
                                label6.Text += 1;
                                lb_time.Text = //視窗中顯示計數
                                    P_int_count.ToString();
                            }
                            );
                        System.Threading.Thread.Sleep(1000);//線程睡眠1秒
                    }
                }
                );
            G_th.IsBackground = true;//設定線程為後台線程
            G_th.Start();//開始執行線程
            G_int_num = G_random.Next(1, 100);//產生隨機數1~到100
            btn_begin.Enabled = false;//停用開始按鈕
        }
        void bt_Click(object sender, EventArgs e)
        {
            Control P_control = sender as Control;//將sender轉換為control類型對像
            if (int.Parse(P_control.Name) > G_int_num)
            {
                P_control.BackColor = Color.Red;//設定按鈕背景為紅色
                P_control.Enabled = false;//設定按鈕停用
                P_control.Text = "大";//更改按鈕文字
            }
            if (int.Parse(P_control.Name) < G_int_num)
            {
                P_control.BackColor = Color.Red;//設定按鈕背景為紅色
                P_control.Enabled = false;//設定按鈕停用
                P_control.Text = "小";//更改按鈕文字
            }
            if (int.Parse(P_control.Name) == G_int_num)
            {
                G_th.Abort();//終止計數線程
                MessageBox.Show(string.Format(//顯示遊戲訊息
                    "恭喜你猜對了!共猜了{0}次 用時{1}秒",
                    GetCount(), lb_time.Text), "恭喜!");
                btn_begin.Enabled = true;//啟用開始按鈕
            }
        }
        /// <summary>
        /// 用於搜尋視窗中Enable屬性為False控制元件的數量
        /// 用於計算玩家有多少次沒有猜中
        /// </summary>
        /// <returns>返回沒有猜中數量</returns>
        string GetCount()
        {
            int P_int_temp = 0;//初始化計數器
            foreach (Control c in Controls)//深度搜尋控制元件集合
            {
                if (!c.Enabled)
                {
                    P_int_temp++;//計數器累加
                }
            }
            return P_int_temp.ToString();//返回計數器訊息
        }
        /// <summary>
        /// 用於清空視窗中動態產生的按鈕
        /// </summary>
        void RemoveControl()
        {
            for (int i = 0; i < 100; i++)//開始深度搜尋100個按鈕
            {
                //如果ContainsKey索引 會搜尋controls中text叫1~100的按鈕
                if (Controls.ContainsKey((i + 1).ToString()))//如果找到k值繼續執行
                {
                    for (int j = 0; j < Controls.Count; j++)//j<控制項的種集合數量;j++
                    {   ////搜尋索引值1~100的text是否有叫1的
                        if (Controls[j].Name ==(i + 1).ToString())
                        {//刪除指定控制向的索引值 RemoveAt(索引值)
                            Controls.RemoveAt(j);//刪除指定按鈕
                            break;//終止j迴圈
                        }
                    }
                }
            }
        }
        private void Frm_Main_FormClosing(object sender, FormClosingEventArgs e)
        {
            Environment.Exit(0);//強行關閉視窗
        }
    }
}

沒有留言:

張貼留言