오늘의 학습 키워드
Task
공부한 내용
스네이크 게임
스네이크 게임 구현
스파르타 동료분의 코드를 참고하여 진행하였습니다.
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace SnakeGame
{
class Program
{
static int score = 0;
static int highScore = 0;
static int foodCount = -1;
static Map map;
static SnakeHead player;
static ConsoleKeyInfo input;
static Vector2Int direction = new Vector2Int(1, 0);
static bool applicationQuit = false;
static bool isEnterPressed = false;
static void Main(string[] args)
{
Init();
Route();
while (!applicationQuit);
}
private static async void Route()
{
bool isCrashed = false;
Task task = Task.Run(() =>
{
while (true)
{
input = Console.ReadKey(true);
if (input.Key == ConsoleKey.Escape)
{
applicationQuit = true;
break;
}
else if (input.Key == ConsoleKey.Enter)
{
isEnterPressed = true;
}
}
});
while (!applicationQuit)
{
await Task.Delay(100);
if (isCrashed)
{
Console.Clear();
map.DrawMap();
Console.WriteLine("===============================================================");
Console.WriteLine($"점수 : {score} 최고 점수 : {highScore} 먹은 수 : {foodCount}");
Console.WriteLine("===============================================================");
Console.WriteLine("죽었습니다. 다시 시작 : Enter");
if (isEnterPressed)
{
Reset();
Init();
isEnterPressed = false;
isCrashed = false;
}
}
else
{
switch (input.Key)
{
case ConsoleKey.RightArrow:
direction = new Vector2Int(1, 0);
break;
case ConsoleKey.LeftArrow:
direction = new Vector2Int(-1, 0);
break;
case ConsoleKey.UpArrow:
direction = new Vector2Int(0, -1);
break;
case ConsoleKey.DownArrow:
direction = new Vector2Int(0, 1);
break;
}
isCrashed = Update();
}
}
}
private static void Reset()
{
score = 0;
foodCount = -1;
map = null;
player = null;
direction = new Vector2Int(1, 0);
}
static bool Update()
{
Console.SetCursorPosition(0,0);
if (!map.IsFoodExist())
{
foodCount++;
map.SpawnRandomFood();
}
bool isCrashed = player.TryMove(map, direction);
map.DrawMap();
Console.WriteLine("===============================================================");
Console.WriteLine($"점수 : {score} 최고 점수 : {highScore} 먹은 수 : {foodCount}");
Console.WriteLine("===============================================================");
Console.WriteLine("ESC를 누르면 종료");
score++;
if (score > highScore)
{
highScore = score;
}
isEnterPressed = false;
return isCrashed;
}
private static void Init()
{
int mapX = 50, mapY = 25;
map = new Map(mapX, mapY);
player = new SnakeHead(new Vector2(mapX / 2, mapY / 2));
}
public enum ObjectType
{
BLANK,
WALL,
FOOD,
SNAKE_BODY,
SNAKE_HEAD,
}
public struct Vector2
{
public int X { get; set; }
public int Y { get; set; }
public Vector2(int x, int y)
{
X = x;
Y = y;
}
}
public struct Vector2Int
{
private int x, y;
public int X
{
get => x;
set
{
if (value > 1)
{
x = 1;
}
else if (value < -1)
{
x = -1;
}
else
{
x = value;
}
}
}
public int Y
{
get => y;
set
{
if (value > 1)
{
y = 1;
}
else if (value < -1)
{
y = -1;
}
else
{
y = value;
}
}
}
public Vector2Int(int x, int y)
{
this.x = x;
this.y = y;
}
}
public class Transform
{
public Vector2 position = new Vector2(0, 0);
public Vector2Int rotation = new Vector2Int(0, 0);
}
class Object
{
public Transform trans = new Transform();
public ObjectType objType;
public Object(Vector2 pos, Vector2Int rot, ObjectType type)
{
trans.position = pos;
trans.rotation = rot;
objType = type;
}
}
class Map
{
public int X { get; private set; }
public int Y { get; private set; }
public Object[][] tiles { get; private set; }
public Map(int x, int y)
{
X = x;
Y = y;
// 세로줄이 y개인 2차원 배열
tiles = new Object[Y][];
for (int i = 0; i < Y; i++)
{
// 안에 가로줄의 요소가 x개인 배열
tiles[i] = new Object[X];
}
for (int i = 0; i < Y; i++)
{
for (int j = 0; j < X; j++)
{
Vector2 pos = new Vector2(X, Y);
Vector2Int rot = new Vector2Int(0, 0);
Object tile;
// 벽 만들기
if (i == 0 || i + 1 == Y || j == 0 || j + 1 == X) // 경계 부분이라면
{
if (i == 0)
{
if (j == 0)
{
rot = new Vector2Int(-1, 1);
}
else if (j + 1 == X)
{
rot = new Vector2Int(1, 1);
}
else
{
rot = new Vector2Int(0, 1);
}
}
// -1
else if (i + 1 == Y)
{
if (j == 0)
{
rot = new Vector2Int(-1, -1);
}
else if (j + 1 == X)
{
rot = new Vector2Int(1, -1);
}
else
{
rot = new Vector2Int(0, -1);
}
}
else
{
if (j == 0)
{
rot = new Vector2Int(-1, 0);
}
else if (j + 1 == X)
{
rot = new Vector2Int(1, 0);
}
}
tile = new Object(pos, rot, ObjectType.WALL);
}
else // 경계 부분이 아니라면 기본 Vector2Int(0,0);
{
tile = new Object(pos, rot, ObjectType.BLANK);
}
tiles[i][j] = tile;
}
}
}
public void DrawMap()
{
for (int i = 0; i < Y; i++)
{
for (int j = 0; j < X; j++)
{
if (tiles[i][j].objType == ObjectType.BLANK)
{
Console.Write(' ');
}
else if (tiles[i][j].objType == ObjectType.FOOD)
{
Console.Write('$');
}
else if (tiles[i][j].objType == ObjectType.SNAKE_HEAD)
{
Console.Write('@');
}
else if (tiles[i][j].objType == ObjectType.SNAKE_BODY)
{
Console.Write('#');
}
else if (tiles[i][j].objType == ObjectType.WALL)
{
if (tiles[i][j].trans.rotation.X == -1 && tiles[i][j].trans.rotation.Y == 0
|| tiles[i][j].trans.rotation.X == 1 && tiles[i][j].trans.rotation.Y == 0)
{
Console.Write('|');
}
else if (tiles[i][j].trans.rotation.Y == -1 && tiles[i][j].trans.rotation.X == 0
|| tiles[i][j].trans.rotation.Y == 1 && tiles[i][j].trans.rotation.X == 0)
{
Console.Write('-');
}
else
{
Console.Write('+');
}
}
}
Console.WriteLine();
}
}
public void SpawnRandomFood()
{
Random rand = new Random();
while (true)
{
int ranX = rand.Next(0, X);
int ranY = rand.Next(0, Y);
if (tiles[ranY][ranX].objType == ObjectType.BLANK)
{
tiles[ranY][ranX].objType = ObjectType.FOOD;
break;
}
}
}
public bool IsFoodExist()
{
for (int i = 0; i < Y; i++)
{
for (int j = 0; j < X; j++)
{
if (tiles[i][j].objType == ObjectType.FOOD)
{
return true;
}
}
}
return false;
}
}
class SnakeHead : Object
{
List<Object> body = new List<Object>();
public SnakeHead(Vector2 startPos) : base(startPos, new Vector2Int(1, 0), ObjectType.SNAKE_HEAD)
{
body.Add(this);
for (int i = 1; i < 4; i++)
{
body.Add(new Object(new Vector2(trans.position.X - i, trans.position.Y),
trans.rotation, ObjectType.SNAKE_BODY));
}
}
public bool TryMove(Map map, Vector2Int dir)
{
bool isCrashed = false;
Vector2 lastBodyPosition = body[body.Count - 1].trans.position;
// 머리 다음 부분을 제외한 몸통 이동
for (int i = body.Count - 1; i > 1; i--)
{
body[i].trans.rotation = body[i - 1].trans.rotation;
body[i].trans.position =
new Vector2(body[i].trans.position.X + body[i].trans.rotation.X,
body[i].trans.position.Y + body[i].trans.rotation.Y);
map.tiles[body[i].trans.position.Y][body[i].trans.position.X].objType =
body[i].objType;
}
body[1].trans.rotation = trans.rotation;
body[1].trans.position =
new Vector2(body[1].trans.position.X + body[1].trans.rotation.X,
body[1].trans.position.Y + body[1].trans.rotation.Y);
map.tiles[body[1].trans.position.Y][body[1].trans.position.X].objType =
body[1].objType;
trans.rotation = dir;
trans.position.X += trans.rotation.X;
trans.position.Y += trans.rotation.Y;
if (map.tiles[trans.position.Y + dir.Y][trans.position.X + dir.X].objType ==
ObjectType.WALL)
{
isCrashed = true;
}
else if (map.tiles[trans.position.Y + dir.Y][trans.position.X + dir.X].objType ==
ObjectType.SNAKE_BODY)
{
isCrashed = true;
}
else if (map.tiles[trans.position.Y + dir.Y][trans.position.X + dir.X].objType ==
ObjectType.FOOD)
{
Object tail = body[body.Count - 1];
body.Add(new Object(new Vector2(tail.trans.position.X - tail.trans.rotation.X, tail.trans.position.Y - tail.trans.rotation.Y),
body[body.Count - 1].trans.rotation, ObjectType.SNAKE_BODY));
lastBodyPosition = body[body.Count - 1].trans.position;
}
map.tiles[trans.position.Y][trans.position.X].objType = objType;
map.tiles[lastBodyPosition.Y][lastBodyPosition.X].objType = ObjectType.BLANK;
return isCrashed;
}
}
}
}
블랙잭
딜러와 겨루는 블랙잭 게임을 구현했습니다.
나의 조건 : 21이 목표, 21을 넘어가면 짐, 1~13의 카드뭉치 4개 => 52장
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace sparta
{
class 블랙잭
{
static int cardCount = 3;
static int targetSum = 21;
static void Main(string[] args)
{
List<int> cardSet = new List<int>();
int[] cards = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 };
for (int i = 0; i < 4; i++)
{
cardSet.AddRange(cards);
}
// 1 ~ 13
List<int> playerCards = new List<int>();
int playerSum = 0;
List<int> dealerCards = new List<int>();
int dealerSum = 0;
Random rand = new Random();
for (int i = 0; i < cardCount; i++)
{
int randomIndex = rand.Next(0, cardSet.Count);
playerCards.Add(cardSet[randomIndex]);
cardSet.RemoveAt(randomIndex);
WriteCards(playerCards);
randomIndex = rand.Next(0, cardSet.Count);
dealerCards.Add(cardSet[randomIndex]);
cardSet.RemoveAt(randomIndex);
WriteCards(dealerCards);
playerSum = CalculateSum(playerCards);
dealerSum = CalculateSum(dealerCards);
if (playerSum > targetSum && dealerSum > targetSum)
{
Console.WriteLine("둘 다 합이 목표 숫자를 넘었습니다. 무승부입니다.");
break;
}
else if (dealerSum > targetSum)
{
Console.WriteLine("플레이어의 승입니다.");
break;
}
else if (playerSum > targetSum)
{
Console.WriteLine("딜러의 승입니다.");
break;
}
if (i == cardCount - 1)
{
if (playerSum == dealerSum)
{
Console.WriteLine("합이 같습니다. 무승부입니다.");
}
else if (playerSum > dealerSum)
{
Console.WriteLine("플레이어의 승입니다.");
}
else
{
Console.WriteLine("딜러의 승입니다.");
}
}
}
}
private static void WriteCards(List<int> cards)
{
foreach (var card in cards)
{
Console.Write($"{card} ");
}
Console.WriteLine();
}
private static int CalculateSum(List<int> cards)
{
int sum = 0;
foreach (var card in cards)
{
sum += card;
}
return sum;
}
}
}
오늘의 회고
오늘은 강의 듣느랴 기능 구현 해보느랴 코드 이해하느랴 정신이 없었다. 하지만 하나하나 문제가 풀려가는 것을 보고 꽤나 보람을 느낀 하루였던 것 같다. 이렇게만 꾸준히 노력하면 나도 언젠가 코딩 고수가 되지 않을까 하는 기대를 품으며 내일도 달려보도록 하겠다.
내일은 알고리즘 강의 듣는 것이 목표인데 먼저 알고리즘 분야 별로 접근법이나 빅오 표기법을 위주로 공부하도록 해야겠다. 내일도 파이팅!
참고 :
https://potatopotatopotato.tistory.com/15
C# 콘솔로 스네이크 게임 찍어내기
숙제라서 만들었다 만들고 보니까 껌뻑껌뻑 거리는데 예전에 WINAPI 할때 더블 버퍼링 생각이 났다 어렵진 않았는데 시간 박치기 구현 노가다라서 피곤했다.. 저녁까지 밖에 나갔다 왔는데 집에
potatopotatopotato.tistory.com
'스파르타 Unity 1기' 카테고리의 다른 글
내일배움캠프 9일차 TIL - TextRPG 만들기 1 (0) | 2023.08.18 |
---|---|
내일배움캠프 8일차 TIL - 알고리즘 과제 (0) | 2023.08.17 |
내일배움캠프 1주차 WIL - 미니 프로젝트 (0) | 2023.08.14 |
내일배움캠프 6일차 TIL - C# 문법과 기능 구현 (0) | 2023.08.14 |
스파르타 Unity 8기 5일차 TIL (0) | 2023.08.11 |