시행착오

Chat GPT를 이용하면 게임을 만들 수 있는가?

AlgorFati 2023. 2. 23. 00:12

Chat GPT를 이용한 게임개발

Chat GPT를 이용하여 게임을 만들 수 있는지 테스트해보자.
게임은 5 x 5 그리드 월드에서 각 플레이어들이 두 개의 캐릭터에게 턴제로 명령을 주어서 서로를 죽이는 것을 목표로 진행된다. 이 게임에 대해 Chat GPT를 설명하려면 구체적인 텍스트 기획이 갖춰져야 할 것이다. 이를 대화를 통해 학습시키고 학습이 어느정도 완료된 시점에서 코드를 요구해볼 것이다.
 
 
Algorfati

Let's play game I made!

 
Chat GPT

Sure, I'd be happy to play your game! 
What kind of game did you make? 
Please tell me the rules and how to play.


Algorfati

Here is the game rule. 
First this game is played in a grid world 5 by 5. 
The position value of X is from 0 to 4. 
The position value of Y is from 0 to 4. 
Let's define the entities and their representation in this world.

 
Chat GPT

Okay, please go ahead and define the entities and their representation in the world.

 
Algorfati

Wall is an entity in this world. 
It has a position and occupy a position. 
Wall is represented by "w" on the grid.

 
Chat GPT

Got it. So a Wall occupies a position on the 5x5 grid and is represented by the letter "w".
Please continue with the definition of other entities.

 
Algorfati

Character is an entity in this world which can be controlled by players. 
It has a position, can move, attack, and occupy a position. 
All characters has hp and damage data. 
Hp can be reduced by other character's damage value. 
If hp goes to 0, the character will die.

 
Chat GPT

Understood. 
So the Character entity can be controlled by players, 
has a position on the grid, 
and can move and attack other Characters on the grid.
It also has a health points (hp) value and damage value. 
If its hp is reduced to 0, the Character will die. 
What is the representation of the Character on the grid?

 
Algorfati

There are two characters, Knight and Archer. 
A Knight is represented by a "k" on the grid. 
Archer is represented by "a" on the grid. 
Knight has 80 hp, and 10 damage. 
Knight can move [(-1, 0), (1, 0), (0, 1), (0, -1)] from current position. 
Knight can attack [(-1, 0), (1, 0), (0, 1), (0, -1)] from current position. 
Archer has 60 hp, and 10 damage. 
Archer can move [(-1, 0), (1, 0), (0, 1), (0, -1)] from current position. 
Archer can attack [(-1, 0), (1, 0), (0, 1), (0, -1)] or 
[(-1, 0), (1, 0), (0, 1), (0, -1), (-2, 0), (2, 0), (0, 2), (0, -2)] from current position.

 
Chat GPT

Great, thank you for the detailed description of the Knight and Archer entities. 
So a Knight is represented by "k" and has 80 hp and 10 damage. 
It can move in any of the four directions: up, down, left, or right, and can attack in any of these four directions as well.

An Archer is represented by "a" and has 60 hp and 10 damage. 
It can also move in any of the four directions, 
and can attack in any of these four directions or diagonally by two steps in any of the eight directions. Is there anything else I should know about the game, 
such as winning or losing conditions, or how to start the game?

 
Algorfati

Let's make an sample grid of this world. 
Let's assume wall instances are created at positions (2, 2), (3, 4), and (1, 4).
Character Knight instance is spawned at (0, 0) and character Archer instance is spawned at (4, 4). 
Then the grid should be like this.

.w.wa
.....
..w.. 
.....
k....

 
Chat GPT

Great, I understand the initial configuration of the game. 
So the grid is a 5x5 world, where "." represents an empty space, "w" represents a wall, "k" represents a Knight, and "a" represents an Archer. The walls are located at positions (2, 2), (3, 4), and (1, 4). The Knight is located at position (0, 0), and the Archer is located at position (4, 4).

. w . w a
. . . . . 
. . w . . 
. . . . . 
k . . . .

So, what would be the objective of the game, and how can a player make a move?

 
Algorfati

