프로젝트/C# Wafer 코팅 시뮬

2. Wafer 예광탄 [Wafer 코팅 시뮬레이션]

언휴 2024. 1. 10. 15:00

유튜브 동영상 강의

안녕하세요. 언제나 휴일입니다.

이번 강의는 Wafer 예광탄을 작성하는 실습입니다.

[그림] Wafer 예광탄 실행 화면
[그림] Wafer 예광탄 실행 화면

1. Wafer 클래스 소스 코드

namespace Wafer_예광탄
{
    /// <summary>
    /// Wafer 클래스
    /// </summary>
    public class Wafer
    {
        static int last_wn;//가장 최근에 부여한 웨이퍼 일련 번호
        readonly int wn;//웨이퍼 일련 번호
        int[] cells = new int[100];
        int now;//현재 코팅할 쉘 번호
        /// <summary>
        /// 기본 생성자
        /// </summary>
        public Wafer()
        {
            last_wn++;
            wn = last_wn;//웨이퍼 번호 순차 부여
        }
        /// <summary>
        /// 현재 코팅하고 있는 쉘 번호 속성 - 가져오기
        /// </summary>
        public int Now
        {
            get { return now; }
        }
        /// <summary>
        /// 코팅할 쉘 번호 1증가 메서드
        /// </summary>
        /// <returns>다음 쉘이 유효하면 true, 유효하지 않으면 false</returns>
        public bool Increment()
        {
            if (now < 100)
            {
                now++;
                if (now == 100)//100번 인덱스 쉘은 없음 - 코팅 완료를 의미함
                {
                    return false;
                }
                return true;
            }
            return false;
        }
        /// <summary>
        /// 코팅 메서드
        /// </summary>
        /// <param name="quality">코팅 품질</param>
        public void Coating(int quality)
        {
            if (Now < 100)
            {
                cells[Now] = quality;
            }
        }
        /// <summary>
        /// 쉘의 품질에 접근하는 인덱서 - 가져오기
        /// </summary>
        /// <param name="index">쉘 인덱스(0~99)</param>
        /// <returns>쉘의 Quality</returns>
        public int this[int index]
        {
            get
            {
                if ((index < 0) || (index >= 100)) { return 0; }
                return cells[index];
            }
        }
        /// <summary>
        /// 품질 속성(평균 품질) - 가져오기
        /// </summary>
        public double Quality
        {
            get
            {
                int sum = 0;
                foreach (int elem in cells)
                {
                    sum += elem;
                }
                return sum / 100.0;
            }
        }
        /// <summary>
        /// ToString 재정의
        /// </summary>
        /// <returns>웨이퍼 번호, 품질</returns>
        public override string ToString()
        {
            return string.Format("No:{0}, Quality:{1}", wn, Quality);
        }
    }
}

2. Form1.cs 소스 코드

using System;
using System.Drawing;
using System.Windows.Forms;

namespace Wafer_예광탄
{
    public partial class Form1 : Form
    {
        public Wafer Wafer
        {
            get;
            set;
        }
        public Form1()
        {
            InitializeComponent();            
        }

        private void pn_wafer_Paint(object sender, PaintEventArgs e)
        {
            Graphics graphics = e.Graphics;
            Brush brush = Brushes.Silver;
            Rectangle rect = new Rectangle(0, 0, pn_wafer.Width, pn_wafer.Height);
            graphics.FillEllipse(brush, rect);
            int width = pn_wafer.Width;
            int height = pn_wafer.Height;
            int sx = (int)(width * 0.15);
            int sy = (int)(height * 0.15);
            Rectangle rect2 = new Rectangle(sx, sy, (int)(width * 0.7), (int)(height * 0.7));
            graphics.DrawRectangle(Pens.Red, rect2);
            int xu = rect2.Width / 10;
            int yu = rect2.Height / 10;
            Pen pen = new Pen(Color.DarkGray, 1);
            for (int x = 1; x < 10; x++)
            {
                graphics.DrawLine(pen, new Point(sx + x * xu, sy), new Point(sx + x * xu, sy + rect2.Height));
            }
            for (int y = 1; y < 10; y++)
            {
                graphics.DrawLine(pen, new Point(sx, sy + y * yu), new Point(sx + rect2.Width, sy + y * yu));
            }

            if (Wafer == null)
            {
                return;
            }
            int dir = 0;
            int step = 1, nowstep = step;
            int nx = 4, ny = 5;
            for (int i = 0; i < 100; i++)
            {
                int qual = Wafer[i];
                Color color = Color.FromArgb(200 - qual * 2, 55 + qual * 2, 0);
                Rectangle rt = new Rectangle(sx + nx * xu + 1, sy + ny * yu + 1, xu - 1, yu - 1);
                graphics.FillRectangle(new SolidBrush(color), rt);

                if (nowstep == 0)
                {
                    dir = (dir + 1) % 4;
                    if (dir % 2 == 0)
                    {
                        step++;
                    }
                    nowstep = step;
                }
                nowstep--;
                switch (dir)
                {
                    case 0: ny--; break;
                    case 1: nx++; break;
                    case 2: ny++; ; break;
                    case 3: nx--; break;
                }
            }
        }

