C#으로 만들어 보는 Sokoban Game(WPF)

Software/C#|2024. 4. 18. 15:46
반응형

 

소코반 게임을 WPF 버젼으로 수정해서 올립니다. 아직 WPF를 공부중이라 MVVM 은 사용을 하지 않고 제작을 하였습니다.

코드는 지속적으로 수정을 진행할 예정입니다. 

소스 코드는 아래 Git에서 다운 받으시면 됩니다. 

 

https://github.com/Sihwan-Kim/PushPush.git

 

아래 파일은 맵화일과 Config파일 입니다. 실행파일이 있는 곳에 넣으시면 됩니다. 

stage.zip
0.00MB

 

Winform 버전의 알고리즘은 그대로 사용하였고 기능적인 부분이 조금 수정되었습니다. 

1. 윈폼 버전에서는 맵의 크기가 10 x 10으로 고정하였지만 WPF 버전에서는 크기를 동적으로 수정할 수 있도록 하였습니다.

2. 윈도우의 크기가 변경되면 맵이 항상 중앙에 위치 하도록 하였습니다. 

 

 

 

반응형

댓글()

2차원 배열의 크기를 동적으로 변경 - C#

Software/C#|2024. 4. 18. 14:09
반응형

        private static Array ResizeArray(Array arr, int[] newSizes)
        {
            if(newSizes.Length != arr.Rank)
            {
                throw new ArgumentException("arr must have the same number of dimensions " +
                                            "as there are elements in newSizes", "newSizes");
            }

            var temp = Array.CreateInstance(arr.GetType().GetElementType(), newSizes);
            int length = arr.Length <= temp.Length ? arr.Length : temp.Length;
            Array.ConstrainedCopy(arr, 0, temp, 0, length);

            return temp;
        }

//----------------------------------------------------------------------------------------------------------------

public int[,] array = new int[2, 2] ;     // 2 x 2 배열 생성 

array  = (int[,])ResizeArray( array  , new int[] {12, 3}) ;    // 12 x 3 형식으로 변경 

 

 

반응형

댓글()

C#으로 만들어 보는 Sokoban Game(Winform)

Software/C#|2024. 3. 13. 23:15
반응형

C# 의 winform 으로 소코반(Sokoban) 게임을 만들어 보았습니다. 

아마 프로그램 배우시는 분들이 가장 쉽게 만들어 볼 수 있는 게임 프로그램이 아닐까 합니다. 

 

프로그램의 형태는 아래 그림과 같습니다.

 

현재 기본적인 게임 알고리즘은 구현이 되어 있고 조금씩 기능을 업데이트 하고 있는 중입니다. 

소스는  Github 에 올려 두었습니다. 

 

https://github.com/Sihwan-Kim/Sokoban.git

 

코드는 계속 업데이트할 계획입니다. 

 

반응형

댓글()

ScottPlot Multi Axis 그리기 - C#

Software/C#|2024. 1. 18. 09:19
반응형

ScottPlot 가 버젼 5로 업데이트 되고 사용하는 방법이나 함수가 많이 변경이 된듯 합니다. 

이번 포스팅에서는 버젼 5를 기준으로 멀티 축을 그리는 방법에 대한 코드를 공유합니다. 

 

