C#의 기초 조건문과 반복문, 매서드에 대해서 배워보도록 한다
조건문과 반복문
조건문 (Conditional) |
● 조건에 따라 실행이 달라지게 할 때 사용하는 문장 ● 조건문은 주어진 조건식의 결과에 따라 프로그램의 제어 흐름을 변경하는 제어문 |
<조건문>
◆ 조건식(논리형자료)의 true, false에 따라 실행할 블록을 결정하는 조건문
1) if 문
● if 문은 조건식의 결과에 따라 실행 여부를 결정하는 조건문
if (true) // 조건이 true인 경우 바로 아래의 블록이 실행됨
{
Console.WriteLine("실행되는 블록");
}
2) else 문
● else 문은 if 문에서 조건식이 거짓일 경우 실행할 코드를 지정하는 조건문
else // 조건식의 조건에 부합하지 않은 조건일 경우 else 아래의 블록이 실행됨
{
Console.WriteLine("실행되는 블록");
}
3) else if 문
● else if 문은 if 문의 조건식이 거짓일 때, 새로운 조건식을 사용하여 실행 여부를 결정하는 조건문입니다.
if (조건식1)
{
// 조건식1이 참일 경우 실행할 코드
}
else if (조건식2)
{
// 조건식2가 참일 경우 실행할 코드
}
else
{
// 모든 조건식이 거짓일 경우 실행할 코드
}
● 예제
<가위, 바위, 보 조건문 응용>
string command = "가위";
if (command == "가위")
{
Console.WriteLine("가위를 냅니다");
}
else
{
if (command == "바위")
{
Console.WriteLine("바위를 냅니다");
}
else
{
Console.WriteLine("보를 냅니다");
}
}
// else if 키워드가 있는 것이 아닌 else + if 가능
if (command == "가위")
{
Console.WriteLine("가위를 냅니다");
}
else if (command == "바위")
{
Console.WriteLine("바위를 냅니다");
}
else if (command == "보")
{
Console.WriteLine("보를 냅니다");
}
else
{
Console.WriteLine("가위 바위 보가 아닙니다.");
}
4) switch 문
● 조건값에 따라 실행할 시작지점을 결정하는 조건문
switch (변수나 식)
{
//case문을 사용하여 변수나 식의 결과에 따라 실행할 코드를 지정
case 값1:
// 값1이 나온 경우 실행되는 코드
break;
case 값2:
// 값2가 나온 경우 실행되는 코드
break;
// ...
default:
// 모든 case문에 해당하지 않는 경우 실행되는 코드
break;
}
● 예제
<이동키 구성(case 중첩)>
char key = 'w';
switch (key)
{
case 'w':
case 'W':
case 'ㅈ':
Console.WriteLine("위쪽으로 이동");
break;
case 'a':
case 'A':
case 'ㅁ':
Console.WriteLine("왼쪽으로 이동");
break;
case 's':
case 'S':
case 'ㄴ':
Console.WriteLine("아래쪽으로 이동");
break;
case 'd':
case 'D':
case 'ㅇ':
Console.WriteLine("오른쪽으로 이동");
break;
default:
Console.WriteLine("이동하지 않음");
break;
}
5) 삼항연상자
● if 문의 간단한 형태로, 조건식의 결과에 따라 두 값을 선택하는 연산자임
(조건식) ? 참일 경우 값 : 거짓일 경우 값;
● 예제
반복문 (Iteration) |
● 일련의 명령문을 반복해서 실행하는 제어문 |
1) for 문
● 초기화, 조건식, 증감연산 으로 구성된 반복문
● 정해진 횟수를 만족할때 까지 진행함
for (초기식; 조건식; 증감식)
{
// 조건식이 참인 경우 실행되는 코드
}
● 예제
2) while 문
● 조건식의 true, false에 따라 블록을 반복하는 반복문
● 해당 조건을 달성할때 까지 계속함 (조건이 만족할때까지 무한가능)
while (조건식)
{
// 조건식이 참인 경우 실행되는 코드
}
● 예제
3) do-while 문
● 블록을 한번 실행 후 조건식의 true, false에 따라 블록을 반복하는 반복문
do
{
// 조건식이 참인 경우 실행되는 코드
}
while (조건식);
● 예제
4) foreach 문
● 반복가능한 데이터집합의 처음부터 끝까지 반복하는 반복문
foreach (자료형 변수 in 배열 또는 컬렉션)
{
// 배열 또는 컬렉션의 모든 요소에 대해 반복적으로 실행되는 코드
}
● 예제
1) Break & Continue 문
● 프로그램의 순차적인 실행 중 다른 문으로 제어를 전송
<Break>
// <break> : 그만, 탈출, 안함
// 가장 가까운 바깥쪽 반복문 또는 switch 조건문을 종료
int primeNumber = 19;
for (int i = 2; i < primeNumber; i++)
{
if (primeNumber % i == 0)
{
Console.WriteLine(primeNumber + "는 소수가 아님");
break;
}
}
<Continue >
// <continue> : 생략, 건너뛰기
// 가장 가까운 반복문의 처음으로 이동
for (int i = 0; i < 10; i++)
{
if (i % 2 == 0)
{
Console.WriteLine(i + "는 홀수가 아님");
continue;
}
}
//홀수들만 할 작업
Console.WriteLine("홀수 확인");
배열 (Array) |
● 동일한 자료형의 값들이 연속적으로 저장되는 자료 구조 ● 배열의 처음 요소의 인덱스는 0부터 시작함 ● 인덱스를 통하여 개개의 배열요소(Element)에 접근할 수 있음 ● 선언된 크기만큼의 공간을 메모리에 할당받음 |
1) 1차원 배열
● 동일한 데이터 유형을 가지는 데이터 요소들을 한 번에 모아서 다룰 수 있는 구조
// 배열 선언
데이터_유형[] 배열_이름;
// 배열 초기화
배열_이름 = new 데이터_유형[크기];
// 배열을 한 줄로 선언 및 초기화
데이터_유형[] 배열_이름 = new 데이터_유형[크기];
// 배열 요소에 접근
배열_이름[인덱스] = 값;
값 = 배열_이름[인덱스];
● 예제
2) 다차원 배열
● 여러 개의 배열을 하나로 묶어 놓은 배열
● 행과 열로 이루어진 표 형태와 같은 구조
● 2차원, 3차원 등의 형태의 배열을 의미
● C#에서는 다차원 배열을 선언할 때 각 차원의 크기를 지정하여 생성함
● 예제
컬렉션(Collection) |
● 자료를 모아 놓은 데이터 구조를 의미함 ● 컬렉션은 배열과 비슷한 자료 구조 ● 배열과는 다르게 크기가 가변적 ● C#에서는 다양한 종류의 컬렉션을 제공 ● 사용하기 위해서는 System.Collections.Generic 네임스페이스를 추가 |
1) List
● List는 가변적인 크기를 갖는 배열
● List를 생성할 때는 List에 담을 자료형을 지정
2) Dictionary
● 딕셔너리(Dictionary)는 키와 값으로 구성된 데이터를 저장
● 딕셔너리는 중복된 키를 가질 수 없으며, 키와 값의 쌍을 이루어 데이터를 저장
3) Stack
● Stack은 후입선출(LIFO) 구조를 가진 자료 구조
4) Queue
● Queue는 선입선출(FIFO) 구조를 가진 자료 구조
5) HashSet
● HashSet은 중복되지 않은 요소들로 이루어진 집합
위와 같은 자료구조들은 https://passingwolf.tistory.com/11 해당 링크 또는 '개발관련공부자료' 카테고리에 '자료구조' 게시물에 들어가면 더 자세히 지필해두었으니 CS적으로 더 궁금하다면 참고하길 바람
메서드 선언과 호출
메서드(Method) |
● 메서드(Method)는 일련의 코드 블록으로, 특정한 작업을 수행하기 위해 사용되는 독립적인 기능 단위임 ● 코드의 재사용성과 모듈화를 위해 사용되며, 필요할 때 호출하여 실행됨 |
메서드의 역할과 중요성 |
● 코드의 재사용성: 메서드를 사용하면 동일한 작업을 반복해서 구현하지 않아도 됩니다. 필요할 때 메서드를 호출하여 작업을 수행할 수 있음 ● 모듈화: 메서드를 사용하여 코드를 작은 단위로 분리하고 관리할 수 있습니다. 각 메서드는 특정한 기능을 수행하므로 코드의 구조가 더욱 명확해짐 ● 가독성과 유지보수성: 메서드를 사용하면 코드가 간결해지고 가독성이 좋아집니다. 또한, 코드 수정이 필요한 경우 해당 메서드만 수정하면 되므로 유지보수가 용이해짐 ● 코드의 중복 제거: 반복적인 작업을 메서드로 묶어서 사용하면 코드 중복을 방지할 수 있음 ● 코드의 추상화: 메서드를 통해 작업 단위를 추상화하고, 메서드 이름을 통해 해당 작업이 어떤 역할을 하는지 파악할 수 있음 |
1) 메서드의 구조와 문법
[접근 제한자] [리턴 타입] [메서드 이름]([매개변수])
{
// 메서드 실행 코드
}
● 접근 제한자(Access Modifier): 메서드에 접근할 수 있는 범위를 지정합니다. 주로 public, private, protected 등을 사용함
● 리턴 타입(Return Type): 메서드가 반환하는 값의 데이터 타입을 지정합니다. 반환 값이 없을 경우 void를 사용함
● 매개변수(Parameters): 메서드에 전달되는 입력 값으로, 필요한 경우 0개 이상의 매개변수를 정의할 수 있음
● 메서드 실행에 코드(Method Body): 중괄호({}) 안에 메서드가 수행하는 작업을 구현하는 코드를 작성함
● 메서드 이름(Method Name): 메서드를 호출하기 위해 사용하는 이름입니다. 호출할 때 이 이름을 사용함
2) 메서드 호출 방법
● 메서드를 호출하기 위해서는 메서드 이름과 필요한 매개변수를 전달하여 호출
● 메서드 호출은 다음과 같은 형식으로 이뤄짐
[메서드 이름]([전달할 매개변수]);
● 예를 들어, 위 예제의 AddNumbers라는 이름의 메서드를 호출하고자 할 때는 다음과 같이 호출함
AddNumbers(10, 20);
3) 매개변수
● 매개변수는 메서드에 전달되는 입력 값으로, 메서드 내에서 이 값을 활용하여 원하는 작업을 수행할 수 있음
● 매개변수는 메서드의 선언부에 정의되며, 필요한 경우 0개 이상의 매개변수를 정의할 수 있음
● 매개변수는 메서드 호출 시 전달되는 값에 따라 동적으로 결정되며, 호출 시에는 해당 매개변수의 값을 전달해야 함
● 예제
4) 반환값
● 반환값은 메서드가 수행한 작업의 결과를 호출자에게 반환하는 값
● 반환값은 메서드의 리턴 타입에 지정되며, 해당 타입의 값을 반환해야함
● 메서드 내에서 계산, 조작, 처리한 결과 등을 반환값으로 사용할 수 있음
● 예제
int AddNumbers(int a, int b)
{
int sum = a + b;
return sum;
}
// 메서드 호출 및 반환값 사용
int result = AddNumbers(10, 20);
Console.WriteLine("Sum: " + result);
<void 형식과 반환값이 없는 메서드>
void PrintMessage(string message)
{
Console.WriteLine("Message: " + message);
}
// 메서드 호출
PrintMessage("Hello, World!");
5) 메서드 오버로딩
● 같은 이름의 함수를 매개변수를 달리하여 다른 함수로 재정의하는 기술
● 함수명은 이름이 같더라도 매개변수만 틀리면 동작이 가능함
● 오버라이딩도 비슷한 기술이지만 성격이 다름
● 예제
static int Minus(int left, int right) { return left - right; }
static float Minus(float left, float right) { return left - right; }
static double Minus(double left, double right) { return left - right; }
static void Main5()
{
Console.WriteLine(Minus(5, 3)); // Minus(int, int) 가 호출됨
Console.WriteLine(Minus(5.0f, 3.0f)); // Minus(float, float) 가 호출됨
Console.WriteLine(Minus(5.0d, 3.0d)); // Minus(double, double) 가 호출됨
}
6) 재귀 호출
● 재귀 호출은 메서드가 자기 자신을 호출하는 것을 의미함
● 재귀 호출은 문제를 작은 부분으로 분할하여 해결하는 방법 중 하나로, 작은 부분의 해결 방법이 큰 문제의 해결 방법과 동일한 구조를 갖고 있는 경우에 적합함
● 재귀 호출은 호출 스택에 호출된 메서드의 정보를 순차적으로 쌓고, 메서드가 반환되면서 스택에서 순차적으로 제거되는 방식으로 동작함
● 예제
static void Func4_1()
{ // (1) 6
Console.WriteLine("Func4_1"); // (2) 7
} // (3) 8
static void Func4_2()
{ // (4) 3
Console.WriteLine("Func4_2"); // (5) 4
Func4_1(); // (6) 5
} // (7) 9
static void Main4()
{
Console.WriteLine("Main4"); // (8) 1
Func4_2(); // (9) 2
} // (10) 10
static void Main(string[] args)
{
Main4();
}
// 호출 순서 : (8) -> (9) -> (4) -> (5) -> (6) -> (1) -> (2) -> (3) -> (7) -> (10)
구조체 |
● 여러 개의 데이터를 묶어서 하나의 사용자 정의 형식으로 만들기 위한 방법임 ● 구조체는 값 형식(Value Type)으로 분류되며, 데이터를 저장하고 필요한 기능을 제공할 수 있음 ● 구조체는 struct 키워드를 사용하여 선언함 ● 구조체의 멤버는 변수와 메서드로 구성될 수 있음 |
struct Person
{
public string Name;
public int Age;
public void PrintInfo()
{
Console.WriteLine($"Name: {Name}, Age: {Age}");
}
}
1) 구조체 사용
● 구조체는 변수를 선언하여 사용할 수 있음
● 구조체의 멤버에는 접근할 때 . 연산자를 사용합니다.
Person person1;
person1.Name = "John";
person1.Age = 25;
person1.PrintInfo();
금일 배운 내용들을 포함한 과제 수행 '틱택토'게임 만들기
해당 틱택토게임에는 치명적인점이 있음
1. 컴퓨터가 마커한 곳은 플레이어가 찍기 전까지 Draw가 반영안됨(텍스트로 컴퓨터가 마커한곳 알려줌)
2. 마지막 마커한게 플레이어인지 컴퓨터인지 정하는 로직을 수정하지 않음
internal class Program
{
// 플레이어의 마크를 기억할 목적의 배열
static char[] drawMark = { '1', '2', '3', '4', '5', '6', '7', '8', '9' };
private const char O = 'O';
private const char X = 'X';
// 현재 플레이 중인 플레이어 확인 목적의 변수
static int playerTurn=1;
static int computerTrun;
// 진행 중인 턴을 확인 목적의 변수
static int turnCount = 1;
// 플레이어의 입력을 받아 추후에 배열 값을 수정해주기 위한 변수
static int playerInput = 0;
// 출력할 메시지 플래그를 담당할 변수
static int warningMessage = 0;
// 게임 상태 플래그를 담당할 변수
static int isGameOver = 2;
static int turn = new Random().Next(0, 2);// 플레이어의 차례를 랜덤으로 결정
static void Main(string[] args)
{
do // do ~ while() 문을 사용해 먼저 한 번 실행 후에 조건 비교하도록 하기
{
// 게임 시작 전 Console 창을 Clear하고 간단한 설명과 플레이어 차례 보여주기
Console.Clear();
// 플레이어의 차례에 따라 출력 메시지 변경
if (playerTurn == turn)
{
computerTrun = 2;
Console.WriteLine("플레이어의 차례입니다.\n");
Console.WriteLine("플레이어: O 와 컴퓨터: X\n");
}
else
{
computerTrun = 1;
Console.WriteLine("컴퓨터의 차례입니다.\n");
Console.WriteLine("컴퓨터: O 와 플레이어: X\n");
}
// 3 x 3 표 그리기
DrawPanel();
// warningMessage를 통해 출력할 메시지 변경
switch (warningMessage)
{
case 1: // 이미 마커가 위치한 곳에 마커를 두려고 할 경우
Console.WriteLine("# 이미 마커가 위치하고 있습니다, 다른 위치를 골라주세요!\n");
break;
case 2: // 1 ~ 9 사이의 값을 입력하지 않은 경우
Console.WriteLine("# 잘못된 위치입니다, 다른 위치를 골라주세요!\n");
break;
}
int computerDraw = new Random().Next(0, 8);
Console.WriteLine($"[DEBUG] 컴퓨터가 시도하는 위치: {computerDraw + 1}, 현재 마커: {drawMark[computerDraw]}");
while (drawMark[computerDraw] == 'O' || drawMark[computerDraw] == 'X')
{
Console.WriteLine($"[DEBUG] 위치 {computerDraw + 1}는 이미 마커({drawMark[computerDraw]})가 있습니다. 다른 위치를 선택합니다.");
computerDraw = new Random().Next(0, 8);
Console.WriteLine($"[DEBUG] 컴퓨터가 새로 시도하는 위치: {computerDraw + 1}, 현재 마커: {drawMark[computerDraw]}");
}
if (playerTurn == turn)
{
playerInput = int.Parse(Console.ReadLine());
DrawMarkerOnPanelPlayer();
DrawMarkerOnPanelComputer(computerDraw);
}
else
{
DrawMarkerOnPanelComputer(computerDraw);
playerInput = int.Parse(Console.ReadLine());
DrawMarkerOnPanelPlayer();
}
// 줄이 완성되었는지 확인
IsGameOver();
}
while (isGameOver == 2);
// 게임 종료 후 승자 표시 패널 띄우기
DrawEndPanel();
}
// 3 x 3 표 그리기
static void DrawPanel()
{
Console.WriteLine(" | | ");
Console.WriteLine(" {0} | {1} | {2} ", drawMark[0], drawMark[1], drawMark[2]);
Console.WriteLine("_____|_____|______");
Console.WriteLine(" | | ");
Console.WriteLine(" {0} | {1} | {2} ", drawMark[3], drawMark[4], drawMark[5]);
Console.WriteLine("_____|_____|______");
Console.WriteLine(" | | ");
Console.WriteLine(" {0} | {1} | {2} ", drawMark[6], drawMark[7], drawMark[8]);
Console.WriteLine(" | | \n");
}
static void DrawMarkerOnPanelComputer(int draw)
{
if (0 <= draw && draw <= 8)
{
// 해당 위치의 drawCheck에 값이 들어있지 않은 경우
if ((drawMark[draw] != 79) && (drawMark[draw] != 88))
{
// 마커다운
if (computerTrun == 2)
{
drawMark[draw] = X; // O로 마커다운
}
else
{
drawMark[draw] = O; // X로 마커다운
}
// turnCount + 1
turnCount++;
// warningMessage 끄기
warningMessage = 0;
// playerTurn 조정
computerTrun = (computerTrun == 2) ? 1 : 2;
}
else
{
// 이미 마커가 위치한 곳에 마커를 두려고 할 경우
warningMessage = 1;
}
}
else
{
// 1 ~ 9 사이의 값을 입력하지 않은 경우
warningMessage = 2;
}
}
static void DrawMarkerOnPanelPlayer()
{
// Input 값이 1 ~ 9 사이 값인 경우
if (1 <= playerInput && playerInput <= 9)
{
// 해당 위치의 drawCheck에 값이 들어있지 않은 경우
if ((drawMark[playerInput - 1] != 79) && (drawMark[playerInput - 1] != 88))
{
// 마커다운
if (playerTurn == turn)
{
drawMark[playerInput - 1] = O; // O로 마커다운
}
else
{
drawMark[playerInput - 1] = X; // X로 마커다운
}
// turnCount + 1
turnCount++;
// warningMessage 끄기
warningMessage = 0;
// playerTurn 조정
playerTurn = (playerTurn == 1) ? 2 : 1;
}
else
{
// 이미 마커가 위치한 곳에 마커를 두려고 할 경우
warningMessage = 1;
}
}
else
{
// 1 ~ 9 사이의 값을 입력하지 않은 경우
warningMessage = 2;
}
}
// 줄이 완성되었는지 확인
static void IsGameOver()
{
// 아무 문제가 없다면
if (warningMessage == 0)
{
// 1열 일치 여부
if ((drawMark[0] == drawMark[1]) && (drawMark[0] == drawMark[2]))
{
isGameOver = 1;
}
// 2열 일치 여부
else if ((drawMark[3] == drawMark[4]) && (drawMark[3] == drawMark[5]))
{
isGameOver = 1;
}
// 3열 일치 여부
else if ((drawMark[6] == drawMark[7]) && (drawMark[6] == drawMark[8]))
{
isGameOver = 1;
}
// 1행 일치 여부
else if ((drawMark[0] == drawMark[3]) && (drawMark[0] == drawMark[6]))
{
isGameOver = 1;
}
// 2행 일치 여부
else if ((drawMark[1] == drawMark[4]) && (drawMark[1] == drawMark[7]))
{
isGameOver = 1;
}
// 3행 일치 여부
else if ((drawMark[2] == drawMark[5]) && (drawMark[2] == drawMark[8]))
{
isGameOver = 1;
}
// 대각선 일치 여부 1
else if ((drawMark[0] == drawMark[4]) && (drawMark[0] == drawMark[8]))
{
isGameOver = 1;
}
// 대각선 일치 여부 2
else if ((drawMark[2] == drawMark[4]) && (drawMark[2] == drawMark[6]))
{
isGameOver = 1;
}
// 일치하는 라인이 하나라도 존재할 경우
if ((isGameOver == 1))
{
// 마지막에 찍힌 마커가 후턴 플레이어의 마커라면
// isGameOver = -1
// 그렇지 않다면 (선턴 플레이어의 마커라면)
// isGameOver = 1
if (drawMark[playerInput] == O)
{
isGameOver = -1;
}
}
// 9번째 턴이고 아직 일치하는 라인이 만들어지지 않았다면
else if ((isGameOver == 2) && (turnCount >= 9))
{
isGameOver = 0;
}
}
}
// 게임 종료 후 승자 표시 패널 띄우기
static void DrawEndPanel()
{
// 콘솔창을 클리어 후에
Console.Clear();
// isGameOver 플래그에 따라 메시지 출력
switch (isGameOver)
{
case 1: // 플레이어 1의 승리
Console.WriteLine("Winner Winner Chicken Dinner!!\nWinner is Player1");
break;
case -1: // 플레이어 2의 승리
Console.WriteLine("Winner Winner Chicken Dinner!!\nWinner is Player2");
break;
case 0: // 무승부
Console.WriteLine("무승부!");
break;
}
// 패널 그리기
DrawPanel();
}
}
'유니티개발 TIL' 카테고리의 다른 글
2주차 4~5일 TIL_C#기초_게임 만들기(TextRPG) (0) | 2025.07.11 |
---|---|
2주차 3일 TIL_C#기초-3(클래스) (8) | 2025.07.09 |
2주차 1일 TIL_C#기초-1(자료형, 연산자) (4) | 2025.07.07 |
1주차 5일 TIL - 간단한 기능 모작(포켓몬스터-02), TIL정리 (1) | 2025.07.04 |
1주차 4일 TIL - 객체지향프로그래밍- (0) | 2025.07.03 |