WPFImagePrintTest.zip



회사에서 일을 하던중에 이미지 파일의 인쇄가 프로그램을 만들게 되었습니다.


웹을 뒤져보니까 윈폼용을 있지만 WPF용으로는 없는 것 같아서 이렇게 블로깅을 하게 되었네요!


매우 간추리자면 PridDialog를 사용하면 됩니다! 아시는 문들은 MSDN에 가서 보시면 되시겠구요. 저는 버튼을 누르면 이미지 출력!


인쇄를 누르면 인쇄 하는 것 까지 만들어 보겠습니다.


파일 -> 새로 만들기 -> 프로젝트


먼저 Xaml은


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<Window x:Class="WPFImagePrintTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WPFImagePrintTest"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Image Name="image" Height="250" Width="425" Margin="82,10,10,59"></Image>
 
        <Button x:Name="button1" Content="이미지!" HorizontalAlignment="Left" Margin="10,279,0,10" Width="75" Click="button1_Click"/>
        <Button x:Name="button" Content="인쇄" HorizontalAlignment="Left" Margin="110,279,0,10"  Width="75" Click="button_Click"/>
    </Grid>
</Window>
 
cs

버튼 2개 이미지뷰 한개를 만들어서 올려줍니다. 어차피 간단한 테스트 프로그램이니 대충~ 원하는 대로!


먼저 이미지를 불러오는 함수를 만들어 줍시다.


1
2
3
4
5
6
7
8
9
private ImageSource imageLoad() // 이미지를 불러오는 부분
{
    var bi = new BitmapImage();
    bi.BeginInit();
    bi.CacheOption = BitmapCacheOption.OnLoad;
    bi.UriSource = new Uri(@"..\Assets\images.png", UriKind.Relative);
    bi.EndInit();
    return bi;
}
cs

비트뱁 이미지를 생성후에 Uri를 통해서 이미지를 가져옵니다.

먼저 이미지 소스에 이미지를 넣는 버튼 이벤트를 해보겠습니다.

1
2
3
4
private void button1_Click(object sender, RoutedEventArgs e)   // 이미지 보여주는 함수
{
    image.Source = imageLoad();
}
cs

네 참 쉽죠? 그냥 이미지의 속성중에 소스라는 곳에 비트맵을 넣어주면 됩니다.


실행해보면?



네 잘 나옵니다!


자 이제 정말 중요한 인쇄 부분을 보겠습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
private void button_Click(object sender, RoutedEventArgs e) // 이미지를 인쇄하는 부분
{
    var bi = imageLoad();
 
    var vis = new DrawingVisual();
    var dc = vis.RenderOpen();
    dc.DrawImage(bi, new Rect { Width = bi.Width, Height = bi.Height });// 이것을 움직이면 크기를 바꿀 수 있습니다.
    dc.Close();
 
    var pdialog = new PrintDialog();
    if (pdialog.ShowDialog() == true)
    {   
        pdialog.PrintVisual(vis, "Smile Image");
    }
}
cs

비트맥에 이미지 로딩하는 부분을 넣은후

그 비트맵을 Visual이라는 형식으로 바꾸는 작업이 필요합니다. 그렇게 바뀌어진 Visual을 PrintDialog.PrintVisual에 넣으면 완성!


짠~ 전 pdf와 저의 인쇄기로 테스트해봤는데 잘 됩니다!


풀 소스와 프로젝트파일 까지 올려 놓을테니 많이 많이 도움이 되시길 바랍니다!


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        
    }
    private void button_Click(object sender, RoutedEventArgs e) // 이미지를 인쇄하는 부분
    {
        var bi = imageLoad();
 
        var vis = new DrawingVisual();
        var dc = vis.RenderOpen();
        dc.DrawImage(bi, new Rect { Width = bi.Width, Height = bi.Height });// 이것을 움직이면 크기를 바꿀 수 있습니다.
        dc.Close();
 
        var pdialog = new PrintDialog();
        if (pdialog.ShowDialog() == true)
        {   
            pdialog.PrintVisual(vis, "Smile Image");
        }
    }
    private void button1_Click(object sender, RoutedEventArgs e)   // 이미지 보여주는 함수
    {
        image.Source = imageLoad();
    }
    private ImageSource imageLoad() // 이미지를 불러오는 부분
    {
        var bi = new BitmapImage();
        bi.BeginInit();
        bi.CacheOption = BitmapCacheOption.OnLoad;
        bi.UriSource = new Uri(@"..\Assets\images.png", UriKind.Relative);
        bi.EndInit();
        return bi;
    }
}



cs



참고: http://stackoverflow.com/questions/265062/load-image-from-file-and-print-it-using-wpf-how


 

 

 

먼저 제가 첨부해 놓은 파일을 받아봅시다!

파일 이름에서 유추할수 있듯이 가위 바위 보 입니다.

윈도우즈 10 앱으로 제가 만들 가위 바위 보는 제가 그림을 클릭 하면 가위 바위 보를 내게 되고 컴퓨터도 그렇게 내어서 이겼는지 졌는지를 알수 있는 앱입니다.

