상세 컨텐츠

본문 제목

2048 콘솔 게임.

C#/과제

by McRobbin 2020. 5. 1. 22:56

본문

콘솔을 이용한 2048 게임을 만들었습니다.

 

주요 기능.

1. 게임하는 중간에 저장을 하며 강제 종료시 기존 게임을 불러와 할 수 있습니다.

2. 새로 시작할 시 이전 데이터를 무시하고 새게임을 시작할 수 있습니다.

3. 새 게임을 시작해도 계속해서 쌓이는 총 점수를 보여줍니다.

4. 게임 설정을 하고 이를 저장합니다. 타일의 사이즈, 난이도, 점수 획득량이 있습니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
using System;
using System.Collections.Generic;
using System.IO;
 
 
namespace _2048Game
{
    public class App
    {
 
        public int moveCount;
        public GameInfo gameInfo;
 
        public App()
        {
            this.LoadGameMapInfo();
 
            while (true)
            {
                Console.WriteLine("명령어를 입력해 주세요.");
                Console.Write("1 : 기존 게임 시작, 2 : 새로운 게임 시작, 3 : 설정 변경.");
                int command = int.Parse(Console.ReadLine());
 
                switch (command)
                {
                    case 1:
                        gameInfo.PrintGameMap();
                        this.RunGame();
                        break;
                    case 2:
                        this.gameInfo = new GameInfo(gameInfo.TotalScore, gameInfo.gameSetting);
                        this.gameInfo.PrintGameMap();
                        this.RunGame();
                        break;
                    case 3:
                        this.ReSetGameSettingProcess();
                        this.gameInfo.SaveGameInfo();
                        break;
                    default:
                        Console.WriteLine("잘못된 명령어 입니다.\n");
                        break;
                }
 
            }
        }
 
        public void RunGame()
        {
            while (true)
            {
                Console.WriteLine("===================");
                
                if (gameInfo.isFull())
                {
                    gameInfo.ClearMap();
                    gameInfo.SaveGameInfo();
                    this.moveCount = 0;
                    gameInfo.ClearScore();
                    Console.WriteLine("게임 오버.");
                    return;
                }
 
                //게임 키 입력.
                ConsoleKey key = Console.ReadKey(false).Key;
                if (key == ConsoleKey.Escape)
                {
                    Console.WriteLine("게임 종료.");
                    return;
                }
                else
                    this.GetKeyProcess(key);
 
                //랜덤으로 타일 추가.
                gameInfo.AddRandomTile(moveCount++);
 
                //게임 맵 프린트.
                gameInfo.PrintGameMap();
 
                //게임 저장.
                gameInfo.SaveGameInfo();
            }
        }
 
        public void GetKeyProcess(ConsoleKey key)
        {
            switch (key)
            {
                case ConsoleKey.UpArrow:
                    Console.WriteLine("위쪽\t점수 : {0}\t토탈 점수 : {1}", gameInfo.Score, gameInfo.TotalScore);
                    gameInfo.SlideUpProcess();
                    break;
 
                case ConsoleKey.DownArrow:
                    Console.WriteLine("아래쪽\t점수 : {0}\t토탈 점수 : {1}", gameInfo.Score, gameInfo.TotalScore);
                    gameInfo.SlideDownProcess();
                    break;
 
                case ConsoleKey.LeftArrow:
                    Console.WriteLine("왼쪽\t점수 : {0}\t토탈 점수 : {1}", gameInfo.Score, gameInfo.TotalScore);
                    gameInfo.SlideLeftProcess();
                    break;
 
                case ConsoleKey.RightArrow:
                    Console.WriteLine("오른쪽\t점수 : {0}\t토탈 점수 : {1}", gameInfo.Score, gameInfo.TotalScore);
                    gameInfo.SlideRightProcess();
                    break;
 
                default:
                    break;
            }
            Console.Write('\n');
        }
 
        public void ReSetGameSettingProcess()
        {
            Console.Write("게임 사이즈 입력 (3 ~ 9 권장.) : ");
            int size = int.Parse(Console.ReadLine());
            Console.Write("게임 점수 배수 입력 : (5-박함 ~ 20-아주 많음) : ");
            int multiScore = int.Parse(Console.ReadLine());
            Console.Write("게임 난이도 입력 : (10-어려움 ~ 20-쉬움)");
            int difficulty = int.Parse(Console.ReadLine());
 
            gameInfo.gameSetting = new GameSetting(size, multiScore, difficulty);
        }
 
        public void LoadGameMapInfo()
        {
            string filePath = @"../game_map_info.json";
            if (File.Exists(filePath))
            {
                this.gameInfo = JsonConvert.DeserializeObject<GameInfo>(File.ReadAllText(filePath));
                Console.WriteLine("게임 맵 데이터 불러오기 완료.\n");
            }
 
            else
            {
                this.CreateGameMapInfo();
            }
        }
 