MultiAxis.zip
0.13MB

        (소스 코드)

    public partial class Form1 : Form
    {
        private ScottPlot.AxisPanels.RightAxis? YRight2 = null;  // 오른쪽 Y축 추가 
        private ScottPlot.AxisPanels.LeftAxis? YLeft2 = null;    // 왼쪽 Y축 추가 

        public Form1()
        {
            InitializeComponent();
            graphInit();
        }
        private void graphInit()
        {
            YLeft2 = formsPlot1.Plot.Axes.AddLeftAxis();        // 폼 디자인에 올려진 그래프 컨트롤에 왼쪽축을 추가하고 맵핑시킨다. 
            YRight2 = formsPlot1.Plot.Axes.AddRightAxis();      // 폼 디자인에 올려진 그래프 컨트롤에 오른쪽축을 추가하고 맵핑시킨다. 

            formsPlot1.Plot.Axes.Left.Label.Text = "Power";   // 기존 왼쪽 축의 항목을 설정 
            formsPlot1.Plot.Axes.Left.Label.ForeColor = Colors.Red;
            formsPlot1.Plot.Axes.Right.Label.Text = "Voltage";    // 기존 오른쪽 축의 항목을 설정 
            formsPlot1.Plot.Axes.Right.Label.ForeColor = Colors.Green;

            YLeft2.Label.Text = "SE";                           // 추가된 왼쪽 축의 항목을 설정 
            YLeft2.Label.ForeColor = Colors.Blue;
            YRight2.Label.Text = "RD";                          // 추가된 오른쪽 축의 항목을 설정 
            YRight2.Label.ForeColor = Colors.Purple;

            formsPlot1.Plot.Axes.Bottom.Label.Text = "Current"; // Bottom 축의 항목을 설정 
        }

        private void button1_Click(object sender, EventArgs e)
        {
            double[] dataX = { 0, 1, 2, 3, 4, 5};
            double[] dataLeftY1 = { 0, 10, 100, 300, 500, 800};
            double[] dataLeftY2 = { 0.1, 0.24, 1, 2, 2.1, 2.1};
            double[] dataRightY1 = { 0, 2, 2.1, 2.2, 2.3, 2.4};
            double[] dataRightY2 = { 100, 10, 5, 5.1, 5.2, 5.1 };

            var sigLeft1 = formsPlot1.Plot.Add.SignalXY(dataX, dataLeftY1, Colors.Red);       // 시그널 생성
            var sigLeft2 = formsPlot1.Plot.Add.SignalXY(dataX, dataLeftY2, Colors.Blue);
            var sigRight1 = formsPlot1.Plot.Add.SignalXY(dataX, dataRightY1, Colors.Green);
            var sigRight2 = formsPlot1.Plot.Add.SignalXY(dataX, dataRightY2, Colors.Purple);

            sigLeft1.Axes.YAxis = formsPlot1.Plot.Axes.Left;            // 시그널과 축을 맵핑 
            sigLeft2.Axes.YAxis = YLeft2!;
            sigRight1.Axes.YAxis = formsPlot1.Plot.Axes.Right;
            sigRight2.Axes.YAxis = YRight2!;

            graphScale(6, 1000, 4, 5, 100);   // 그래프 스케일 조정 
        }

        private void graphScale(double X_Axis, double Y_Left1, double Y_Left2, double Y_Right1, double Y_Right2)
        {
            formsPlot1.Plot.Axes.Bottom.Min = 0;
            formsPlot1.Plot.Axes.Bottom.Max = X_Axis;

            formsPlot1.Plot.Axes.Left.Min = 0;
            formsPlot1.Plot.Axes.Left.Max = Y_Left1;

            formsPlot1.Plot.Axes.Right.Min = 0;
            formsPlot1.Plot.Axes.Right.Max = Y_Right1;

            YLeft2!.Min = 0;
            YLeft2!.Max = Y_Left2;

            YRight2!.Min = 0;
            YRight2!.Max = Y_Right2;

            formsPlot1.Refresh();       // 그래프 갱신
        }
    }

 

 

출력결과 표시

 

반응형

댓글()

사칙연산을 통해 알아보는 Lambda 와 Func 델리게이트 활용 - C#

Software/C#|2023. 12. 23. 10:14
반응형

델리게이트와 lambda 에 대해 공부를 하면서 어느경우에 써먹을 수 있나 생각을 많이 하게 됩니다. 

이번 포스팅에서는 간단하게 사칙연산을 위한 lambda 와 Func 델리케이트의 활용에 대해 포스팅 해 보았습니다. 

 

 

위와 같이 폼을 하나 구성하고 콤보 박스에 각연산에 대한 항목을 Items 에 추가하고 이벤트 함수를 만들면 됩니다. 

 

        private double calculate(Func<double, double, double> func, double a, double b)
        {
            var result = func(a, b);
            return result;
        }

        private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            var a = double.Parse(textBox1.Text);
            var b = double.Parse(textBox2.Text);

            switch(comboBox1.SelectedIndex) 
            {
                case 0: textBox3.Text = calculate((i, j) => { return (i + j); }, a, b).ToString(); break;
                case 1: textBox3.Text = calculate((i, j) => { return (i - j); }, a, b).ToString(); break;
                case 2: textBox3.Text = calculate((i, j) => { return (i * j); }, a, b).ToString(); break;
                case 3: textBox3.Text = calculate((i, j) => { return (i / j); }, a, b).ToString(); break;
            }
        }

 

* calculate 함수는 Func 델리케이트와 피 연산자 값을  파라메터로 받는 함수입니다. 

* 콤보막스의 SelectedIndexChanged 이벤트 함수에서 switch-case 문을 이용하여 각각의 연산에 맞는 lambda 함수를 만들어 calculate 함수의 파라메터로 넘겨주면 계산된 결과가 출력이 됩니다. 

반응형

댓글()

항목이 여러개인 List<>에서 각각의 항목을 나누어서 배열로 변환 C#

Software/C#|2023. 12. 12. 10:54
반응형

배열이나 구조체 형식의 List 의 경우 각각의 요소에 대해 배열로 만들 경우가 발생한다. 

형식 자체를 배열로 만드는 것은 ToArray() 를 사용할 수 있지만 각각의 요소를 배열로 만들 경우는 아래와 같이 사용하면 된다. 

 

class Point

{

    public int X {  get; set; }

    public int Y {  get; set; }

}

 