저번에 그냥 텍스트 블록과 버튼만 필요했던 것과는 달리 이번에는 알아야 할것이 몇가지 있습니다. 짚어보겠습니다.

1. 버튼에 이미지 넣기!

Xaml에서 마이크로소프트가 제공하는 버튼을 넣으면

이렇게 나옵니다. 깔끔하긴한데 그렇게 이쁘? 지는 않는것 같습니다.

그리고 요즘 UI나 UX를 중요시 하는 시대라서 그런지 아마 저것을 그냥 쓰는 회사도 많이 없을거 같네요

그럼 어떻게 해야 할까요?

자 먼저 위의 버튼을 xaml 파일로 본다면

1
 <Button x:Name="button" Content="Button" HorizontalAlignment="Left" Margin="176,198,0,0" VerticalAlignment="Top" Width="182" Height="102"/>
cs

이렇게 나옵니다. 이름도 버튼 써있는 것도 버튼 그럼 우리 첨부파일중에 가위를 버튼이미지로 해보겠습니다.

1
2
3
4
5
6
7
<Button x:Name="button" Content="Button" HorizontalAlignment="Left" Margin="176,198,0,0" VerticalAlignment="Top" Width="182" Height="102">
            <Button.Template>
                <ControlTemplate>
                    <Image Source="Assets/Scissor.png"/>
                </ControlTemplate>
            </Button.Template>
        </Button>
cs

버튼 사이에 버튼 템플릿이라는 것을 넣고 더해서 컨트롤 템플릿을 넣으면 이미지소스를 통해서 이미지모양 버튼을 만들 수 있게 됩니다.

그럼 버튼이 어떻게 나오나 볼까요?


이렇게 칙칙한 회색 버튼이 가위로 바뀌었습니다! 버튼 사이에 템플릿 넣기! 기억해 둡시다

2. 이벤트시 그림 나오게 하기

우리 버튼 이벤트( 버튼을 클릭했을 때) 어떻게 했는지 기억 나시나요?

저버튼을 두번 클릭하기!

1
2
3
4
private void button_Click(object sender, RoutedEventArgs e)
        {
 
        }
cs

그럼 이렇게 메서드가 생기죠? 자 여기서 생각을 해봅시다. 우리가 버튼을 템플릿으로 만들었을때 이미지소스 즉 위치를 컴퓨터가 찾을수 있도록 해주었죠?

그럼 저 메서드 안에서 이미지 소스를 알려주어야 하지 않을까요? 즉 이미지를 보여주는 곳에 이미지 소스를 알려주면 되지 않을까요?

네 가능합니다.! 먼저 저 앱에서 ToolBox에서 이미지를 원하는 곳에 위치 시켜봅시다.

이미지를 보여주는것에 사용할 레고 세트를 사야합니다

using Windows.UI.Xaml.Media.Imaging;

를 추가 시켜 줍시다 그래야 Bitmap이라는 클래스를 이용해서 이미지를 보여줄수 있어요!

자 그럼 소스를 적어봅시다.

1
 image.Source = new BitmapImage(new Uri("ms-appx:///Assets/Scissor.png", UriKind.Absolute));
cs

이 한줄이면 버튼을 누르면 그것이 바로 Image가 위치한 화면에 뙇! 하고 나옵니다.

소스를 뜯어보면 image의 Source를 정해줄게요! 라는 것을 시작으로 비트맵 클래스의 uri를 정해주는 겁니다.

ms-appx는 Microsoft의 앱 데이터들을 말해주는 것이고요 urikind.absolute 보니까 감이 오지 않나요?

uri경로를 절대경로로 하겠다는 뜻입니다!


자 이렇게 그림 가위바위 보를 만들기 위한 그림과 요소들을 알아보았구요! 혼자 가위바위보를 만들어 봅시다!


우리 로또 번호을 universal app으로 만들어 봅시다

먼저 로또번호가 나와야할 Textblock이 하나 필요하겠네요

두번째 로는 버튼이 필요할 것 같네요 버튼을 누를때 마다 새로운 로또 번호를 생성하도록 만들어 보겠습니다

첫번째로는 xaml 파일로 버튼과 텍스트 블록을 만들어 줍니다. 위치나 크기 등등은 마음대로 해보세요

이렇게 위치도 바꾸어 보고 만져보면서 xaml에 더 나아가 윈도우앱에 익숙해집니다!



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<Page
    x:Class="uniappTest.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:uniappTest"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">
 
    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" Margin="0,0,-647,0">
        <Button x:Name="button" Content="로또 번호 생성하기" HorizontalAlignment="Left" Margin="675,188,0,0" VerticalAlignment="Top" Click="button_Click"/>
        <TextBlock x:Name="textBlock" HorizontalAlignment="Left" Margin="148,188,0,0" TextWrapping="Wrap" Text="로또 번호 생성기" VerticalAlignment="Top" Width="522" Height="32"/>
 
 
    </Grid>
</Page>
 
cs

 저같은 경우는 텍스트 블록을 하나두고 로또번호 생성기라고 처음에 넣어줄겁니다

그냥 하얀 화면에 버튼만 보인다면 심심하니까요?