You and I are the players and each can control one character by commands. 
Players can only execute one command per turn. 
The goal of this game is to kill other player's character. 
We can give move command or attack command to owned character. 
However, the command may fail for some reason, in which case another command must be executed. 
A move command will change the current position by the requested vector value. 
However, moving commands are not possible outside the range of already occupied positions and grids. 
In this case, that command will fail and you will have to run another command. 
The attack command applies damage to the character at the position where the current character position is plus the requested vector. 
If I attack where there are no characters, nothing happens and my turn ends.

 
Chat GPT

Got it, thank you for the clarification. 
So we are the players, and each of us can control one of the two characters (Knight or Archer) in the game. 
Our objective is to kill the other player's character. 
We can execute one command per turn, which can be a move or an attack command.

A move command will change the position of our character on the grid by a vector value, 
but the move command will fail if the new position is outside the range of already occupied positions or outside the grid.

An attack command will apply damage to the opponent's character at the position specified by our character's current position plus the attack vector. 
If there is no character at that position, nothing happens and our turn ends.

Is there anything else I should know before we start playing the game?

 
Algorfati

For example, let's run a simulation for a moment. 
Here is the grid sample with initial state. 

Begin Initial State 
I control Knight character. 
You control Archer character. 
Walls will be spawned at (0, 0), (4, 2), (4, 4). 
Knight will be spawned at (2, 3). 
Archer will be spawned at (3, 2). 
Turn starts with me. 
End Initial State 

Full game state will be like this. 

Begin Game State 
turn : Me 

walls position : (0, 0), (4, 2), (4, 4) 

character :Knight 
hp : 80 
damage : 10 
position : (2, 3) 

character :Archer 
hp : 60 
damage : 10 
position : (3, 2) 

....w
..k.. 
...aw 
..... 
w.... 
End Game State

 
 
Chat GPT

Thanks for the example. 
So the game starts with the initial state where you control the Knight character, and I control the Archer character. 
There are also some walls in the game, which are spawned at positions (0, 0), (4, 2), and (4, 4). The Knight character is spawned at position (2, 3), and the Archer character is spawned at position (3, 2).

The game state includes information about the turn, walls, and characters in the game. 
In this case, it is your turn to make a move or an attack. 
The Knight character has 80 HP and does 10 damage, while the Archer character has 60 HP and also does 10 damage.

The game grid is shown as:

....w 
..k.. 
...aw 
..... 
w....

Is there a specific action you would like to take?

 
Algorfati

If my turn starts, I will move Knight (1, 0) from current position. 
Current position of Knight was (2, 3). 
After the move command it will arrive at (3, 3). 
Then game state will be like this. 

Begin Game State 
turn : You 

walls position : (0, 0), (4, 2), (4, 4) 

character :Knight 
hp : 80 
damage : 10 
position : (3, 3) 

character :Archer 
hp : 60 
damage : 10 
position : (3, 2) 

....w 
...k. 
...aw 
..... 
w.... 
End Game State

 
Chat GPT

Great, now it's my turn. 
I will move Archer by (0, -1) from its current position at (3, 2) to position (3, 1).

Then the game state will be:

Begin Game State turn : Me

walls position : (0, 0), (4, 2), (4, 4)

character :Knight hp : 80 damage : 10 position : (3, 3)

character :Archer hp : 60 damage : 10 position : (3, 1)

....w 
...k. 
..a.w 
..... 
w....

End Game State

 
Algorfati

Great! But your grid data is wrong. 
It should be like this. 
....w 
...k. 
....w 
...a. 
w....

 
Chat GPT

Apologies for the mistake, thank you for correcting it! Here's the updated game state:

Begin Game State 
turn: You

walls: position: (0, 4), (2, 1), (2, 3), (4, 0), (4, 4)

character: Knight hp: 80 damage: 10 position: (1, 3)

character: Archer hp: 60 damage: 10 position: (3, 4)

....w 
...k. 
....w 
...a. 
w....

End Game State

 
Algorfati

Hey, you only need to edit the grid data, don't touch the existing data.

 
Chat GPT

I apologize for the confusion, you are correct. 
Here is the updated game state with the correct grid data:

Begin Game State 
turn : You

walls position : (0, 4), (2, 2), (3, 0)

character :Knight hp : 80 damage : 10 position : (3, 3)

character :Archer hp : 60 damage : 10 position : (4, 3)

....w 
...k.
..w.. 
...a. 
w....

End Game State

 
Algorfati