        public void CreateGameMapInfo()
        {
            this.gameInfo = new GameInfo();
            Console.WriteLine("새로운 게임 맵 생성 완료.\n");
            gameInfo.SaveGameInfo();
        }
 
    }
}
 
 
 

App.cs 파일 입니다.

유저 정보를 읽어오고 새로 쓰는것, 키를 입력받는 Process들이 있습니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
 
namespace _2048Game
{
    public class GameInfo
    {
        private int[,] map;
        public int[,] Map { get { return this.map; } }
        private int score;
        public int Score { get { return this.score; } }
        private int totalScore;
        public int TotalScore { get { return this.totalScore; } }
        public GameSetting gameSetting;
 
        public GameInfo(int totalScore = 0, GameSetting gameSetting = nullint[,] map = nullint score = 0
        {
            this.totalScore = totalScore;
            this.gameSetting = (gameSetting == null) ? gameSetting = new GameSetting() : gameSetting;
            this.map = (map == null) ? new int[gameSetting.mapSize, gameSetting.mapSize] : map;
            this.score = score;
        }
 
        public void AddRandomTile(int count)
        {
            //움직인 횟수 9마다 숫자가 1승씩 증가.
            int powerVal = count / gameSetting.difficulty + 1;
 
            //증가한 숫자에서 랜덤하게 뽑아냄.
            int addNum = (int)Math.Pow(2new Random().Next(1, powerVal));
            var addPos = this.GetEmptyRandomTile();
            map[addPos.yPos, addPos.xPos] = addNum;
        }
 
        public Position GetEmptyRandomTile()
        {
            var posList = new List<Position>();
            for(int row = 0; row < map.GetLength(0); row++)
            {
                for(int col = 0; col < map.GetLength(1); col++)
                {
                    if (map[row, col] == 0)
                        posList.Add(new Position(col, row));
                }
            }
            if (posList.Count == 0)
                return null;
 
            return posList[(new Random().Next(0posList.Count))];
        }
 
        public void PrintGameMap()
        {
            for(int row = 0; row < map.GetLength(0); row++)
            {
                for (int col = 0; col < map.GetLength(1); col++)
                    Console.Write("[{0}]\t", map[row, col]);
                Console.WriteLine();
            }
        }
 
        public bool isFull()
        {
            return this.GetEmptyRandomTile() == null;
        }
 
        public void SlideLeftProcess()
        {
 
            for (int row = 0; row < map.GetLength(0); row++)
            {
                this.MoveLeft(row);
                for(int col = 0; col < map.GetLength(1- 1; col++)
                {
                    //col 은 현재 칸, col + 1은 다음 칸.
 
                    //합쳐질 것들 먼저 확인.
                    if(map[row, col] == map[row, col + 1])
                    {
                        map[row, col] += map[row, col + 1];
                        map[row, col + 1= 0;
                        this.score += map[row, col] * gameSetting.scoreMultiAmount;
                        this.totalScore += map[row, col] * gameSetting.scoreMultiAmount;
                    }
                }
                this.MoveLeft(row);
            }
 
        }
 
        public void SlideRightProcess()
        {
            //같은 것 합치기.
            for(int row = 0; row < map.GetLength(0); row++)
            {
                this.MoveRight(row);
                for(int col = map.GetLength(1-1; col > 0; col--)
                {
                    if(map[row, col] == map[row, col - 1])
                    {
                        map[row, col] += map[row, col - 1];
                        map[row, col - 1= 0;
                        this.score += map[row, col] * gameSetting.scoreMultiAmount;
                        this.totalScore += map[row, col] * gameSetting.scoreMultiAmount;
                    }
                }
                this.MoveRight(row);
            }
        }
 
        public void SlideUpProcess()
        {
            for(int col = 0; col < map.GetLength(1); col++)
            {
                this.MoveUp(col);
                for(int row = 0; row < map.GetLength(0- 1; row++)
                {
                    if(map[row, col] == map[row + 1, col])
                    {
                        map[row, col] += map[row + 1, col];
                        map[row + 1, col] = 0;
                        this.score += map[row, col] * gameSetting.scoreMultiAmount;
                        this.totalScore += map[row, col] * gameSetting.scoreMultiAmount;
 
                    }
                }
                this.MoveUp(col);
            }
        }
 
        public void SlideDownProcess()
        {
 
            for (int col = 0; col < map.GetLength(1); col++)
            {
                this.MoveDown(col);
                for(int row = map.GetLength(0- 1; row > 0; row--)
                {
                    if(map[row, col] == map[row -1, col])
                    {
                        map[row, col] += map[row - 1, col];
                        map[row - 1, col] = 0;
                        this.score += map[row, col] * gameSetting.scoreMultiAmount;
                        this.totalScore += map[row, col] * gameSetting.scoreMultiAmount;
 
                    }
                }
                this.MoveDown(col);
            }
        }
 
        //왼쪽으로 당기기.
        public void MoveLeft(int row)
        {
            for(int col = 0; col < map.GetLength(1); col++)
            {
                if(map[row, col] == 0)
                {
                    for(int targetCol = col; targetCol < map.GetLength(1); targetCol++)
                    {
                        if(map[row, targetCol] != 0)
                        {
                            map[row, col] = map[row, targetCol];
                            map[row, targetCol] = 0;
                            break;
                        }
                    }
                }
            }
        }
 
        public void MoveRight(int row)
        {
            for(int col = map.GetLength(1- 1; col >= 0; col--)
            {
                if(map[row, col] == 0)
                {
                    for(int targetCol = col; targetCol >= 0; targetCol--)
                    {
                        if(map[row, targetCol] != 0)
                        {
                            map[row, col] = map[row, targetCol];
                            map[row, targetCol] = 0;
                            break;
                        }
                    }
                }
            }
        }
 
        public void MoveUp(int col)
        {
            for(int row = 0; row < map.GetLength(0); row++)
            {
                if(map[row, col] == 0)
                {
                    for(int targetRow = row; targetRow < map.GetLength(1); targetRow++)
                    {
                        if(map[targetRow, col] != 0)
                        {
                            map[row, col] = map[targetRow, col];
                            map[targetRow, col] = 0;
                            break;
                        }
                    }
                }
            }
        }
 
        public void MoveDown(int col)
        {
            for(int row = map.GetLength(0- 1; row >= 0; row--)
            {
                if(map[row, col] == 0)
                {
                    for(int targetRow = row; targetRow >= 0; targetRow--)
                    {
                        if(map[targetRow, col] != 0)
                        {
                            map[row, col] = map[targetRow, col];
                            map[targetRow, col] = 0;
                            break;
                        }
                    }
                }
            }
        }
 
        public void SaveGameInfo()
        {
            string filePath = @"../game_map_info.json";
            File.WriteAllText(filePath, JsonConvert.SerializeObject(this));
            Console.WriteLine("게임 맵 저장 완료.\n");
        }
 
        public void ClearMap()
        {
            this.map = new int[gameSetting.mapSize, gameSetting.mapSize];
        }
 
        public void ClearScore()
        {
            this.score = 0;
        }
    }
}
 
 
 

GameInfo.cs 입니다.

게임의 맵과 옮기고 합치는 등의 기능이 있습니다.

점수와 설정 정보를 함께 가지고 있습니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
 
namespace _2048Game
{
    public class GameSetting
    {
        public int mapSize;
 
        public int scoreMultiAmount;
 
        public int difficulty;
 
        public GameSetting(int mapSize = 4int scoreMultiAmount = 5int difficulty = 8)
        {
            this.mapSize = mapSize;
            this.scoreMultiAmount = scoreMultiAmount;
            this.difficulty = difficulty;
        }
 
        public void SaveGameSetting()
        {
            var filePath = @"../game_setting_info.json";
            File.WriteAllText(filePath, JsonConvert.SerializeObject(this));
            Console.WriteLine("게임 세팅 저장 완료.\n");
        }
 
 
    }
}
 
 
 

GameSetting.cs 입니다.

게임을 세팅 정보를 가지고 있습니다. 사이즈, 점수 획득량, 난이도를 가지고 있습니다.

게임세팅 인스턴스는 게임 인포가 가지고 있습니다.

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace _2048Game
{
    public class Position
    {
        public int xPos;
        public int yPos;
 
        public Position(int xPos, int yPos)
        {
            this.xPos = xPos;
            this.yPos = yPos;
        }
    }
}
 
 
 

Position.cs 입니다.

일부 메서드에서 자리를 찾기 위해 사용합니다.

x, y좌표가 전부입니다.

 

 

Program.cs는 new App()의 내용만 있으며 대리자를 이용한 강제종료는 구현하지 않았습니다.

 

2048Game.zip
5.74MB

프로젝트 파일을 올리고 과제 마치겠습니다.

'C# > 과제' 카테고리의 다른 글

Unity 5Runs 과제.  (0) 2020.05.09
과제 - 롤 챔프, 스킨 구매 시뮬레이션..?  (0) 2020.04.30
레시피 과제.  (0) 2020.04.17
홍길동과 임꺽정의 전투 클래스 사용.  (0) 2020.04.10
과제 04-03  (0) 2020.04.03

관련글 더보기