그리고 그 옆에 버튼을 하나 두어서 누를때 마다 새로운 로또번호가 나오게 할 것 입니다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
 
// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409
 
namespace uniappTest
{
    /// <summary>
    /// An empty page that can be used on its own or navigated to within a Frame.
    /// </summary>
    public sealed partial class MainPage : Page
    {
        int[] number;
        Random my_rand;
        public MainPage()
        {
            number = new int[7];
            my_rand = new Random();
            this.InitializeComponent();
        }
 
        private void button_Click(object sender, RoutedEventArgs e)
        {
            MakeNumber();
            textBlock.Text = " "// 초기화 전에 있던 거 지우기
            
           
            for (int i = 0; i < number.Length;i++)
            {
                
                if (number.Length-1==i)
                {
                    textBlock.Text += " 보너스 번호는 " + number[number.Length - 1];
                }
                else
                {
                    textBlock.Text += " " + number[i];
                }
            }
        }
        void MakeNumber()
        {
            int a;
            for (int i = 0; i < number.Length; i++)
            {
                a = my_rand.Next(145);
                if (true == CheckSame(i, a))
                {
                    number[i] = a;
                }
                else
                {
                    i--;
                }
            }
 
        }
        bool CheckSame(int index,int value)
        {
            for (int i = 0; i < index; i++)
            {
                if (value == number[i])
                {
                    return false;
                }
            }
            return true;
        }
       
    }
}
 
cs


나머지는 앞에서 콘솔로 만들었던 것과 같습니다! 조금 달랐던점은 제가 주석으로 표시를 해두었으니 참고하시면서

꼭 자기손으로 만들어 보시길 바랍니다!


실행화면










올해 발표하고 많은 사람들이 업데이트한 Windows 10!

마이크로소프트의 차기 운영체제로 마이크로소프트에서도 밀고 있는 운영체제인데요 지금까지 배운 C#으로

GUI 프로그래밍을 해보겠습니다.

첫 번째로 프로젝트를 만들어 봅시다!

1. File -> New  -> Project 를 누릅니다.



2.Visual C# -> Universal -> Blank App(Universal Windows) 를 누르고 이름을 HelloWindows10 을 하고 OK를 눌러줍니다.

짠 하고 생성되었습니다 다른것들은 차차 알아갈테니 우리가 가장 중요하게 봐야 하는것!

MainPage.xaml을 클릭해줍니다


그럼 이렇게 Xaml과 Degin이 생깁니다.

우리가 중점을 두어야 할 것은 바로 이 Xaml입니다. 마이크로소프트는 처음에 C언어와 C++언어를 이용해서 윈도우즈 프로그래밍 언어를 만들게끔 도구들을 제공했습니다. 바로 Win32 API와 MFC 인데요 하지만 너무 어려웠고 비주얼 스튜디오때문에 쓴다는 말이 있을 정도로 그렇게 까지 좋지 않았습니다.

그렇게 발전하고 발전하다가 나온게 xaml이라는 마크업 언어로 디자인을 하고 C#/C++/VB로 코딩을 하는 방법을 나오게 되었고 지금 wpf->windows 8->windows 10이런식으로 발전하면서 윈도우즈 프로그래밍은 이렇게 만드는 것으로 고착화?가 된듯 합니다. 이런 배경이 궁금하신분들은 찾아보시고! 우리 Hello Windows 10을 만들어 봅시다

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<Page
    x:Class="HelloWindows10.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:HelloWindows10"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">
 
    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
 
    </Grid>
</Page>
 
cs

바로 생성된 xaml 파일! 하나하나 볼까요?

      x:Class="HelloWindows10.MainPage"

이것은 xaml 파일의 가장 중요한 루트(뿌리)에서만 나타나며 C#에 의하면 class 와 같은 의미를 가지는 것입니다 즉 HelloWindows10이라는 네임스페이스 하위의 Mainpage 클래스는 Page로부터 나타난 것이다 라고 생각하시면 됩니다.

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

2006년이 마이크로소프트가 이런 방식과 xaml을 처음으로 선보인 해 입니다. winfx라는것은 이런 방식이 wpf라고도 하는데 이렇게 발표되기 전에는 Winfx라고도 불렸다네요 그래서 winfx가 삽입되어 있습니다. xaml은 WPF,실버라이트,윈도우폰,윈도우즈 사이에서 어느정도 호환은 되지만 공통되는 것은 클래스와 속성과 기능뿐입니다.

나머지 세줄은 마이크로소프트에서 디자인과 기획툴로 사용되는 블랜드라는 툴을 위한 코드이므로 무시하셔도 됩니다!

자그럼 우리 Hello Windows 10을 만들어 볼까요?

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

    </Grid>

사이에 코드를 적어 봅시다

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<Page
    x:Class="HelloWindows10.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:HelloWindows10"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">
 
    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <TextBlock Text="Hello, Windows 10"
                   FontFamily="segoe UI"
                   FontSize="96"
                   Foreground="SkyBlue"
                   HorizontalAlignment="Center"
                   VerticalAlignment="Center" />
    </Grid>
</Page>
 
cs

