25.10.14 개발일지(C# 개인 프로젝트 게임 만들기)

2025. 11. 16. 18:15·10월 개발일지

 

25.10.14 개발일지

[C# 개인 프로젝트 게임 만들기]

 

 

서버-클라이언트 구조 구현

using System.Net;
using System.Net.Sockets;

namespace Server
{
    internal class Program
    {
        static TcpListener? listener;
        static readonly List<ClientSession> waiting = new();
        static readonly object gate = new();
        static readonly Database db = new();

        static async Task Main(string[] args)
        {
            Console.OutputEncoding = System.Text.Encoding.UTF8;
            Console.WriteLine("[Penalty Server] starting on :9000 ...");
            listener = new TcpListener(IPAddress.Any, 9000);
            listener.Start();

            _ = Task.Run(MatchMakerLoop);

            while (true)
            {
                var tcp = await listener.AcceptTcpClientAsync();
                _ = Task.Run(() => HandleClient(tcp));
            }
        }

        static async Task HandleClient(TcpClient tcp)
        {
            var session = new ClientSession(tcp);
            Console.WriteLine($"[Connect] {session.EndPoint}");
            try
            {
                await session.SendAsync("HELLO");

                while (tcp.Connected)
                {
                    var line = await session.ReadLineAsync();
                    if (line == null) break;

                    if (line.StartsWith("REGISTER "))
                    {
                        var sp = line.Split(' ', StringSplitOptions.RemoveEmptyEntries);
                        if (sp.Length >= 3 && db.Register(sp[1], sp[2]))
                        {
                            session.Username = sp[1];
                            await session.SendAsync("REGISTER_OK");
                        }
                        else await session.SendAsync("REGISTER_FAIL");
                    }
                    else if (line.StartsWith("LOGIN "))
                    {
                        var sp = line.Split(' ', StringSplitOptions.RemoveEmptyEntries);
                        if (sp.Length >= 3 && db.Login(sp[1], sp[2]))
                        {
                            session.Username = sp[1];
                            await session.SendAsync("LOGIN_OK");
                        }
                        else await session.SendAsync("LOGIN_FAIL");
                    }
                    else if (line == "READY")
                    {
                        if (string.IsNullOrEmpty(session.Username))
                        {
                            await session.SendAsync("NEED_LOGIN");
                            continue;
                        }
                        lock (gate)
                        {
                            if (!waiting.Contains(session)) waiting.Add(session);
                        }
                        await session.SendAsync("QUEUED");
                    }
                    else if (line.StartsWith("SHOOT:") || line.StartsWith("SAVE:"))
                    {
                        session.CurrentMatch?.OnPlayerActionAsync(session, line);
                    }
                    else if (line == "PING") { await session.SendAsync("PONG"); }
                    else { await session.SendAsync("ERR"); }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"[Err] {ex.Message}");
            }
            finally
            {
                Console.WriteLine($"[Disconnect] {session.EndPoint}");
                lock (gate) waiting.Remove(session);
                if (session.CurrentMatch != null) await session.CurrentMatch.AbortAsync(session);
                session.Dispose();
            }
        }

        static async Task MatchMakerLoop()
        {
            while (true)
            {
                await Task.Delay(200);
                ClientSession? a = null, b = null;
                lock (gate)
                {
                    if (waiting.Count >= 2)
                    {
                        a = waiting[0];
                        b = waiting[1];
                        waiting.RemoveRange(0, 2);
                    }
                }
                if (a != null && b != null)
                {
                    var match = new Match(a, b, db);
                    _ = match.RunAsync();
                }
            }
        }
    }
}
 

기존에 1p로만 가능한 페널티킥 게임에서

서버-클라이언트 구조를 만들어서 클라이언트 2명이 키커와 골키퍼를 번갈아가면서 게임할 수 있게 만들었다.

로그인 해서 2명의 클라이언트가 2p로 게임 가능

내일 ui 좀 더 손볼 예정이다.

: 서버 콘솔 화면

DB 연결

CREATE DATABASE IF NOT EXISTS penaltydb CHARACTER SET utf8mb4;
USE penaltydb;

CREATE TABLE IF NOT EXISTS users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    username VARCHAR(50) UNIQUE NOT NULL,
    password VARCHAR(255) NOT NULL,
    wins INT DEFAULT 0,
    losses INT DEFAULT 0,
    games_played INT DEFAULT 0,
    `rank` VARCHAR(20) DEFAULT 'Bronze'
);

CREATE TABLE IF NOT EXISTS match_history (
    match_id INT AUTO_INCREMENT PRIMARY KEY,
    player1 VARCHAR(50),
    player2 VARCHAR(50),
    winner  VARCHAR(50),
    score   VARCHAR(20),
    played_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
 

로그인/회원가입 회원정보와 매치 기록을 DB에 저장한다.

이후 이 매치 기록을 이용해서 랭크 시스템도 만들 예정이다.

 

 

'10월 개발일지' 카테고리의 다른 글

25.10.16 개발일지(C# 개인 프로젝트 게임 만들기)  (0) 2025.11.17
25.10.15 개발일지(C# 개인 프로젝트 게임 만들기)  (0) 2025.11.16
25.10.13 개발일지(이것이 C#이다 chapter 21, 22)  (0) 2025.11.16
25.10.06 개발일지(이것이 C#이다 chapter 20)  (0) 2025.11.16
25.10.05 개발일지(이것이 C#이다 chapter 13, 19)  (0) 2025.11.16
'10월 개발일지' 카테고리의 다른 글
  • 25.10.16 개발일지(C# 개인 프로젝트 게임 만들기)
  • 25.10.15 개발일지(C# 개인 프로젝트 게임 만들기)
  • 25.10.13 개발일지(이것이 C#이다 chapter 21, 22)
  • 25.10.06 개발일지(이것이 C#이다 chapter 20)
dldmstj4378
dldmstj4378
dldmstj4378 님의 블로그 입니다.
  • dldmstj4378
    dldmstj4378 님의 블로그
    dldmstj4378
  • 전체
    오늘
    어제
    • 분류 전체보기 (136)
      • 비전 검사 (0)
      • 11월 개발일지 (6)
      • 10월 개발일지 (15)
      • 9월 개발일지 (26)
      • 8월 개발일지 (20)
      • 7월 개발일지 (26)
      • 6월 개발일지 (27)
      • 5월 개발일지 (16)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
dldmstj4378
25.10.14 개발일지(C# 개인 프로젝트 게임 만들기)
상단으로

티스토리툴바