뱀 게임 만들기
어제 못 다한 뱀 게임을 만들었다.
1. List.Add() - 뱀 표시인 *가 하나만 찍히는 현상
문제의 코드
public class Snake
{
List<Point> positions;
public Snake(Point p, int l, Direction d)
{
positions = new List<Point>();
Point tempPos = new Point(p.x, p.y, p.sym);
for (int i = 0; i < l; ++i)
{
--tempPos.x;
positions.Add(tempPos);
}
}
...
}
고친 코드
public Snake(Point p, int l, Direction d)
{
List<Point> positions;
positions = new List<Point>();
for (int i = 0; i < l; ++i)
{
Point tempPos = new Point(--p.x, p.y, p.sym);
positions.Add(tempPos);
}
}
List.Add는 값 복사(수정해도 원래의 값에 영향X)가 아니라 참조(영향 O)이다.
나는 값 복사라 생각하고 코드를 짰었다.
문제의 코드에서 --tempPos.x를 하면 원래의 값인 tempPos의 x도 전부 --되니
tempPos를 4번 Add한 리스트의 크기는 4이지만 다 같은 Position을 가진 일이 일어난 것이다.
비슷한 문제 발생
Point tempPoint = positions[0]; // 얕은 복사
Point tempPoint = new Point(positions[0].x, positions[0].y, positions[0].sym);
// 로 해결
2. 뱀 게임 완성
문제 없이 돌아간다!
뱀 게임 전체 코드
더보기
class SnakeGame
{
static void Main(string[] args)
{
const int wallYSize = 20;
const int wallXSize = 40;
int eatenFoodNum = 0;
// 뱀의 초기 위치와 방향을 설정하고, 그립니다.
Point p = new Point(wallXSize / 2, wallYSize / 2, '*');
Snake snake = new Snake(p, 4, Direction.RIGHT);
snake.Draw();
// 음식의 위치를 무작위로 생성하고, 그립니다.
FoodCreator foodCreator = new FoodCreator(wallXSize, wallYSize, '$');
Point food = foodCreator.CreateFood(snake.positions);
food.Draw();
DrawWall(wallXSize, wallYSize);
// 게임 루프
while (true)
{
// 키 입력이 있는 경우에만 방향을 변경
if (Console.KeyAvailable)
{
ConsoleKey key = Console.ReadKey().Key;
snake.ChangeDirection(key);
}
// 벽 충돌
if (snake.isWallCollision(wallXSize, wallYSize))
{
Console.SetCursorPosition(0, wallYSize + 1);
Console.WriteLine("벽과 충돌했습니다.");
break;
}
// 몸통과 머리 충돌
if (snake.isBodyCollision())
{
Console.SetCursorPosition(0, wallYSize + 1);
Console.WriteLine("뱀의 머리와 몸통이 충돌했습니다.");
break;
}
// 음식 먹기
if (snake.positions[0].x == food.x && snake.positions[0].y == food.y)
{
++eatenFoodNum;
snake.Eat();
foodCreator = new FoodCreator(wallXSize, wallYSize, '$');
food = foodCreator.CreateFood(snake.positions);
food.Draw();
}
snake.Move();
snake.Draw();
// 게임 속도 조절
Thread.Sleep(100);
// 뱀의 상태를 출력합니다 (예: 현재 길이, 먹은 음식의 수 등)
Console.SetCursorPosition(0, wallYSize + 1);
Console.WriteLine("현재 뱀의 길이: " + snake.positions.Count);
Console.SetCursorPosition(0, wallYSize + 2);
Console.WriteLine("먹은 음식의 수: " + eatenFoodNum);
}
Console.SetCursorPosition(0, wallYSize + 2);
Console.WriteLine("최종 뱀의 길이: " + snake.positions.Count);
Console.SetCursorPosition(0, wallYSize + 3);
Console.WriteLine("최종 먹은 음식의 수: " + eatenFoodNum);
}
static void DrawWall(int xSize, int ySize)
{
for (int i = 0; i < xSize; i++)
{
Console.SetCursorPosition(i, 0);
Console.Write('-');
Console.SetCursorPosition(i, ySize);
Console.Write('-');
}
for (int i = 0; i < ySize; i++)
{
Console.SetCursorPosition(0, i);
Console.Write('|');
Console.SetCursorPosition(xSize, i);
Console.Write('|');
}
}
}
public class Snake
{
Direction dir;
bool isEat = false;
public List<Point> positions { get; private set; }
public Snake(Point p, int length, Direction d)
{
dir = d;
positions = new List<Point>(10);
for (int i = 0; i < length; ++i)
{
Point tempPos = new Point(--p.x, p.y, p.sym);
positions.Add(tempPos);
}
}
public void Draw()
{
for (int i = 0; i < positions.Count; ++i)
positions[i].Draw();
}
public void Move()
{
Point tempPoint = new Point(positions[0].x, positions[0].y, positions[0].sym);
switch (dir)
{
case Direction.UP:
--tempPoint.y;
break;
case Direction.DOWN:
++tempPoint.y;
break;
case Direction.LEFT:
--tempPoint.x;
break;
case Direction.RIGHT:
++tempPoint.x;
break;
default:
break;
}
positions.Insert(0, tempPoint);
if (!isEat)
{
positions[positions.Count - 1].Clear();
positions.RemoveAt(positions.Count - 1);
}
else isEat = false;
}
public void Eat()
{
isEat = true;
}
public void ChangeDirection(ConsoleKey key)
{
if (key == ConsoleKey.UpArrow) dir = Direction.UP;
else if (key == ConsoleKey.DownArrow) dir = Direction.DOWN;
else if (key == ConsoleKey.LeftArrow) dir = Direction.LEFT;
else if (key == ConsoleKey.RightArrow) dir = Direction.RIGHT;
}
public bool isWallCollision(int wallXsize, int wallYSize)
{
if (positions[0].x >= wallXsize || positions[0].x <= 0
|| positions[0].y >= wallYSize || positions[0].y <= 0)
return true;
else return false;
}
public bool isBodyCollision()
{
for (int i = 0; i < positions.Count; ++i)
for (int j = 0; j < positions.Count; ++j)
if (i != j
&& positions[i].x == positions[j].x
&& positions[i].y == positions[j].y)
return true;
return false;
}
}
public class FoodCreator
{
int x;
int y;
char foodChar;
Point p;
public FoodCreator(int _x, int _y, char f)
{
x = _x;
y = _y;
foodChar = f;
//p = new Point(x, y, f);
}
public Point CreateFood(List<Point> snakePositions)
{
bool isCollision = false;
while (!isCollision)
{
Random random = new Random();
x = random.Next(1, x);
y = random.Next(1, y);
p = new Point(x, y, foodChar);
for (int i = 0; i < snakePositions.Count; ++i) {
if (snakePositions[i].x == p.x && snakePositions[i].y == p.y)
{
isCollision = false;
break;
}
else
isCollision = true;
}
}
return p;
}
}
public class Point
{
public int x { get; set; }
public int y { get; set; }
public char sym { get; set; }
// Point 클래스 생성자
public Point(int _x, int _y, char _sym)
{
x = _x;
y = _y;
sym = _sym;
}
// 점을 그리는 메서드
public void Draw()
{
Console.SetCursorPosition(x, y);
Console.Write(sym);
}
// 점을 지우는 메서드
public void Clear()
{
sym = ' ';
Draw();
}
// 두 점이 같은지 비교하는 메서드
public bool IsHit(Point p)
{
return p.x == x && p.y == y;
}
}
// 방향을 표현하는 열거형입니다.
public enum Direction
{
LEFT,
RIGHT,
UP,
DOWN
}
블랙잭 만들기