1. TextBlock 글자를 보여주는 도구 입니다 그안에 여러가지 속성이 있습니다.

Text=Text="Hello, Windows 10"""  ""안에 우리가 쓰고 싶은 글자를 써주시면 됩니다

FontFamily="segoe UI"               ""안에 원하는 폰트 이름을 넣어주시면 됩니다. 저는 윈도우 공식폰트인 segoe UI

FontSize="100"                         폰트 사이즈! 저는 단순하게 100 넣어볼게요!

Foreground="SkyBlue"              색생! 저는 시원하게 Skyblue를 넣어 보겠습니다!

 HorizontalAlignment="Center"   수평으로 가운데! 라는 뜻인데요 어느 플랫폼이든 가운데에 넣을 수 있게 됩니다!

 VerticalAlignment="Center"      수직으로 가운데! 이또한 어느 플랫폼이나 기기든 가운데에 넣을수 있게 됩니다.


이렇게 나오면 잘 됮거에요!

그럼 실행해 봅시다!


우아 먼가 멋있죠? 아 뭔가 예뻐... 우리의 첫 GUI 프로그램 Hello World가 완성되었습니다.

Xaml 생각보다 어렵지 않고 신기하죠? 다음은 로또번호 생성기를 만들면서 버튼도 만들어 보겠습니다!


드디어! 까만화면에 커서만 번뜩번뜩 하던것을 떠나서

우리가 정말 쓰는 프로그램 같은 네모에 이것저것 나오는 GUI 프로그래밍을 해볼 것 입니다.

C#에서 GUI를 만들때 쓰는 방법은 WindowsForm,WPF,Universal App 이정도로 있습니다(WIndows 8 은점유율이 낮으니 제외하도록 하겠습니다)

하지만 WindowsForm은 점점 쓰지 않는 기술이고 다른 두개와 방식이 많이 다릅니다. 그래서 저는 WindowsForm은 하지 않겠습니다.

제가 주로 할 것은 Uiversal App(Windows 10) 인데요 이 방식은 Xaml 이라는 Markup 언어를 사용하고 그 방식이 비슷합니다.

최근 Microsoft에서도 밀고 있는 언어이기도 하고 Universal App을 하게 되면 WPF나 Windows 8 사용하는데 큰 지장이 없습니다.

또한 이것을 통해서 익혀 두면 Web에서 사용하는 ASP .NET을 쉽게 익히실수 있을 것 입니다.(사실 이거 두개만해도 Windows 8 app도 가능합니다)

그래서 프로젝트를 WIndows 10 Universal App을  한번 만들어 보겠습니다.

우리가 콘솔환경에서 했던것을 GUI로 한번 복습한후 다음 진도로 넘어갈게요!

그럼 다음 포스팅때 봐요~~!

자 우리 까만화면 시리즈의 마지막 행맨을 해봅시다!

제가 생각한 방법은 

1. 클래스를 하나 더 만들겠습니다! 컴퓨터 클래스를 만들어서 문제들을 몇개 넣을거에요! 배열로요!

2. 이겼습니다 졌습니다 나오는 메서드와 행맨의 상태를 보여주는 메서드를 만들겠습니다.

3. 레벨이 5이상일때 끝내는 매서드를 만들겠습니다.

4. 레벨이 5면 끝내고 아니라면 입력한 문자를 바꾸어주는 메서드를 만들겠습니다.

5. 주 클래스로 와서 String을 입력받고 그 값이 에러가 아니라면 리턴해주는 메서드를 만들겠습니다.

6. 마지막으로 While문으로 이기거나 지기까지 계속 하게 만드는 메서드를 만들겠습니다.

