티스토리 뷰
[1]매칭게임
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Threading;
namespace A176_WPFMatchingGame
{
public partial class MainWindow : Window
{
Button first;
Button second;
DispatcherTimer myTimer = new DispatcherTimer();
int matched = 0;
int[] rnd = new int[16]; // 랜덤 숫자가 중복되는지 체크
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 c = new Button();
c.Background = Brushes.White;
c.Margin = new Thickness(10);
c.Content = MakeImage("../../Images/check.png");
c.Tag = TagSet(); // 이 문장이 중요, 그림의 인덱스
c.Click += C_Click;
board.Children.Add(c);
}
}
private void C_Click(object sender, RoutedEventArgs e)
{
Button btn = sender as Button;
string[] icon = { "딸기", "레몬", "모과", "배", "사과", "수박", "파인애플", "포도" };
btn.Content = MakeImage("../../Images/" + icon[(int)btn.Tag] + ".png");
// 두개의 버튼을 순서대로 눌렀을 때 처리
if (first == null) // 지금 누른 버튼이 첫번째 버튼
{
first = btn;
return;
}
second = btn;
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)
{
NewGame();
}
else
Close();
}
}
else // 매치가 안되었을 때는 다시 덮어주어야 한다
{
myTimer.Start();
}
}
private void NewGame()
{
for (int i = 0; i < 16; i++)
rnd[i] = 0;
board.Children.Clear();
BoardSet();
matched = 0;
}
private int TagSet()
{
int i;
Random r = new Random();
while (true)
{
i = r.Next(16); // 0~15까지
if (rnd[i] == 0)
{
rnd[i] = 1;
break;
}
}
return i % 8; // 태그는 0~7까지, 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;
}
}
}
WPF프로젝트 매칭게임을 작성해보았다.
Button first;
Button second;
DispatcherTimer myTimer = new DispatcherTimer();
int matched = 0;
int[] rnd = new int[16]; // 랜덤 숫자가 중복되는지 체크
전역변수로 버튼 두 개와 타이머, 정수형 matched와 정수형배열 rnd를 선언 해주었다.
BoardSet();
myTimer.Interval = new TimeSpan(0, 0, 0, 0, 750);
myTimer.Tick += MyTimer_Tick;
mainwindow에서는 추후에 만들어줄 BoardSet 함수를 실행해주고 타이머의 인터벌을 750밀리초(0.75)초로 설정해주었다.
그리고 타이머의 이벤트함수인 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;
}
타이머의 Tick 이벤트 함수이다.
함수가 작동하면 timer를 정지한 후
이전에 선언한 button인 first와 second의 내용을 추후에 작성할 MakeImage함수를 사용하여 작성해준다.
"../"은 상위폴더로 이동하라는 상대경로 명령어이다.
그 후 first와 second를 null로 바꿔준다.
private void BoardSet()
{
for (int i = 0; i < 16; i++)
{
Button c = new Button();
c.Background = Brushes.White;
c.Margin = new Thickness(10);
c.Content = MakeImage("../../Images/check.png");
c.Tag = TagSet(); // 이 문장이 중요, 그림의 인덱스
c.Click += C_Click;
board.Children.Add(c);
}
}
보드를 세팅해주는 BoardSet함수이다.
16번의 반복안에
버튼 C를 만들어 하얀색으로 , 여백을 10의 굵기로 ,내용은 MakeImage함수를 사용하여 설정한 후
tag를 Tagset함수를 사용하여 설정하여 해시테이블을 만드는 것 처럼 해준다.
C의 이벤트인 Click에 추후에 만들 C_Click함수를 더해준다.
board의 children으로 버튼 c를 추가해준다.
private void C_Click(object sender, RoutedEventArgs e)
{
Button btn = sender as Button;
string[] icon = { "딸기", "레몬", "모과", "배", "사과", "수박", "파인애플", "포도" };
btn.Content = MakeImage("../../Images/" + icon[(int)btn.Tag] + ".png");
// 두개의 버튼을 순서대로 눌렀을 때 처리
if (first == null) // 지금 누른 버튼이 첫번째 버튼
{
first = btn;
return;
}
second = btn;
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)
{
NewGame();
}
else
Close();
}
}
else // 매치가 안되었을 때는 다시 덮어주어야 한다
{
myTimer.Start();
}
}
주요내용인 C_Click함수이다.
버튼이 클릭되면 작동하는 이벤트함수이며
버튼이 클릭되면 sender로 데이터를 받아 선언한 btn에 값으로 설정해준다.
string배열 icon을 설정하여 이미지의 name들을 인자로 저장해준다.
btn의 content를 MakeImage함수를 사용하는데 추후에 사용할 Tag함수를 사용해 만들어준 태그를 기준으로
(Tag는 16개의 이미지들 중 8쌍으로 이루어지며 0~7까지 있다.) icon배열의 인덱스를 참조하여 값을 뽑아와준다.
first=null이면 버튼을 뒤집는 것 처럼 btn을 대입하여 이미지를 띄워준 후 리턴해준다.
현재 타이머는 멈춰있고 first에는 이전 btn의 값이 들어있으므로 first!=null이다.
고로 if를 지나쳐 밑의 second=btn까지 오게된다. 그러므로 first와 second의 내용이 모두 작성되었다.
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)
{
NewGame();
}
else
Close();
}
}
else // 매치가 안되었을 때는 다시 덮어주어야 한다
{
myTimer.Start();
}
first의 tag가 secondd와 일치한다면
first와 second를 모두 null로 바꾼 뒤
matched에 2만큼 더해준다.
matched가 16이상이 되어 8쌍 이상이 오픈되면 (전체칸이 오픈되면) yes와 no버튼을 가지고 성공 메세지를 띄우는 메세지박스를
띄운 후 이 버튼의 값을 저장한 res의 값이 yes라면 추후에 작성할 newgame함수를 사용하여 새로 게임을 시작한다.
아니라면 close해준다.
그리고 다음은 first와 second의 tag가 다르다면 타이머를 시작하여 다시 Tick함수를 실행해준다.
private void NewGame()
{
for (int i = 0; i < 16; i++)
rnd[i] = 0;
board.Children.Clear();
BoardSet();
matched = 0;
}
newgame함수는 게임을 다시 시작하는 함수이다.
16번을 반복하여 tag생성에 필요한 rnd배열을 초기화해준 후
board의 children을 모두 clear해준다.
다음 board를 다시 세팅해주고
matched를 0으로 만들어 완전 초기상태로 돌아간다.
private int TagSet()
{
int i;
Random r = new Random();
while (true)
{
i = r.Next(16); // 0~15까지
if (rnd[i] == 0)
{
rnd[i] = 1;
break;
}
}
return i % 8; // 태그는 0~7까지, 8개의 그림을 표시
}
TagSet함수이다.
int형 i와
random class r을 생성해준다.
while반복문을 돌려 i에 0~15의 값을 넣어준다.
rnd는 전역변수 선언으로 현재 모든 칸이 0으로 설정되어있는 상태이다.
rnd[랜덤으로 생성한 숫자]==0이면
1로 바꿔주고(그래프탐색의 visited설정과 비슷하다)
루프를 break하여 i%8을 리턴한다. (at-1=idx의 특성을 잘 활용한 문장이다)
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;
}
마지막으로 MakeImage함수이다.
bitmapimage클래스의 설명에 따르면
xaml을 사용하는 이미지 로딩에 최적화된 구체화된 bitmapsource를 제공한다고 나와있다.
BitmapImage클래스의 bi를 생성해주고
BeginInit함수를 사용하여 비트맵이미지의 초기화의 시작신호를 보낸다.
bi의 Urisource를 설정해주는데 Uri클래스의 Uri구조체를 선언하여
string type url과 url의 속성을 relative로 부여해준다.
EndInit함수를 사용하여 초기화의 끝 신호를 보낸다.
image클래스의 myimage를 선언해주고
margin을 10으로
꽉 차게 늘려준 뒤
이미지의 source를 방금 받아준 bi의 값으로 설정해준다.
그 후 myImage를 return한다.
잘 실행된다.
감사합니다.
'VS-02분반수업' 카테고리의 다른 글
VP(22-06-08) (0) | 2022.06.09 |
---|---|
VP(22-06-03) (0) | 2022.06.08 |
VP(22-05-27) (0) | 2022.05.30 |
VP(22-05-25) (0) | 2022.05.25 |
VP(22-05-20) (0) | 2022.05.24 |