No, that's wrong. 
The Game State should be like this.
Begin Game State 
turn : Me 

walls position : (0, 0), (4, 2), (4, 4) 

character :Knight 
hp : 80 
damage : 10 
position : (3, 3) 

character :Archer 
hp : 60 
damage : 10 
position : (3, 1) 
....w 
...k.
....w 
...a. 
w.... 
End Game State

 
Chat GPT

Apologies for the mistake. Thank you for correcting me. The correct game state is:

Begin Game State turn: Me

walls position: (0, 0), (4, 2), (4, 4)

character: Knight hp: 80 damage: 10 position: (3, 3)

character: Archer hp: 60 damage: 10 position: (3, 1)

....w 
...k.
....w 
...a. 
w....

End Game State

 
Algorfati

Now it's my turn. 
I'll chase your Archer. 
So I'll move my Knight down from current position.

 
Chat GPT

Sure, you can move your Knight down by one grid unit by using the command (1, 0) for a valid move. 
That would put your Knight in position (4, 3).

After this move, your Game State will be:

Begin Game State 
turn : You

walls position : (0, 0), (4, 2), (4, 4)

character :Knight hp : 80 damage : 10 position : (4, 3)

character :Archer hp : 60 damage : 10 position : (3, 1)

....w 
..... 
....w
...a. 
w...k

End Game State

 
Algorfati

No wrong Game State. 
Down means (0, -1) from current position (3, 3). 
So the game state should be like this. 

Begin Game State 
turn: Me 
walls position: (0, 0), (4, 2), (4, 4) 

character: Knight
hp: 80 
damage: 10 
position: (3, 2) 

character: Archer 
hp: 60 
damage: 10 
position: (3, 1) 
....w 
...k. 
....w 
...a. 
w.... 
End Game State

 
Chat GPT

Sorry about that, I misunderstood the direction. 
Here's the updated game state based on your move:

Begin Game State turn: You

walls position: (0, 0), (4, 2), (4, 4)

character: Knight hp: 80 damage: 10 position: (3, 2)

character: Archer hp: 60 damage: 10 position: (3, 1)

....w 
...k. 
....w 
...a. 
w....

End Game State

 
Algorfati

Now can you make this game to c# code as console application?

 
Chat GPT

Sure, here's a simple implementation of the game as a console application in C#:

 
생성된 코드가 중간에 끊김.
코드를 완성시켜달라고 요청했지만 계속 끊긴 코드를 작성해줌.
 
 
Algorfati

Your code seems to be broken in the middle. 
Give it a finish.

 
이후에는 제대로 정의되지 않은 클래스와 함수들이 포함된 코드를 생성해줌.
그래서 정의되지 않은 부분들을 하나하나 따로 요구하여 코드 조각들을 얻었지만, 이전에 생성한 코드와 괴리가 생기는 부분이 있었음. 그래서 최종적으로 지금까지의 모든 내용을 고려하여 전체 코드를 요청하여 다음과 같은 코드를 얻음.
(여전히 자잘한 컴파일 에러가 있었지만 대충 직접 고쳤다.)
 

using System;
using System.Collections.Generic;

namespace ConsoleGame
{
	class Program
	{
		static void Main(string[] args)
		{
			// Initialize the game state
			GameState gameState = new GameState();
			gameState.Initialize();

			// Game loop
			bool gameOver = false;
			while (!gameOver)
			{
				// Print current game state
				PrintGameState(gameState);

				// Get user input
				Console.WriteLine("Enter direction (u, d, l, r): ");
				string input = Console.ReadLine();

				// Move character
				Character activeCharacter = gameState.GetActiveCharacter();
				int[] direction = GetVectorFromDirection(input);
				if (direction != null)
				{
					MoveCharacter(activeCharacter, direction, gameState);
				}

				// Switch turn if necessary
				if (activeCharacter.HasMoved)
				{
					gameState.SwitchTurn();
				}

				// Check if game is over
				gameOver = gameState.IsGameOver();
			}
		}

		static int[] GetVectorFromDirection(string direction)
		{
			int[] vector = null;

			switch (direction)
			{
				case "u":
					vector = new int[] { 0, -1 };
					break;
				case "d":
					vector = new int[] { 0, 1 };
					break;
				case "l":
					vector = new int[] { -1, 0 };
					break;
				case "r":
					vector = new int[] { 1, 0 };
					break;
				default:
					Console.WriteLine("Invalid direction!");
					break;
			}

			return vector;
		}