List<Point> ListPoints = new List<Point>() ;

 

배열변환 #1  :

    var arrayX = ListPoints.ConvertAll(s => s.X).ToArray() ; 

    var arrayY = ListPoints.ConvertAll(s => s.Y).ToArray() ;

 

배열변환 #2  :

    var arrayX = ListPoints.Select(s => s.X).ToArray() ; 

    var arrayY = ListPoints.Select (s => s.Y).ToArray() ;

반응형

댓글()

설정값 저장을 위한 ini 파일 과 yaml 파일 사용방법 - C#

Software/C#|2023. 11. 29. 14:47
반응형

장비제어 프로그램 개발시에 시스템의 하드웨어 설정값등을 저장하고 불러 오는 용도로 ini 파일 저장과 yaml 파일 저장 방법을 사용할 수 있도록 테스트 프로그램을 작성해 보았습니다. 

 

Ini_Yaml.zip
0.01MB

 

ini 파일 저장은 인터넷에 있는 Class 를 다운받아 사용하였습니다. yaml 은 YamlDotNet 라이브러리를 사용하였습니다. 

 

코드 작성이나 향후 항목 변경이 되었을 경우 코드 변경에서는 yaml이 편하고 좋습니다. 하지만 프로그램 사용자가 yaml 데이타를 직접 수정할 경우에는 규칙을 지켜서 수정해야 하는 번거로움은 좀 있네요.. 

 

파일에 저장되는 형태는 아래와 같습니다. 

ini 저장 데이타 파일

[Temperature]
Offset-1=12.3
Offset-2=53.987
[System]
Name=test
Item-1=0

 

yaml 저장 데이타 파일

temperature:
  Offset1: 3
  Offset2: 4
system:
  Name: bbb
  Item1: 3
  Item2: 0
  ListItems:
  - 11
  - 22
  - 33

 

아래 코드는 yaml 사용에 대한 내용입니다.

    public class MachineData
    {
        public class Temperature
        {
            public double Offset1 { get; set; }
            public double Offset2 { get; set; }
        }

        public class System
        {
            public string Name { get; set; }
            public int Item1 { get; set; }
            public int Item2 { get; set; }
            public List<double> ListItems { get; set; }

            public System() 
            { 
                ListItems = new List<double>(); 
            }
        }

        public Temperature temperature = new Temperature();
        public System system = new System();
    }

    public class YamlControl<T>
    { 
        public void SaveYaml(string FileName, T data)
        {
            var serializer = SerializeToYaml(data);

            using StreamWriter sw = new StreamWriter(FileName);
            sw.Write(serializer);
        }

        public T LoadYaml(string FileName)
        {
            T machine = DeserializeFromYaml<T>(FileName);

            return machine;
        }

        private string SerializeToYaml<T>(T obj)
        {
            var serializer = new SerializerBuilder().Build();
            return serializer.Serialize(obj);
        }

        // Deserialize YAML to an object
        private T DeserializeFromYaml<T>(string yaml)
        {
            var deserializer = new DeserializerBuilder().Build();
            return deserializer.Deserialize<T>(File.ReadAllText(yaml));
        }
    }
반응형

댓글()

Tag 속성을 이용하여 RadioButton 사용 코딩 줄이기 #2 - C#

Software/C#|2023. 8. 29. 23:55
반응형

RadioButton 사용방법 2번째 입니다. 지난번에 이어 이번에도 Tag 속성을 이용하여 RadioButton 을 간단하게 사용하는 방법을 구현합니다. 

위 그림과 같이 GroupBox 안에 3개의 RadioButton 을 넣습니다. 그리고 순서대로 Tag 속성을 0,1,2 로 설정합니다.

첫번째 메뉴인 등심에 Checked 를 하고 GroupBox의 Tag 속성을 0으로 설정합니다.

 

그리고 RadioButton 3개의 Clicked 이벤트를 아래 코드와 같이 동일한 이벤트 함수로 구현합니다.

        private void MenuClicked(object sender, EventArgs e)
        {
            RadioButton radio = sender as RadioButton;
            if (radio != null)
            {
                groupBox1.Tag = radio.Tag;   // 눌려진 버튼의 tag 값을 groupBox 의 Tag 값에 저장한다. 
            }
        }

 

그리고 주문 버튼에 대한 이벤트 함수를 아래와 같이 switch 문을 이용해서 구현하면 간단하게 RadioButton 에 대한 선택 구현을 할수 있습니다.

 

        private void btnOrder_Click(object sender, EventArgs e)
        {
            var menu = int.Parse(groupBox1.Tag.ToString());
            switch (menu)
            {
                case 0: textBox1.Text = "등심주문"; break;
                case 1: textBox1.Text = "안심주문"; break;
                case 2: textBox1.Text = "갈비주문"; break;
            }
        }

반응형

댓글()