Computer.cs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace Hangman  // 크게 입력 문제인지, 비교문제인지, 알아 보아야 함
{
    class Computer
    {
        private String[] m_key =
        {
            "Boolean",
            "Integer",
            "String",
            "System",
            "Thread",
            "StringBuffer",
            "Package",
            "Class",
            "Object",
            "Void"
        };
        public StringBuilder m_user;  //유저가 넣은 글자
        public String m_word;        // 컴퓨터가 랜덤으로 넣은 글자
        private int m_level;          // 맞거나 틀리거나 한 레벨
        private int m_index;          // 크기를 알아야 그 크기 만큼 -로 채울수 있다
        public Computer()            //생성자를 통해서 변수 초기화
        {
            Random myrand = new Random();
            m_index = myrand.Next(m_key.Length-1); //랜덤으로 값을 인덱스에 넣고 번째 찾음
            m_word = m_key[m_index];               //나의 키 중에 나의 인덱스를 가진값을 word에 넣음 예 0은 boolean
            m_level = 0;                           //레벨은 9부터 시작
 
            m_user = new StringBuilder();         //유저가 넣은 값을 stringbuilder 에 넣음
           
            
            for(int i=0;i<m_word.Length;i++)       //word에 길이 만큼 -생성
            {
                m_user.Append('_');
            }
 
        }
        public void showEndMsg(Boolean isWin) // true false값을 통해서 메세지 생성 함수
        {
            String msg;
 
            if(true == isWin)
            {
                msg = "사형수를 구하셨습니다";
            }
            else 
            {
                msg = "사형이 집행 되었습니다.";
            }
            Console.WriteLine(msg);
        }
        public void showHangMan()           //레벨을 가지고 행맨을 보여주는 함수
        {
            Console.WriteLine("★ 집행 단계 ★");
            switch (m_level)
            {
                case 0:
                    Console.WriteLine("    ┌──┐");
                    Console.WriteLine("    ▲    ┃");
                    Console.WriteLine("          ┃");
                    Console.WriteLine("          ┃");
                    Console.WriteLine("          ┃");
                    Console.WriteLine("          ┃"); ;
                    break;
                case 1:
                    Console.WriteLine("    ┌──┐");
                    Console.WriteLine("    ▲    ┃");
                    Console.WriteLine("┌─┼─  ┃");
                    Console.WriteLine("          ┃");
                    Console.WriteLine("          ┃");
                    Console.WriteLine("          ┃");
                    break;
                case 2:
                    Console.WriteLine("    ┌──┐");
                    Console.WriteLine("    ▲    ┃");
                    Console.WriteLine("┌─┼─┐┃");
                    Console.WriteLine("          ┃");
                    Console.WriteLine("          ┃");
                    Console.WriteLine("          ┃");
                    break;
                case 3:
                    Console.WriteLine("    ┌──┐");
                    Console.WriteLine("    ▲    ┃");
                    Console.WriteLine("┌─┼─┐┃");
                    Console.WriteLine("    ┃    ┃");
                    Console.WriteLine("          ┃");
                    Console.WriteLine("          ┃");
                    break;
                case 4:
                    Console.WriteLine("    ┌──┐");
                    Console.WriteLine("    ▲    ┃");
                    Console.WriteLine("┌─┼─┐┃");
                    Console.WriteLine("    ┃    ┃");
                    Console.WriteLine("┌─┼─  ┃");
                    Console.WriteLine("          ┃");
                    break;
                case 5:
                    Console.WriteLine("    ┌──┐");
                    Console.WriteLine("    ▲    ┃");
                    Console.WriteLine("┌─┼─┐┃");
                    Console.WriteLine("    ┃    ┃");
                    Console.WriteLine("┌─┼─┐┃");
                    Console.WriteLine("          ┃");
                    break;
                default:
                    Console.WriteLine("  ┌───┐");
                    Console.WriteLine("      ┃");
                    Console.WriteLine("      ┃");
                    Console.WriteLine("      ┃");
                    Console.WriteLine("      ┃");
                    Console.WriteLine("      ┃");
                    break;
 
            }
        }
        private int checkEnd()              
        {
            String t_msg;
 
            t_msg = m_user.ToString();
            
            if(t_msg.Equals(m_key[m_index]))
            {
                return 1;
            }
 
            if(5<=m_level)
            {
                return 2;
            }
            return 0;
        }
        public int checkLevel(char msg)
        {
            Boolean find = false;
 
            for(int i =0;i<m_key[m_index].Length;i++)
            {
                if(m_key[m_index][i]==msg)
                {
                    if('_' == m_user[i]) //중복을 막아준다
                    {
                        m_user[i]=msg;
                        find = true;
                        break;
                    }
                }
            }
            if(false == find)
            {
                m_level++;
            }
            return checkEnd();
        }
    }
}
 
cs

Program.cs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace Hangman
{
    class Program
    {
        Computer m_com;
        public void Hangman()
        {
            m_com = new Computer();
        }
        public char getKey()
        {
            String msg;
 
            char a;
            msg = "error";
         
            Console.WriteLine("알파벳을 입력하세요:");
            msg = Console.ReadLine();
         
            a = msg[0];
            return a;
        }
        public void run()
        {
            int result;
            char msg;
 
            while (true)
            {
                Console.WriteLine(" "+m_com.m_user);
                msg = getKey();
                result = m_com.checkLevel(msg);
 
                m_com.showHangMan();
                if(1==result)
                {
                    m_com.showEndMsg(true);
                    break;
                }
                else if(2==result)
                {
                    m_com.showEndMsg(false);
                    break;
                }
            }
           
 
        }
        static void Main(string[] args)
        {
            Program m = new Program();
            m.Hangman();
            m.run(); 
        }
    }
}
 
cs
프로그램 모습




음.. 제가 아마 처음 영어공부를 할때 였던거 같아요

아버님 회사 직원중 한분이 영어를 너무 잘하셔서 저희에게 영어를 가르쳐 주셨는데 전 그때 행맨을 알았어요

전 단순히 글자 맞추는 건줄 알았는데 왠걸? 나중에 알아보니 못 마출 경우 뭔가는 매다는? 무시무시한 게임이었어요

네 글자맞추기! 하지만 맞추지 못하면? 무엇인가를 매다는? 게임 행맨 을 해볼게요!






그전에 알아야 할 것들 첫번째는?


1. String 변수의 할당과 초기화


먼저 String을 해보면 string과 String 두개가 있습니다다 무슨차이일까요? 결론은 똑같습니다다.

System.String allias를 쓴다고 하는데 이런거 몰라도 되고 그냥 마음에 드는 것을 쓰자구요!