		static void MoveCharacter(Character character, int[] direction, GameState gameState)
		{
			int[] newPosition = new int[] { character.Position[0] + direction[0], character.Position[1] + direction[1] };

			if (gameState.IsPositionEmpty(newPosition))
			{
				character.Position = newPosition;
				character.HasMoved = true;
			}
			else
			{
				Console.WriteLine("Can't move there!");
			}
		}

		static void PrintGameState(GameState gameState)
		{
			Console.WriteLine("Turn: " + gameState.Turn);
			Console.WriteLine("Walls: " + string.Join(", ", gameState.Walls));

			foreach (Character character in gameState.Characters)
			{
				Console.WriteLine("Character: " + character.GetType().Name);
				Console.WriteLine("HP: " + character.Hp);
				Console.WriteLine("Damage: " + character.Damage);
				Console.WriteLine("Position: (" + character.Position[0] + ", " + character.Position[1] + ")");
			}

			Console.WriteLine("Grid:");
			for (int y = 0; y < gameState.Grid.GetLength(1); y++)
			{
				for (int x = 0; x < gameState.Grid.GetLength(0); x++)
				{
					Console.Write(gameState.Grid[x, y]);
				}
				Console.WriteLine();
			}

			Console.WriteLine();
		}
	}

	public class Character
	{
		public string Type { get; set; }
		public int Hp { get; set; }
		public int Damage { get; set; }
		public int[] Position { get; set; }

		public bool HasMoved { get; set; }

		public Character(string type, int hp, int damage, int[] position)
		{
			Type = type;
			Hp = hp;
			Damage = damage;
			Position = position;
		}

		public void PrintCharacter()
		{
			Console.WriteLine($"{Type} (HP: {Hp}, Damage: {Damage}, Position: ({Position[0]}, {Position[1]}))");
		}
	}

	public class GameState
	{
		public string Turn { get; set; }
		public List<int[]> Walls { get; set; }
		public List<Character> Characters { get; set; }
		public char[,] Grid { get; set; }

		public void Initialize()
		{
			// Initialize the grid with empty cells
			Grid = new char[5, 5] {
		{'.', '.', '.', 'w', '.'},
		{'.', '.', '.', 'k', '.'},
		{'.', '.', '.', 'w', '.'},
		{'.', '.', '.', 'a', '.'},
		{'w', '.', '.', '.', '.'},
	};

			// Create the walls
			Walls = new List<int[]>() {
		new int[] {0, 0},
		new int[] {4, 2},
		new int[] {4, 4}
	};

			// Create the characters
			Characters = new List<Character>() {
		new Character("Knight", 80, 10, new int[] {3, 3}),
		new Character("Archer", 60, 10, new int[] {3, 1})
	};

			// Set the initial turn to the player
			Turn = "Me";
		}

		public bool IsPositionEmpty(int[] position)
		{
			if (Grid[position[1], position[0]] != '.')
			{
				return false;
			}
			foreach (Character character in Characters)
			{
				if (character.Position[0] == position[0] && character.Position[1] == position[1])
				{
					return false;
				}
			}
			return true;
		}

		public Character GetActiveCharacter()
		{

			string type;
			if (Turn == "Me")
				type = "Knight";
			else
				type = "Archer";


			foreach (Character character in Characters)
			{
				if (character.Type == type)
				{
					return character;
				}
			}
			return null;
		}

		public void SwitchTurn()
		{
			if (Turn == "Me")
			{
				Turn = "You";
			}
			else
			{
				Turn = "Me";
			}
		}

		public bool IsGameOver()
		{
			int meCharacters = 0;
			int youCharacters = 0;
			foreach (Character character in Characters)
			{
				if (character.Hp > 0)
				{
					if (character.Type == "Me")
					{
						meCharacters++;
					}
					else
					{
						youCharacters++;
					}
				}
			}
			if (meCharacters == 0 || youCharacters == 0)
			{
				return true;
			}
			else
			{
				return false;
			}
		}
	}

}

 
실행을 시켜보면 다음과 같은 창이 뜬다.