텍스트로만 간단하게 구현해봤다.
블랙잭 코드
더보기
코드는 빠른 구현을 목적으로 짰기 때문에 마음에 들진 않는다.
public class Blackjack
{
Player player;
Dealer dealer;
Deck deck;
public Blackjack(Player _player, Dealer _dealer)
{
player = new Player();
dealer = new Dealer();
deck = new Deck();
}
// 딜러와 플레이어에게 2장의 카드 주기
public void DealInitialCards()
{
Hit();
Hit();
}
// 카드 더 받기
public void Hit()
{
player.DrawCardFromDeck(deck);
if (dealer.Hand.GetTotalValue() < 17)
dealer.DrawCardFromDeck(deck);
}
// 플레이어가 stop했을 경우
// 딜러의 카드가 17이 넘거나 17점이 될 때까지 딜러에게 카드 주기
public void DealerHit()
{
while (dealer.Hand.GetTotalValue() != 17
&& dealer.Hand.GetTotalValue() < 17)
dealer.DrawCardFromDeck(deck);
}
// 점수 비교, 승패 가르기
public void WhoWin()
{
Console.Clear();
WritePlayerInfo();
WriteDealerInfo();
int playerScore = (int)MathF.Abs(player.Hand.GetTotalValue() - 21);
int dealerScore = (int)MathF.Abs(dealer.Hand.GetTotalValue() - 21);
if(dealerScore > playerScore)
Console.WriteLine("플레이어 승! ");
else if(dealerScore == playerScore)
Console.WriteLine("무승부!");
else
Console.WriteLine("딜러 승! ");
Console.WriteLine("PlayerScore: " + player.Hand.GetTotalValue());
Console.WriteLine("DealerScore: " + dealer.Hand.GetTotalValue());
}
public void WritePlayerInfo()
{
Console.WriteLine("Player Card Info");
Console.WriteLine();
for (int i = 0; i < player.Hand.cards.Count; ++i)
Console.WriteLine( player.Hand.cards[i].ToString());
Console.WriteLine("Player Total: " + player.Hand.GetTotalValue());
Console.WriteLine();
Console.WriteLine();
}
public void WriteDealerInfo()
{
Console.WriteLine("Dealer Card Info");
Console.WriteLine();
Console.WriteLine("딜러가 가지고 있는 카드의 개수: " + dealer.Hand.cards.Count + "개");
Console.WriteLine(dealer.Hand.cards[0].ToString());
Console.WriteLine();
Console.WriteLine();
}
public bool isGameEnd()
{
if (player.Hand.GetTotalValue() >= 21)
return true;
return false;
}
}
class Program
{
static void Main(string[] args)
{
// 블랙잭 게임을 실행하세요
while (true)
{
Player player = new Player();
Dealer dealer = new Dealer();
Blackjack blackjackGame = new Blackjack(player, dealer);
blackjackGame.DealInitialCards();
bool isGameOver = false;
while (!isGameOver)
{
Console.Clear();
blackjackGame.WritePlayerInfo();
blackjackGame.WriteDealerInfo();
Console.WriteLine("Hit : 1, Stand: 2");
char c = Console.ReadLine()[0];
if (c == '1')
{
blackjackGame.Hit();
isGameOver = blackjackGame.isGameEnd();
}
else if (c == '2')
{
blackjackGame.DealerHit();
isGameOver = true;
}
else continue;
}
blackjackGame.WhoWin();
// 계속 게임을 할거냐
Console.WriteLine("게임을 그만하려면 '0'을, 계속하려면 아무 문자나 입력해주세요.");
if (Console.ReadLine()[0] == '0')
break;
}
}
}
'내일배움캠프(Unity)' 카테고리의 다른 글
내일배움캠프 게임개발(Unity) 10일차 231110 TIL (0) | 2023.11.10 |
---|---|
내일배움캠프 게임개발(Unity) 9일차 231109 TIL (0) | 2023.11.09 |
내일배움캠프 게임개발(Unity) 7일차 TIL (0) | 2023.11.07 |
내일배움캠프 게임개발(Unity) 6일차 TIL - 프로그래밍 기초 주차 시작 (0) | 2023.11.06 |
내일배움캠프 게임개발(Unity) 5일차 TIL - 프로젝트 발표날 (1) | 2023.11.03 |