        private void btn_start_Click(object sender, System.EventArgs e)
        {
            tm_coating.Enabled = true;
            btn_start.Enabled = false;
        }

        Random rand = new Random(); 
        private void tm_coating_Tick(object sender, System.EventArgs e)
        {
            if(Wafer ==null)
            {
                Wafer = new Wafer();
            }
            Wafer.Coating(rand.Next(70, 100));
            if(Wafer.Increment()==false)
            {
                tm_coating.Enabled = false;
                btn_start.Enabled = true;
                Wafer = null;
            }
            pn_wafer.Invalidate();
        }
    }
}

4. 더블 버퍼링 가능한 패널 클래스 소스 코드

using System.Windows.Forms;

namespace Wafer_예광탄
{
    /// <summary>
    /// DPanel 클래스 - 더블버퍼링 패널
    /// </summary>
    public class DPanel : Panel
    {
        /// <summary>
        /// 기본 생성자
        /// </summary>
        public DPanel()
        {
            SetStyle(System.Windows.Forms.ControlStyles.OptimizedDoubleBuffer | System.Windows.Forms.ControlStyles.UserPaint | System.Windows.Forms.ControlStyles.AllPaintingInWmPaint, true);
            UpdateStyles();
        }
    }
}

5. Form1.Designer.cs 수정한 소스 코드

namespace Wafer_예광탄
{
    partial class Form1
    {
        /// <summary>
        /// 필수 디자이너 변수입니다.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// 사용 중인 모든 리소스를 정리합니다.
        /// </summary>
        /// <param name="disposing">관리되는 리소스를 삭제해야 하면 true이고, 그렇지 않으면 false입니다.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows Form 디자이너에서 생성한 코드

        /// <summary>
        /// 디자이너 지원에 필요한 메서드입니다. 
        /// 이 메서드의 내용을 코드 편집기로 수정하지 마세요.
        /// </summary>
        private void InitializeComponent()
        {
            this.components = new System.ComponentModel.Container();
            this.tm_coating = new System.Windows.Forms.Timer(this.components);
            this.btn_start = new System.Windows.Forms.Button();
            //this.pn_wafer = new System.Windows.Forms.Panel();
            this.pn_wafer = new Wafer_예광탄.DPanel();
            this.SuspendLayout();
            // 
            // tm_coating
            // 
            this.tm_coating.Tick += new System.EventHandler(this.tm_coating_Tick);
            // 
            // btn_start
            // 
            this.btn_start.Location = new System.Drawing.Point(105, 23);
            this.btn_start.Name = "btn_start";
            this.btn_start.Size = new System.Drawing.Size(75, 23);
            this.btn_start.TabIndex = 1;
            this.btn_start.Text = "시작";
            this.btn_start.UseVisualStyleBackColor = true;
            this.btn_start.Click += new System.EventHandler(this.btn_start_Click);
            // 
            // pn_wafer
            // 
            this.pn_wafer.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
            this.pn_wafer.Location = new System.Drawing.Point(65, 66);
            this.pn_wafer.Name = "pn_wafer";
            this.pn_wafer.Size = new System.Drawing.Size(144, 144);
            this.pn_wafer.TabIndex = 0;
            this.pn_wafer.Paint += new System.Windows.Forms.PaintEventHandler(this.pn_wafer_Paint);
            // 
            // Form1
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 12F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(293, 271);
            this.Controls.Add(this.btn_start);
            this.Controls.Add(this.pn_wafer);
            this.Name = "Form1";
            this.Text = "Wafer Panel 예광탄";
            this.ResumeLayout(false);

        }

        #endregion
        private System.Windows.Forms.Timer tm_coating;
        private System.Windows.Forms.Button btn_start;
        private DPanel pn_wafer;
    }
}