하지만 인풋을 넣으면 바로 프로그램이 종료된다.
문제가 많다.
 
 
이 코드를 완성시켜보자. 현재 이 코드에는 여러가지 문제가 있다.
먼저 인풋을 넣자마자 종료되는 문제가 있는데, 이는 GameState 클래스의 IsGameOver 함수가 제대로 구현되지 않았기 때문이다. 게임은 특정 캐릭터의 Hp가 0이 되면 종료되어야 한다. 그러므로 다음과 같이 수정하면 된다.

public bool IsGameOver()
{
    foreach (Character character in Characters)
    {
        if (character.Hp == 0)
        {
            return true;
        }
    }
    return false;
}

 
다음으로 게임의 그리드가 갱신되지 않는 문제가 있다. 먼저 GameState의 Initialize 함수에서 Grid를 제대로 초기화해준다.

Grid = new char[5, 5] 
{
    {'.', '.', '.', '.', '.'},
    {'.', '.', '.', '.', '.'},
    {'.', '.', '.', '.', '.'},
    {'.', '.', '.', '.', '.'},
    {'.', '.', '.', '.', '.'},
};

 
다음으로 GameState 클래스에 UpdateGrid라는 함수를 만들고 게임 루프에서 호출하여, 현재 GameState이 갖고있는 모든 엔티티의 값을 Grid에 반영하도록 한다. 그리고 Grid 행렬에 Grid[x, y]가 아니라 Grid[y, x]의 형태로 넣는다.
 

public void UpdateGrid()
{
    for (int y = 0; y < Grid.GetLength(1); y++)
    {
        for (int x = 0; x < Grid.GetLength(0); x++)
        {
            Grid[y, x] = '.';
        }
    }

    foreach (int[] wall in Walls)
    {
        int x = wall[0];
        int y = wall[1];

        Grid[y, x] = 'w';
    }

    foreach (Character c in Characters)
    {
        int x = c.Position[0];
        int y = c.Position[1];

        Grid[y, x] = c.Type == "Knight" ? 'k' : 'a';
    }
}

 
다음으로 게임 상태를 표시해주는 PrintGameState 함수에서 캐릭터 부분을 다음과 같이 고친다.

// 제거 
Console.WriteLine("Character: " + character.GetType().Name);

// 추가
Console.WriteLine("Character: " + character.Type);

 
그리고 Grid를 출력해주는 부분에서 y의 출력순서를 역순으로 바꾸어준다. x와 y 순서도 바꾸어준다.

Console.WriteLine("Grid:");
for (int y = gameState.Grid.GetLength(1) - 1; y >= 0 ; y--)
{
    for (int x = 0; x < gameState.Grid.GetLength(0); x++)
    {
        Console.Write(gameState.Grid[y, x]);
    }
    Console.WriteLine();
}

 
다음으로 GetVectorFromDirection 함수에서 up을 (0, 1)로 down을 (0, -1)로 수정해준다.
 
여기까지 수정하고 나면 어느정도 동작하는것을 확인할 수 있다.

 
하지만 공격 메커니즘에 대한 부분은 완전히 미구현 상태이다. 먼저 AttackCharacter 함수를 구현하자.

static void AttackCharacter(Character character, int[] direction, GameState gameState)
{
    int[] newPosition = new int[] { character.Position[0] + direction[0], character.Position[1] + direction[1] };

    Character targetCharacter = 
        gameState.Characters.Find(c => c.Position[0] == newPosition[0] && c.Position[1] == newPosition[1]);

    if (targetCharacter != null)
    {
        targetCharacter.Hp -= character.Damage;
    }
}

 
다음으로 attack을 할 것인지 move를 할 것인지를 인풋으로 받도록 하고, 방향인풋과 합쳐서 행동을 수행하도록 메인 게임루프를 수정해야한다.
 