초기화는

String a;           //초기화 하지않기

String a = null    //null로 초기화

String a = "haha" //haha로 초기화 등

이렇게 쓸수 있습니다. 지금까지는 항상int로 바꾸었는데 String은 그냥 변수선언하고 따옴표안에 써 넣으면 됩니다.!


2. 두 String 비교하기


행맨을 하기 위해서는 두개의 String 변수를 비교해야 합니다. 그래서 저희는 .Equal 메서드를 사용할 것입니다.

이 문자열이 같은지 안같은지 알려주는 메서드이구요 같으면 true를 다르면 false를 돌려주면서 값이 같은지 안같은지 가르쳐 줍니다.

사용방법은

String a1 = "haha"

String a2 = "haha"

if(a1.Equals(a2))  //Ture로 반환 합니다.

{

정답

}

이렇게 사용하시면 됩니다.!

여기서 볼 것은 Haha와 haha는 다른데요 C#은 대문자 소문자 구별을 하기 때문입니다. 만약 아 그런거 필요없다! 하시는 분은

a.Equals(b, StringComparison.OrdinalIgnoreCase); 이런식으로 해주시면 됩니다.!


3. String 과 StringBuilder


이미 만들어진 문자열에 문자를 추가하거나 중간에 문자를 삽입하는 이렇게 조물딱 조물딱 하려면 String 객체로는 하기 어렵습니다.

그래서 나온것이 바로 StringBuilder 입니다.간단한 것은 String을 사용하고 복잡한 것은 StringBuilder를 사용하면 됩니다!

선언은

StringBuilder str = new StringBuilder();

문자열의 길이는?

str.length;

3번째 문자는?

str.Chars(2);

3번째 문자를 k로 변경하려면?

str[3] = k;

끝에 ab를 추가하면?

str.append("ab");

2번째에 '@'를 첨가하면?

str.insert(1,'@');

등등 정도 알아두면 된다.


4. 클래스의 변수와 메서드의 접근제어


처음 클래스를 배울때 Public Private,protected 에 대해서 배웠는데 public만 하고 나머지는 다음에 한다고 했었죠?

일단 protected는 다음에 알도록 하고 오늘은 private만 해보도록 합시다. public은 앞에서 말했다 시피 어디에서나 접근가능합니다.

public 공공의 라는 단어와 같이 그런 뜻을 지닙니다 그럼 private는? 네 그 메서드를 선언한 클래스 내에서만 사용가능한 메서드 입니다.

C#은 앞에 아무것도 붙이지 않으면 자동으로 private가 되므로 공공연하게 필요할때는 public을 선언해 봅시다. 예를 들어 볼까요? 주석을 봅시다!


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace CallTest
{
    class Program
    {
        public Program()
        {
 
        }
        private void getValue()
        {
 
        }
        static void Main(string[] args)
        {
            
            t1 t = new t1();
            t.ptest();       //사용 가능
            t.priTest();     //사용 불가
 
        }
    }
    class t1
    {
        public t1()
        {
 
        }
        public int ptest()
        {
            int a=0;
            a++;
            
            return a;
        }
        private int priTest()
        {
            int b = 0;
            b++;
            return b;
        }
    }
}
 
cs

자 이정도면 행맨을 만들기에 충분히 안것 같습니다! 이 게임을 만든후 드디어!GUI를 하도록 하니 마지막 까지 힘냅시다!



앞에서 대부분 배운것 이기에 이번 알아야 할 것들이 작네요!

자 만들어 볼까요?

다시 문제를 봅시다

0~9까지 중복을 허용하지 않는 숫자중에 자신이 예측하는 3개의 숫자를 입력합니다. 입력한 숫자와 컴퓨터가 생성한 숫자가 같으면 스트라이크로

값만 있고 위치가 다르면 볼 로 해서 사용자에게 결과를 알려줍니다. 이 정보로 추측하여 세 숫자와 그 위치까지 맞추면 게임이 끝납니다.

한번의 게임에 총 10번의 시도를 할 수 있습니다.


1.먼저 가위바위 보 같이 플레이어 클래스를 만들겠습니다 숫자를 입력받고 int형으로 변환하겠죠?

2. 숫자 3개를 랜덤으로 만드는 메서드 만들겠습니다.(중복이 없게 하는게 중요하겠죠? 중복제거는 로또번호에서 썻던 함수를 응용!)

3. 단순하게 메세지가 보이는 메서드, 스트라이크 볼이 보이는 메서드를 만들겠습니다.

4.게임이 끝날때 보이는 메서드를 생성합니다. 이겼거나 졌거나 컴퓨터의 숫자를 보여주는 메서드등으로 이루어져 있겠죠?

5.스트라이크와 볼등을 체크하는 메서드를 만들것 입니다.

6.한번 플레이 할때마다 체크 메서드를 이용 다른 메서드까지 이용해서 스트라이크와 볼을 보여주는 메서드를 만듭니다.

7.마지막으로 만든 메서드를 run 메서드에 넣고 완료!


소스 코드

