그림맞추기 게임을 만들어보자!
알고리즘
1. 16개의 버튼을 만들어서, Board에 넣는다.
2. 랜덤하게 각 버튼에 숫자(0~7)을 배당한다.
3. 이 숫자를 Button.Tag에 저장한다.
4. 뒤집한 그림으로 표시한다.
int[] rnd = new int[16]; // TagSet()에서 사용할 배열
DispatcherTimer myTimer = new DispatcherTimer();
총 16개의 그림을 비교할 것이니 배열크기를 16으로 정한다.
그림 하나를 선택 후, 다음 그림이 열릴때 너무 빨리 닫히므로 두번째 그림을 확인할 수 없게된다. 그래서 WPF의 시간을 사용하는 클래스인 DispatcherTime 객체를 선언한다.
public MainWindow()
{
InitializeComponent();
BoardSet();
myTimer.Interval = new TimeSpan(0, 0, 0, 0, 750);
myTimer.Tick += MyTimer_Tick;
}
private void MyTimer_Tick(object sender, EventArgs e)
{
myTimer.Stop();
first.Content = MakeImage("../../images/check.png");
second.Content = MakeImage("../../images/check.png");
first = null;
second = null;
}
타이머 설정 및 이미지 불러오기. 시간은 750ms = 0.75초
private void BoardSet()
{
for (int i = 0; i < 16; i++)
{
Button btn = new Button();
btn.Background = Brushes.White;
btn.Margin = new Thickness(10);
btn.Tag = TagSet(); // 랜덤하고 각 숫자가 2개씩
btn.Content = MakeImage("../../images/check.png"); // 그림으로 대체될 것임
// 버튼의 클릭 이벤트 설정
btn.Click += Btn_Click;
board.Children.Add(btn);
}
}
16개의 배열 처럼 16칸의 버튼을 만들어준다.
TagSet() 함수 사용 ( 후술 ) 랜덤하고 각각의 숫자 2개씩 지정하기 위함.
private void Btn_Click(object sender, RoutedEventArgs e)
{
Button btn = sender as Button;
string[] icon = {"딸기", "레몬", "모과", "배",
"사과", "수박", "파인애플", "포도"};
string fruitName = icon[(int)btn.Tag];
if (first == null) // 누른 버튼이 첫번째 버튼이라면
{
first = btn;
btn.Content = MakeImage("../../images/" + fruitName + ".png");
return;
}
else if (second == null) // 지금 누른 버튼이 두번째 버튼이라면
{
second = btn;
btn.Content = MakeImage("../../images/" + fruitName + ".png");
}
else
{
return;
}
// 비교하기
if ((int)first.Tag == (int)second.Tag) // 같다
{
first = null;
second = null;
matched += 2; // 매칭된 버튼의 개수
if (matched >= 16)
{
MessageBoxResult res =
MessageBox.Show("성공! 다시 하겠습니까?", "Success!",
MessageBoxButton.YesNo);
if (res == MessageBoxResult.Yes) // 초기화
{
RndReset();
BoardReset();
BoardSet();
matched = 0;
}
else
this.Close();
}
}
else // 같지 않다면
{
myTimer.Start();
}
}
버튼 클릭시 메소드.
1. 첫번째 버튼 눌렀을 때 사진 불러오기
2. 두번째 버튼 눌렀을 때 사진 불러오기
3. 각각 비교하기.
4. if문을 통해 모두 다 match 성공했다면 MessageBox 띄워서 재시작 or 끝내기
+else에서는 타이머 시작을 통해 그림 덮기
private void BoardReset()
{
board.Children.Clear();
}
private void RndReset()
{
for (int i = 0; i < 16; i++)
rnd[i] = 0;
}
Button first = null;
Button second = null;
private int matched;
// 0~7까지의 그림 종류에 해당하는 번호
// 각 번호는 2개씩 할당되어야 함
private object TagSet()
{
Random r = new Random();
while (true)
{
int n = r.Next(16); // 0~15까지의 숫자
if (rnd[n] == 0) // 처음 나온 숫자인지
{
rnd[n] = 1;
return n % 8;
}
}
}
BoardReset() 및 RndReset() 구현
보드 클리어. 랜덤 값 저장
TagSet()
- 랜덤 값으로 8(0~7)개의 수 총 16개의 수 할당.
private Image MakeImage(string v)
{
BitmapImage bi = new BitmapImage();
bi.BeginInit();
bi.UriSource = new Uri(v, UriKind.Relative);
bi.EndInit();
Image myImage = new Image();
myImage.Margin = new Thickness(10);
myImage.Stretch = Stretch.Fill;
myImage.Source = bi;
return myImage;
}
BitmapImage 형 객체 선언 및 이미지를 만들어서 이미지 리턴.
public partial class MainWindow : Window
{
int[] rnd = new int[16]; // TagSet()에서 사용할 배열
DispatcherTimer myTimer = new DispatcherTimer();
public MainWindow()
{
InitializeComponent();
BoardSet();
myTimer.Interval = new TimeSpan(0, 0, 0, 0, 750);
myTimer.Tick += MyTimer_Tick;
}
private void MyTimer_Tick(object sender, EventArgs e)
{
myTimer.Stop();
first.Content = MakeImage("../../images/check.png");
second.Content = MakeImage("../../images/check.png");
first = null;
second = null;
}
private void BoardSet()
{
for (int i = 0; i < 16; i++)
{
Button btn = new Button();
btn.Background = Brushes.White;
btn.Margin = new Thickness(10);
btn.Tag = TagSet(); // 랜덤하고 각 숫자가 2개씩
btn.Content = MakeImage("../../images/check.png"); // 그림으로 대체될 것임
// 버튼의 클릭 이벤트 설정
btn.Click += Btn_Click;
board.Children.Add(btn);
}
}
private void Btn_Click(object sender, RoutedEventArgs e)
{
Button btn = sender as Button;
string[] icon = {"딸기", "레몬", "모과", "배",
"사과", "수박", "파인애플", "포도"};
string fruitName = icon[(int)btn.Tag];
if (first == null) // 누른 버튼이 첫번째 버튼이라면
{
first = btn;
btn.Content = MakeImage("../../images/" + fruitName + ".png");
return;
}
else if (second == null) // 지금 누른 버튼이 두번째 버튼이라면
{
second = btn;
btn.Content = MakeImage("../../images/" + fruitName + ".png");
}
else
{
return;
}
// 비교하기
if ((int)first.Tag == (int)second.Tag) // 같다
{
first = null;
second = null;
matched += 2; // 매칭된 버튼의 개수
if (matched >= 16)
{
MessageBoxResult res =
MessageBox.Show("성공! 다시 하겠습니까?", "Success!",
MessageBoxButton.YesNo);
if (res == MessageBoxResult.Yes) // 초기화
{
RndReset();
BoardReset();
BoardSet();
matched = 0;
}
else
this.Close();
}
}
else // 같지 않다면
{
myTimer.Start();
}
}
private void BoardReset()
{
board.Children.Clear();
}
private void RndReset()
{
for (int i = 0; i < 16; i++)
rnd[i] = 0;
}
Button first = null;
Button second = null;
private int matched;
// 0~7까지의 그림 종류에 해당하는 번호
// 각 번호는 2개씩 할당되어야 함
private object TagSet()
{
Random r = new Random();
while (true)
{
int n = r.Next(16); // 0~15까지의 숫자
if (rnd[n] == 0) // 처음 나온 숫자인지
{
rnd[n] = 1;
return n % 8;
}
}
}
private Image MakeImage(string v)
{
BitmapImage bi = new BitmapImage();
bi.BeginInit();
bi.UriSource = new Uri(v, UriKind.Relative);
bi.EndInit();
Image myImage = new Image();
myImage.Margin = new Thickness(10);
myImage.Stretch = Stretch.Fill;
myImage.Source = bi;
return myImage;
}
}
전체 소스코드
'C#' 카테고리의 다른 글
048_WPF_Clock_C# (0) | 2022.06.12 |
---|---|
047_Form_Clock_C# (0) | 2022.06.09 |
045_ECG,PPG(Gragh Control) (0) | 2022.06.09 |
044_Graph (0) | 2022.06.09 |
043_TwoChart (0) | 2022.06.09 |