// Game loop
bool gameOver = false;
while (!gameOver)
{
    gameState.UpdateGrid();
    // Print current game state
    PrintGameState(gameState);

    // Get user input
    Console.WriteLine("Enter action (attack, move): ");
    string action = Console.ReadLine();

    Console.WriteLine("Enter direction (u, d, l, r): ");
    string dir = Console.ReadLine();

    int[] direction = GetVectorFromDirection(dir);

    if (direction != null)
    {
        if (action == "attack")
        {
            Character activeCharacter = gameState.GetActiveCharacter();
            AttackCharacter(activeCharacter, direction, gameState);
            gameState.SwitchTurn();
        }
        else if (action == "move")
        {
            // Move character
            Character activeCharacter = gameState.GetActiveCharacter();
            MoveCharacter(activeCharacter, direction, gameState);
            gameState.SwitchTurn();

        }
        else
        {
            Console.WriteLine("Not valid command.");
        }
    }

    // Check if game is over
    gameOver = gameState.IsGameOver();
}

 

그리고 PrintGameState 함수에서 wall의 위치를 출력해주도록 수정한다.

Console.Write("Walls: ");
foreach (int[] wall in gameState.Walls)
{
    Console.Write($"({wall[0]}, {wall[1]}) ");
}
Console.WriteLine();

 


이제 잘 동작한다.

 

 
수정된 전체 코드는 다음과 같다.

using System;
using System.Collections.Generic;

namespace ConsoleGame
{
	class Program
	{
		static void Main(string[] args)
		{
			// Initialize the game state
			GameState gameState = new GameState();
			gameState.Initialize();

			// Game loop
			bool gameOver = false;
			while (!gameOver)
			{
				gameState.UpdateGrid();
				// Print current game state
				PrintGameState(gameState);

				// Get user input
				Console.WriteLine("Enter action (attack, move): ");
				string action = Console.ReadLine();

				Console.WriteLine("Enter direction (u, d, l, r): ");
				string dir = Console.ReadLine();

				int[] direction = GetVectorFromDirection(dir);

				if (direction != null)
				{
					if (action == "attack")
					{
						Character activeCharacter = gameState.GetActiveCharacter();
						AttackCharacter(activeCharacter, direction, gameState);
						gameState.SwitchTurn();
					}
					else if (action == "move")
					{
						// Move character
						Character activeCharacter = gameState.GetActiveCharacter();
						MoveCharacter(activeCharacter, direction, gameState);
						gameState.SwitchTurn();

					}
					else
					{
						Console.WriteLine("Not valid command.");
					}
				}
				
				// Check if game is over
				gameOver = gameState.IsGameOver();
			}
		}

		static int[] GetVectorFromDirection(string direction)
		{
			int[] vector = null;

			switch (direction)
			{
				case "u":
					vector = new int[] { 0, 1 };
					break;
				case "d":
					vector = new int[] { 0, -1 };
					break;
				case "l":
					vector = new int[] { -1, 0 };
					break;
				case "r":
					vector = new int[] { 1, 0 };
					break;
				default:
					Console.WriteLine("Invalid direction!");
					break;
			}

			return vector;
		}

		static void AttackCharacter(Character character, int[] direction, GameState gameState)
		{
			int[] newPosition = new int[] { character.Position[0] + direction[0], character.Position[1] + direction[1] };

			Character targetCharacter = 
				gameState.Characters.Find(c => c.Position[0] == newPosition[0] && c.Position[1] == newPosition[1]);

			if (targetCharacter != null)
			{
				targetCharacter.Hp -= character.Damage;
			}
		}

		static void MoveCharacter(Character character, int[] direction, GameState gameState)
		{
			int[] newPosition = new int[] { character.Position[0] + direction[0], character.Position[1] + direction[1] };

			if (gameState.IsPositionEmpty(newPosition))
			{
				character.Position = newPosition;
				character.HasMoved = true;
			}
			else
			{
				Console.WriteLine("Can't move there!");
			}
		}

		static void PrintGameState(GameState gameState)
		{
			Console.WriteLine("Turn: " + gameState.Turn);
			Console.Write("Walls: ");
			foreach (int[] wall in gameState.Walls)
			{
				Console.Write($"({wall[0]}, {wall[1]}) ");
			}
			Console.WriteLine();

			foreach (Character character in gameState.Characters)
			{
				Console.WriteLine("Character: " + character.Type);
				Console.WriteLine("HP: " + character.Hp);
				Console.WriteLine("Damage: " + character.Damage);
				Console.WriteLine("Position: (" + character.Position[0] + ", " + character.Position[1] + ")");
			}

			Console.WriteLine("Grid:");
			for (int y = gameState.Grid.GetLength(1) - 1; y >= 0 ; y--)
			{
				for (int x = 0; x < gameState.Grid.GetLength(0); x++)
				{
					Console.Write(gameState.Grid[y, x]);
				}
				Console.WriteLine();
			}

			Console.WriteLine();
		}
	}