Player.cs


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace NumberBaseBall
{
 
    class Player
    {
        int a;
        String msg;
        public Player()
        {
            a = 0;
            msg = " ";
        }
        public int input()
        {
            Console.WriteLine("0 - 9 사이 값을 넣으세요");
            msg = Console.ReadLine();
           
            a = int.Parse(msg);
            return a;
        }
    }
 
}
 
cs

Program.cs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace NumberBaseBall
{
    class Program
    {
        int[] m_data;
        Player m_Player;
        void NumberBaseBall()
        {
            m_data= new int[3];
            m_Player = new Player();
        }
        void makeData()
        {
            Random rand;
            rand = new Random();
 
            for(int i=0;i<m_data.Length;i++)
            {
                m_data[i] = rand.Next(09);
                for (int j = 0; j < i; j++)
                {
                    if(m_data[i]==m_data[j])
                    {
                        i--;
                    }
                }
 
            }
        }
        void showMsg(String msg)
        {
            Console.WriteLine(msg);
        }
        void showPlay(int[] data)
        {
            Console.WriteLine("스트라이크:" + data[1+ " ,볼:" + data[0]);
        }
        void showGameEnd(Boolean win)
        {
            if(true == win)
            {
                Console.WriteLine("축하합니다");
 
            }
            else
            {
                Console.WriteLine("다음 기회에");
            }
            Console.WriteLine("컴퓨터의 숫자는?");
            for(int i=0;i<m_data.Length;i++)
            {
                Console.WriteLine(m_data[i]);
            }
        }
        int check(int index,int a)
        {
            int b;
 
            b = 0;
            for(int i=0;i<m_data.Length;i++)
            {
                if(m_data[i]==a)
                {
                    if(i==index)
                    {
                        b = 2;
                        break;
                    }
                    else
                    {
                        b = 1;
                    }
                }
            }
            return b;
        }
        void onePlay(int[] result)
        {
            int input;
            int r;
            for(int i=0;i<result.Length;i++)
            {
                result[i] = 0;
            }
            for(int i=0;i<3;i++)
            {
                input = m_Player.input();
                r = check(i, input);
 
                if(2== r)
                {
                    result[1]++;
                }
                else if(1==r)
                {
                    result[0]++;
                }
            }
        }
        void run()
        {
            Boolean win;
            int[] result;
 
            result = new int[2];
            makeData();
 
            win = false;
            for(int i=0;i<10;i++)
            {
                showMsg((i + 1+ "번째 시도");
 
                onePlay(result);
                showPlay(result);
                if(3==result[1])
                {
                    win = false;
                    break;
                }
            }
            showGameEnd(win);
        }
        static void Main(string[] args)
        {
            Program m = new Program();
            m.NumberBaseBall();
            m.run();
 
        }
    }
}
 
cs

완성 한 프로그램 입니다.




바로 숫자야구!

숫자야구가 무었이냐구요?

0~9까지 중복을 허용하지 않는 숫자중에 자신이 예측하는 3개의 숫자를 입력합니다. 입력한 숫자와 컴퓨터가 생성한 숫자가 같으면 스트라이크로

값만 있고 위치가 다르면 볼 로 해서 사용자에게 결과를 알려줍니다. 이 정보로 추측하여 세 숫자와 그 위치까지 맞추면 게임이 끝납니다.

한번의 게임에 총 10번의 시도를 할 수 있습니다.





1.메서드의 값을 전달하는 방법(Call by Value, Call by Reference)

정말정말 중요한 것이 나왔습니다! 아마 신입 프로그래머로 회사에 들어갈때 대부분 물어보는 문제중 하나일 거에요!

값전달과 방식?참조 전달 이라고 하는 것 인데요

Call by Value는 그 메서드 내에서만 값이 바뀌고 그 메서드가 끝나면? 값이 다시 원래대로 돌아옵니다

Call by reference는 메서드 안에서 바뀐 값이 끝까지 계속 영원히 바뀌는 것을 말합니다. 이것은 소스 코드를 보시면서 꼭!!! 이해하세요! 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace CallTest
{
    class Program
    {
        public Program()
        {
 
        }
        void callbyValue(int a)
        {
            a = a * 2;
        }
        void callbyrefTest(int[] data)
        {
            for(int i= 0;i<3;i++)
            {
                data[i] = data[i] * 2;
            }
        }
        void run()
        {
            int[] mydata;
            int a;
 
            a = 3;
            mydata = new int[3];
 
            mydata[0= 1;
            mydata[1= 2;
            mydata[2= 3;
            
            callbyValue(a);
            Console.WriteLine(a);           //그대로 3
 
            callbyrefTest(mydata);         // 1 ,2,3이 2,4,6,으로 바뀌어 있다
            for (int i = 0; i < 3; i++)
            {
                Console.WriteLine(mydata[i]);
            }
            
        }
        static void Main(string[] args)
        {
 
            Program p = new Program();
            p.run();
 
        }
    }
}
 
cs

특히 두번째 Call by Reference로 위 코드에서 run 메서드에서 callbyref메서드를 호출해서 값을 배열로 받는 경우입니다.
그래서 출력도 for문을 이용해서 배열로 했구요!

2. 프로그램을 설게하는 요령

동일한 것을 만들더라도 코드에서 각각 사람들의 개성이 나타납니다. 그래서 코딩을 기술의 영역에서 예술의 영역으로 보는 분들도 계십니다.

이렇게 프로그램을 설계하는데 있어서 좋은말이 있어서 가져옵니다.

첫 번째 기능 스펙을 명확하게 해야 합니다. 어떤 기능이 어떠한 방식으로 구현되어야 하는지를 정의하는 것입니다(이것은 프로그램을 사용하는 사용자의 요구에 따라서 결정됩니다.)

두 번째 재료를 설계해야 하는데 이때 클래스를 설계하고 그 대략적 기능을 정의합니다. 이후 클래스 메서드, 전역변수를 정의합니다.

세 번째 main 메서드에서 설계된 클래스를 이용해서 프로그램을 구현해 봅니다. 이때 두 번째로 돌아가서 설게를 보정합니다.

네 번째 모든 메서드에 대해서 상호관계 인터페이스가 완료되면 각 클래스의 메서드를 구체적으로 구현합니다.


자 이제 가위 바위 보를 해볼까요?

자 다시 문제를 봅시다

플레이어는 (0)가위 (1)바위 (2)보 중에 하나를 내고 컴퓨터도 임의로 하나를 내어서 승패를 결정하는 게임입니다. 입력시 -1 을 입력하면 게임을 종료합니다.

게임이 종료되면 총 게임횟수와 이긴횟수 진횟수 비긴횟수 및 승률을 출력해 줍니다.

저는 이렇게 생각 했습니다.

1. 저는 플레이어에 대해서 클래스를 만들것 입니다. 리턴형으로 제가 낸 -1 ,0,1,2 를 입력받아 리턴하는 메서드를 만들것입니다.

2. 두번째는 컴퓨터 클래스를 만들것 입니다. 랜덤으로 0~2까지 숫자중 하나를 생성해서 리턴하는 매서드를 만들것 입니다.

3.세번째로는 이제 메인 클래스에서 컴퓨터객체 플레이어 객체를 생성 이긴 횟수 진 횟수를 선언 하겠습니다

4.값을 가져오는 메서드, 이겼는지 졌는지 플레이를 보여주는 메서드,게임이 이겼는지 졌는지를 계산하는 메서드,다 끝나고 게임을 보여주는 메서드를 선언하겠습니다.

5.마지막 run 메서드에 -1이 될때까지 하며 -1이 되멸 끝내게끔 하겠습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace RSPcs
{
    class Program
    {
        Computer m_com;
        Player m_player;
        int m_total;
        int m_win;
        int m_lost;
        public Program()
        {
            m_com = new Computer();
            m_player = new Player();
            m_total = 0;
            m_win = 0;
            m_lost = 0;
        }
        String getValue(int a)
        {
            String msg;
            if(0==a)
            {
                msg = "가위";
            }
            else if(1==a)
            {
                msg = "바위";
            }
            else
            {
                msg = "보";
            }
            return msg;
        }
        void showPlay(int com,int p,int result)
        {
            String msg;
 
            switch(result)
            {
                case 0:
                    msg = "무승부";
                    break;
                case 1:
                    msg = "이겼습니다";
                    break;
                default:
                    msg = "졌습니다";
                    break;
            }
            Console.WriteLine("컴퓨터 " + getValue(com) + "플레이어 " + getValue(p));
            Console.WriteLine("결과 " + msg);
        }
        void showEndGame()
        {
            int equal;
            float rate;
 
            equal = m_total - (m_win + m_lost);
            rate = (float)m_win / m_total;
 
            Console.WriteLine("-------------");
            Console.WriteLine(" 총 게임수"+m_total);
            Console.WriteLine(" 이긴수"+m_win);
            Console.WriteLine(" 비긴수"+equal);
            Console.WriteLine(" 진수"+m_lost);
            Console.WriteLine(" 승률"+rate);
            Console.WriteLine("-------------");
 
        }
        int checkGame(int com,int my)
        {
            int a;
 
            a = 0;
            m_total++;
 
            if(com == my)
            {
                a = 0;
            }
            else if(0 == com && 1 == my)
            {
                a = 1;
                m_win++;
            }
            else if (0 == com && 2 == my)
            {
                a = 2;
                m_lost++;
            }
            else if (1 == com && 0 == my)
            {
                a = 2;
                m_win++;
            }
            else if (1 == com && 2 == my)
            {
                a = 1;
                m_win++;
            }
            else if (2 == com && 0 == my)
            {
                a = 1;
                m_win++;
            }
            else if (2 == com && 1 == my)
            {
                a = 2;
                m_lost++;
            }
            return a;
        }
        void run()
        {
            int com;
            int p;
            int result;
 
            while(true)
            {
                p = m_player.input();
                com = m_com.go();
 
                if(-1==p)
                {
                    break;
                }
                result = checkGame(com, p);
                showPlay(com, p, result);
            }
            showEndGame();
        }
        static void Main(string[] args)
        {
            Program m = new Program();
            //m.Program();
            m.run();
        }
    }
}
 
cs


결과 화면





+ Recent posts