	public class Character
	{
		public string Type { get; set; }
		public int Hp { get; set; }
		public int Damage { get; set; }
		public int[] Position { get; set; }

		public bool HasMoved { get; set; }

		public Character(string type, int hp, int damage, int[] position)
		{
			Type = type;
			Hp = hp;
			Damage = damage;
			Position = position;
		}

		public void PrintCharacter()
		{
			Console.WriteLine($"{Type} (HP: {Hp}, Damage: {Damage}, Position: ({Position[0]}, {Position[1]}))");
		}
	}

	public class GameState
	{
		public string Turn { get; set; }
		public List<int[]> Walls { get; set; }
		public List<Character> Characters { get; set; }
		public char[,] Grid { get; set; }

		public void Initialize()
		{
			// Initialize the grid with empty cells
			Grid = new char[5, 5] 
			{
				{'.', '.', '.', '.', '.'},
				{'.', '.', '.', '.', '.'},
				{'.', '.', '.', '.', '.'},
				{'.', '.', '.', '.', '.'},
				{'.', '.', '.', '.', '.'},
			};

			// Create the walls
			Walls = new List<int[]>() 
			{
				new int[] {0, 0},
				new int[] {4, 2},
				new int[] {4, 4}
			};

			// Create the characters
			Characters = new List<Character>() 
			{
				new Character("Knight", 80, 10, new int[] {3, 3}),
				new Character("Archer", 60, 10, new int[] {3, 1})
			};

			// Set the initial turn to the player
			Turn = "Me";
		}

		public bool IsPositionEmpty(int[] position)
		{
			if (Grid[position[1], position[0]] != '.')
			{
				return false;
			}
			foreach (Character character in Characters)
			{
				if (character.Position[0] == position[0] && 
					character.Position[1] == position[1])
				{
					return false;
				}
			}
			return true;
		}

		public Character GetActiveCharacter()
		{
			string type;
			if (Turn == "Me")
				type = "Knight";
			else
				type = "Archer";

			foreach (Character character in Characters)
			{
				if (character.Type == type)
				{
					return character;
				}
			}
			return null;
		}

		public void SwitchTurn()
		{
			if (Turn == "Me")
			{
				Turn = "You";
			}
			else
			{
				Turn = "Me";
			}
		}

		public bool IsGameOver()
		{
			foreach (Character character in Characters)
			{
				if (character.Hp == 0)
				{
					return true;
				}
			}
			return false;
		}

		public void UpdateGrid()
		{
			for (int y = 0; y < Grid.GetLength(1); y++)
			{
				for (int x = 0; x < Grid.GetLength(0); x++)
				{
					Grid[y, x] = '.';
				}
			}

			foreach (int[] wall in Walls)
			{
				int x = wall[0];
				int y = wall[1];

				Grid[y, x] = 'w';
			}

			foreach (Character c in Characters)
			{
				int x = c.Position[0];
				int y = c.Position[1];

				Grid[y, x] = c.Type == "Knight" ? 'k' : 'a';
			}
		}
	}

}

 
 

결론

꽤 대단하긴 하지만 아직 사이즈가 큰 게임과 같은 개발은 Chat GPT에게 맡기긴 어려울 것 같다. 일단 기획에 대한 내용을 챗봇에게 학습시키는 과정에서 잘 이해하는 것 같지만 막상 같이 게임을 플레이해보면 게임 상태를 유지해주지 못한다. 계속 사용자쪽에서 정정해주어야한다. 그리고 개발하는 내내 두더지 잡기 하는 것처럼 A 요구사항을 충족시키도록 하면 B가 안되고, 다시 B를 요구하면 A가 안되는 상황이 반복되었다. 물론 대략적인 코드를 잡아주긴 하지만, 결국 Chat GPT가 만들어준 코드 조각들을 활용하여 완성시키기 위해서는 전체 코드를 이해할 수 있는 개발자가 필요하다.
(아직까진 밥그릇을 지킬 수 있을 것 같다.)