4차산업혁명의 일꾼/Java&Spring웹개발과 서버 컴퓨터

파이썬프로그래밍 기초

르무엘 2023. 2. 23. 22:42

[목차]

[1]  컴퓨터의 이해

주요용어

  1. 데이터: 어떤 현상이나 사실에 대한 설명 또는 설명의 집합
  2. 정보: 문제 또는 질문을 해결하기 위해 사용할 수 있는 데이터와 데이터의 집합
  3. 프로그램: 컴퓨터가 어떠한 작업을 자동으로 처리할 수 있도록 처리 방법 및 순서를 컴퓨터가 이해할 수 있는 언어 형태로 기술한 것
  4. 알고리즘: 문제를 풀기 위한 단계별 절차를 체계적 명령의 형태로 기술한 것

 

정리하기

  1. 데이터란 관찰이나 측정을 통해 얻은 수치, 문자와 같은 변할 수 있는 질적 또는 양적 값을 뜻한다.
  2. 정보란 데이터를 처리하여 실제 문제해결에 도움이 될 수 데이터를 정리한 결과물을 뜻한다. 데이터 처리에는 정렬, 합산, 군집화 등의 작업이 동반된다.
  3. 컴퓨터는 데이터를 외부로부터 받아들이는 입력기능, 내부 장치를 조정하는 제어기능, 입력된 데이터를 저장하는 저장⦁기억기능, 계산을 수행하는 연산기능, 내부의 데이터를 사용자에게 전달하는 출력기능을 갖추고 있다.
  4. 디지털 컴퓨터는 0과 1이라는 신호만으로 동작하기 때문에, 데이터 및 명령문 또한 0과 1로 표현되어야 한다. 즉, 수나 문자, 명령어 모두 0과 1로 표현된다.
  5. 프로그램이란 컴퓨터가 어떠한 작업을 자동으로 처리할 수 있도록, 처리 방법 및 순서를 컴퓨터가 이해할 수 있는 언어로 기술해 놓은 것을 뜻한다. 프로그램을 제작하는 사람을 프로그래머라고 하며, 이 제작 과정은 프로그래밍이라 부른다.
  6. 알고리즘은 문제를 풀기 위한 단계별 절차를 수학적으로 기술한 것을 뜻한다. 알고리즘에는 입력과 출력이 있어야 하며, 명확성과 유한성, 효율성이 보장되어야 한다.
  7. 프로그램은 프로그래밍 언어를 이용하여 알고리즘을 구현한 결과이며, 프로그래밍 언어로 작성된 소스코드를 컴파일러나 인터프리터를 통해 컴퓨터에서 실행될 수 있는 프로그램으로 생성된다

 

[2] 컴퓨터의 구성

 주요용어

  1. 폰노이만 구조: CPU, 메모리, 프로그램 구조를 갖는 범용 컴퓨터 구조

정리하기

  1. 중앙처리장치는 연산, 비교, 판단을 수행하는 연산장치와 명령어를 해석하고 실행하는 제어장치로 구성된다.
  2. 주기억장치는 컴퓨터에서 처리할 데이터와 프로그램을 기억하고, 처리결과를 기억하는 장치이며 보조기억장치는 주기억장치를 보완하여 컴퓨터 전원이 차단되었다가 다시 컴퓨터를 켰을 때, 주기억장치에 데이터를 불러 올 수 있도록 영구적으로 저장하는 역할을 한다.
  3. 시스템 소프트웨어는 응용 소프트웨어를 실행하기 위한 환경을 제공하고 하드웨어를 제어·관리할 수 있도록 설계된 컴퓨터 소프트웨어이다.
  4. 시스템 소프트웨어 종류에는 운영체제는 사용자가 컴퓨터를 효율적으로 운영·관리·사용할 수 있도록 하드웨어를 제어하는 운영체제, 고급언어로 작성된 프로그램을 컴퓨터가 이해할 수 있는 기계어로 번역해 주는 컴파일러, 그리고 사용자가 컴퓨터를 효율적이고 편리하게 사용할 수 있도록 지원해 유틸리티 등이 있다.
  5. 운영체제는 중앙처리장치, 주기억장치, 보조기억장치와 같은 장치로 구성되는 컴퓨터의 하드웨어를 작동시켜 사용자가 원하는 작업을 처리할 수 있는 환경을 제공하고 컴퓨터와 사용자 사이에 중계 역할을 한다.

 

[3] 파이썬의 이해

2.0 <-> 3.0 호환 잘안되고 문법오류

 

*주요용어

  • 프로그래밍 패러다임: 프로그래밍을 생성하는 접근 방식
  • 주피터 노트북: 오픈소스 웹 기반 대화형 개발 및 실행 환경

*정리하기

  1. 파이썬은 명령형 프로그래밍, 절차적 프로그래밍, 객체지향 프로그래밍, 함수형 프로그래밍 패러다임을 지원한다.
  2. 파이썬은 교육적인 목적뿐만 아니라 응용 프로그램과 웹, 백 엔드 개발, 사물 인터넷 등 다양한 분야에 활용된다
  3. 파이썬은 파이썬 확장 제안(PEP)를 통해 새로운 파이썬의 기능, 파이썬 프로세스, 환경에 대해 커뮤니티에 설계 문서나 정보를 제공하는 등 많은 개발자의 의견을 수용하고 토론하며 발전한 언어이다.
  4. 파이썬은 플랫폼에 독립적이며 인터프리터식 객체지향적, 동적 타이핑(dynamically typed) 대화형 언어이다.
  5. 파이썬 소스 코드는 파이썬 인터프리팅 과정에서 CPython에 의해 바이트 코드로 변환되고, 파이썬 가상머신(PVM)이 한 라인씩 기계어 코드로 변환하여 실행된다.
  6. 파이썬 개발 환경에는 구문 강조, 자동 완성, 스마트 들여쓰기 등의 기능을 지원하는 IDLE, 주피터 노트북, 구글 코랩 등이 있다.
  7. 구글 코랩(Colab)은 주피터 노트북과 구글 드라이브를 결합한 서비스로 데이터 분석 및 딥러닝 연산 등 고성능 컴퓨팅 리소스 활용 가능하다.

 

< 다양한 라이브러리>

PyTorch ,TensorFlow - 딥러닝 , Numpy , Numba, SymPy : 숫자 , matpltlib, Bokeh, pandas- 수치, 함수 만들고 그래프

IP, yupyter, lab : 개발환경,  Flask , dj : 프레임워크      ,  astropy, biopython, sunpy - 연구특화

 

<파이썬의 단점>

- C나 자바 보다 느린 속도

- 완전한 애플리케이션 단독 개발이 불가능

-> 쉘스크립트 언어용으로 개발 => 모바일 앱 등 응용 어플리케이션 개발 불가 (=> Rust 나 Go 로 PC, 모바일 어플리케이션 개발이 낫다)

 

[4] 파이썬 시작하기

*주요용어

  1. 산술연산자: 피연산자(operand)에 대해 지정된 산술 연산을 지시하는 기호
  2. 내장함수: 별도의 라이브러리 없이 파이썬 인터프리터에서 기본적으로 지원하는 함수

*정리하기

  1. 피연산자와 기본연산자(+, -, *, /, **)를 이용한 표현식은 파이썬 인터프리터에 의해 자동 계산된다.
  2. 주석은 개발 속도 향상시키고 유지보수를 용이하게 하는 중요한 설명이다. 주석은 #과 """을 사용한다.
  3. 프로그래밍 언어에서만 사용되는 산술연산자로 정수 나눗셈 연산자(//) 모듈로 연산자(%)가 있다.
  4. 연산자 우선순위는 표현식에 사용된 여러 연산자의 연산 순서를 결정한다.
  5. 파이썬 내장 함수는 별도의 모듈이나 패키지 없이 파이썬 인터프리터에서 기본적으로 지원하는 함수이다.

 

[4] 순차구조

*주요용어

  1. 제어구조: 프로그램의 실행 흐름을 결정하는 구조
  2. 순차구조: 실행의 흐름을 주어지는 명령의 위치적 흐름에 따라 수행하는 구조
  3. 프로그래밍 에러: 설계 미숙, 결함 또는 문법 오류로 프로그램이 의도한 대로 결과를 생성하지 못하는 문제 상황
  4. 데이터 타입 변환: 한 데이터의 타입을 다른 데이터 타입으로 전환하는 과정

*정리하기

  1. 파이썬은 구조적 프로그래밍 패러다임을 지원하며 goto 문을 사용하지 않고 프로그램을 구성할 수 있는 순차, 선택, 반복 구조를 제공한다.
  2. 순차 구조는 실행의 흐름을 주어지는 명령의 위치적 흐름에 따라 수행하는 구조이다.
  3. 선택 구조는 특정 영역 내의 명령문에 대한 실행 여부를 프로그램 실행 과정 중 조건에 따라 결정하는 구조이다.
  4. 반복 구조는 특정 영역의 명령문을 조건에 따라 여러 번 재실행하는 구조이다.
  5. input 함수는 사용자로부터 데이터를 입력 받아, 문자 데이터 타입으로 반환한다.
  6. 프로그래밍 에러는 설계 미숙, 결함 또는 문법 오류로 프로그램이 의도한 대로 결과를 생성하지 못하는 현상이며 구문 오류, 실행 오류, 의미 오류로 구분된다.
  7. 데이터 타입을 다른 데이터 타입으로 전환하기 위해 str, int, float 함수를 사용한다.
  8. print 함수는 여러 개의 데이터를 단일 print 함수로 출력 가능하며, 콤마(,)로 파라미터를 구분하여 입력한다.

 

[4] 순차구조

*주요용어

  1. 선택 구조: 특정 영역 내의 명령문에 대한 실행 여부를판단에 따라 결정하는 구조
  2. 불리언 타입: 논리값인 참(True)과 거짓(False)의 값만 표현할 수 있는 데이터 타입
  3. 논리연산자: 두 개의 논리값(불리언식)을 연산하여 참 또는 거짓을 결과로 얻는 연산자

*정리하기

  1. 단락평가란 첫 번째 논리값 만으로 전체 연산 결과가 판별 가능할 때 두 번째 논리값은 확인(평가)하지 않는 기법이다.
  2. if, elif, else 명령어를 사용하여 이분 또는 다분 선택구조로 확장할 수 있다.
  3. 중첩 선택구조는 한 선택구조 내부에 또 다른 선택구조를 내포하는 구조이다.

 

[5] 반복구조

*주요용어

  1. 조건 제어 반복: 참과 거짓 조건에 의해 반복 여부가 결정되는 반복 구조
  2. 계수 제어 반복: 특정 계수만큼 반복 횟수가 정해진 반복 구조
  3. 인덱스 연산자: 시퀀스 타입의 원소에 접근하는 연산자
  4. 중첩 반복 구조: 반복 구조 내 다른 반복 구조를 내포한 형식

 

*정리하기

  1. 반복 구조란 동일한 명령문에 대해서 사용자가 지정한 횟수만큼 또는 조건을 만족하는 동안 동일한 코드를 반복하여 수행할 때 사용하는 구조이다.
  2. whlie 문은 조건이 참(True)인 동안 while 문 블럭 내부의 명령문을 수행하며 조건이 거짓(False)이 될 때 while문을 빠져나오는 조건 제어 반복 구조이다.
  3. 리스트는 순서화된 값의 집합체를 저장할 수 있는 시퀀스 데이터 타입의 일종이다.
  4. for 문은 리스트 등과 같은 시퀀스의 첫 번째 요소부터 마지막 요소까지 하나씩 변수에 대입하여 블럭의 명령문을 수행하며 마지막 요소까지 수행한 후 종료하는 계수 제어 반복이다.
  5. 중첩 반복 구조는 하나의 외부 반복 구조에 여러 개의 내부 반복 구조가 중첩되어 사용되는 구조를 말하며, 외부 반복 구조가 매 반복될 때마다 내부 반복 구조에 재진입하여 새롭게 실행된다.

[6] 함수

*주요용어

  1. 동시 할당: 복수 개의 변수에 값을 동시에 할당하는 명령
  2. 스코프: 프로그램에서 변수가 참조될 수 있는 영역
  3. 기본 매개변수: 함수 호출 시 매개변수가 전달되지 않을 경우 기본값이 전달되는 매개변수
  4. 가변 매개변수: 함수 호출 시 매개변수를 사용자가 원하는 개수 만큼 지정할 수 있는 매개변수

*정리하기

  1. 값의 전달에 의한 호출이란 함수 호출 시 함수 내부에는 매개변수의 값이 전달된다.
  2. 기본 매개변수란 함수 호출 시 매개변수가 전달되지 않을 경우 기본값이 전달되는 매개변수를 말한다.
  3. 함수 호출 시 매개변수를 사용자가 원하는 개수 만큼 지정할 수 있는 매개변수를 가변 매개변수라고 하며, 함수 정의 시 매개변수 이름 앞에 *를 사용한다.

 

[7] 객체지향

*주요용어

  1. 객체지향: 객체와 객체 사이의 상호작용으로 프로그램을 구성하는 프로그래밍 패러다임
  2. 클래스: 실세계의 객체에 대한 데이터와 연산을 표현한 단위
  3. 초기자: 객체의 상태를 초기화하는 특수 메소드
  4. 객체 멤버 접근 연산자: 객체의 데이터 필드 접근 및 메소드 호출에 사용되는 연산자

*정리하기

  1. 모든 메소드의 첫 번째 매개변수는 self이다.
  2. 클래스의 생성자(constructor)호출을 통해 클래스의 인스턴스인 객체가 생성된다. 클래스의 생성자는 클래스의 이름과 동일하며 초기자의 매개변수를 사용한다.
  3. 객체의 데이터 필드 접근 및 메소드 호출에 객체 멤버 접근 연산자( . )를 사용한다.
  4. private 데이터 필드는 클래스 내부에서만 접근 가능하며 앞 두 밑줄(__)로 정의한다.
  5. private 데이터 필드에 대해 접근하기 위한 접근자 변경자 메소드가 정의되어야 한다.

 

구구단 만들기

* 파이썬 문자열 형식- format(" " , ">20s")  : 20스페이스 다음 시작

* range (초기, 범위  ,스텝)

* print( i   , "|" , end="")   프린트 한줄 계속

# 문자열 형식 format  >20s
print(format("구구단표", ">20s"))

# 새로운 행 삽입
print()    
print("-----------------------------------")

# 구구단 표 출력 
for i in range(1,10 ,1):
    print(i , "|", end="")
    for j in range(1,10,) :
        # 정수 형식 format  >3d
        print( format(i *j, ">3d") , end="")        
    print()

 

#원 뿔 높이 계산
rad_list = range(10,31,10)
hei_list = [1,5,14,26,31]

for rad,hei in zip(rad_list, hei_list):
    vol = 1/3 * 3.14 * rad **2 * hei
    surf = 3.14 * rad **2 +3.14 * rad * hei
    print("반지름", rad , "높이" ,  hei, "원뿔")
    print("원뿔의 부피는" , vol, "입니다.")
    print("원뿔의 겉넓이는" , surf , "입니다.")

** 이 들어가면 제곱

pow(i,j)가 들어가면  i의 j승이 된다

 

 

[8]  모듈

*주요용어

  1. 모듈: 함수, 상수 또는 클래스를 모아 놓은 집합체
  2. 네임스페이스: 특정 객체를 이름에 따라 구분할 수 있는 범위
  3. 난수: 특정한 배열 순서나 규칙적인 의미가 없는, 임의의 수를 의미

 

*정리하기

  1. 모듈, 패키지, 라이브러리는 구분되는 개념이며 패키지는 하위 패키지 및 모듈의 집합, 라이브러리는 패키지 및 모듈의 집합으로 구성되는 상위 개념이다.
  2. 모듈 등록 시 import 구문과 from import 구문을 사용한다. import 구문을 통해 등록된 모듈은 사용시 모듈이름 또는 별칭을 변수/함수/클래스 앞에 붙여야 한다.
  3. import는 파이썬 모듈을 프로그램 내부에서 사용할 수 있게 네임스페이스에 추가하는 기능을 수행한다.
  4. dir 함수는 네임스페이스에 등록되어 있는 모든 이름들을 리스트로 반환한다.
  5. help 함수는 대화형 도움말 시스템 호출 또는 클래스나 메소드의 사용방법을 반환한다.
  6. 네임스페이스는 특정 객체를 이름에 따라 구분할 수 있는 범위를 나타낸다.
  7. del 명령어는 네임스페이스 내 등록된 모듈의 멤버 식별자를 제거한다.
  8. math 모듈은 수학적 계산 문제를 해결하기 위한 수학 함수 및 상수의 집합으로 구성된다.
  9. random은 난수 관련된 기능을 제공하는 모듈이다.
  10. time은 에포크 시간을 얻어 다양한 형식으로 표시하는 기능 제공하는 모듈이다.

 

 

 

 

import math
import random
from math import sin

# a, b = 10, 20
# area = 1 / 2 * a * b * sin(math.radians(60)) 
# print(area)

guess_str = input("1~45 번호 6개를 쉼표로 분리하여 입력하세요:").split(",")
guess_list = list()

for i in guess_str:
    guess_list.append(int(i))

lotto_list = random.sample(range(1,46,1), 6)

print("예상번호는", guess_list, "입니다.")
print("추첨번호는", lotto_list, "입니다.")

hit_count =0;

#print(lotto_list)
for guess in guess_list:
    if guess in lotto_list:
        hit_count = hit_count+1

print("축하합니다." +str(hit_count) + "개 맞췄습니다.")

 

 

# 20번의 기회 안에 1~1000 사이의 숫자를 맞히는 스무고개 프로그램을 작성하시오

import random

hit_number = random.randint(1,1001)
#print( hit_number)
#guess = int(input("숫자를 맞혀보세요: "))
guess_count_list = range(1,21,1)

passfail = False

for guess_count in guess_count_list :

    guess = int(input("숫자를 맞혀보세요: (" +str(guess_count) + "번째 시도 ): "))

    if hit_number == guess:
        passfail = True
        break;
    elif hit_number > guess:
        print(str(guess)+ "보다 큽니다.", end="")
    else:
        print(str(guess)+ "보다 작습니다.", end="")

if passfail == True:
    print("맞췄습니다. 축하합니다.")
else:
    print("모든 기회를 다 사용하셨습니다. 다음에 다시 도전하세요.")

 

 

import time

def is_prime(x):
    for i in range(2,x):
        if x % i == 0:
            return False
    return True

prime_count=0


start_time = time.time()

for i in range(2,5001):
    if is_prime(i):
        prime_count = prime_count + 1
        print(i , end=", ")

end_time = time.time()
print(end_time - start_time , "초 실행했습니다.")

 

[9]  파일

*주요용어

  1. 파일 이름: 파일 경로를 내포하는 파일의 고유 식별자
  2. 파일 포인터: 파일 내부에서 작업 위치를 나타내는 포인터
  3. 딕셔너리: 키와 값의 쌍을 저장하는 시퀀스

*정리하기

  1. 컴퓨터에 의해 처리될 또는 처리된 데이터와 정보가 임시적으로 연속된 바이트의 형태로 저장된 상태이다.
  2. 파일은 연속된 바이트와 파일의 시작, 파일 포인터, 파일의 끝(EoF)으로 구성된다.
  3. 파일은 데이터가 저장되는 방식에 따라 텍스트 파일 바이너리 파일로 구분된다.
  4. 파이썬은 인터프리터에서 파일의 시작, 파일 포인터, 파일의 끝을 활용하여 데이터 읽기, 쓰기를 위한 함수를 제공한다.
  5. 파일은 파일 객체 생성, 읽기/쓰기/추가하기 작업, 파일 객체 삭제 과정을 통해 처리된다.
  6. 파일의 이름은 파일의 고유 식별자 역할 및 저장장치 내부에서 파일의 위치를 표현하는 파일경로를 내포한다.
  7. 딕셔너리는 키와 값의 쌍(pair)을 저장하는 시퀀스이다.

# 파일열기
h_fp = open("Hamlet_by_Shakespeare.txt","r")

# 딕셔너리 만들기
word_dict = dict()

# readlines 줄읽기
for line in h_fp.readlines():
    # strip 줄이고 split 자름
    for word in line.strip().split():
        word = word.strip(" .,;?[]\"\':-!").lower()

        # wh
        if word_dict.get(word) is not None:
            count = word_dict[word]
        else :
            count =0

        word_dict[word] = count+1

word_r_dict = {v:k for(k,v) in word_dict.items() }

word_dict = {k:v for (v,k) in sorted(word_r_dict.items() ,reverse =True ) }

for key in word_dict :
    if word_dict[key] >=100:
        print("["+ key+  "]" , str(word_dict[key]) + "회" ) 

h_fp.close()

 

[10]  실전프로젝트 1

*주요용어

  1. 소프트웨어 개발 라이프사이클: 소프트웨어 개발 계획 수립부터 폐기까지 신뢰도 높은 소프트웨어 결과물 구현을 위한 체계화된 소프트웨어 개발 체계

*정리하기

  1. 소프트웨어 개발 라이프사이클은 대규모 소프트웨어 개발 시 자원을 투입하여 초기에 예상한 대로 결과물 구현을 목적으로 한다.
  2. 소프트웨어 개발 라이프사이클은 계획, 분석, 설계, 구현, 테스트, 유지보수의 순서로 진행된다.
  3. 배치 프로세스란 일괄적으로 모아놓은 대량의 데이터를 특정시간에 지정한 처리 방법에 따라 처리하는 과정 또는 프로그램을 말한다.
  4. 게임은 입력장치, 타이머, 프로그램 등으로부터 발생하는 이벤트를 처리하는 이벤트 기반 프로그램이다.
  5. 이벤트란 프로그램에 의해 감지되고 처리될 수 있는 동작이나 사건이다.
  6. 게임은 게임 초기화 후, 이벤트 검사, 이벤트 처리, 게임 업데이트, 화면 생성, 화면 업데이트 과정을 무한히 반복하는 게임 루프로 구성된다.
  7. 틱택토는 두 명의 플레이어가 3×3 판에 번갈아가며 O와 X 표시를 기록하여 같은 표시를 가로, 세로, 또는 대각선 상에 일직선으로 먼저 놓이도록 하는 게임이다.

[10]  실전프로젝트 2

*주요용어

  1. 소프트웨어 개발 라이프사이클: 소프트웨어 개발 계획 수립부터 폐기까지 신뢰도 높은 소프트웨어 결과물 구현을 위한 체계화된 소프트웨어 개발 체계

*정리하기

 

import random
 
class Tic_Tac_Toe:

    # 게임판 생성
    def __init__(self):
        self.board=[]

    # 게임판 초기화
    def create_board(self):
        for i in range(3):
            row=[]
            for j in range(3):
                row.append('*')
            self.board.append(row)


    # 첫 플레이어 선택
    def select_first_player(self):        
        if random.randint(0,1) == 0:
            return 'X'
        else :
            return 'O'

    # 기호 표시
    def mark_spot(self,row,col,player):
        self.board[row][col] = player
        
    # 승리 상태 확인
    def is_win(self, player):
        
        n = len(self.board)

        # 행 확인
        for i in range(n):            
            win =True
            for j in range(n):
                if self.board[i][j] != player:
                    win=False
                    break
            if win ==True:
                return win
    
        # 열 확인 
        for i in range(n):
            win =True
            for j in range(n):
                if self.board[j][i] != player:
                    win=False
                    break
            if win ==True:
                return win
        # 대각선 확인
        win =True
        for i in range(n):
            if self.board[i][i] !=player:
                win=False
                break
        if win ==True:
            return win

        win =True
        for i in range(n):
            if self.board[i][n-i-1] !=player:
                win=False
                break
        if win ==True:
            return win

        return False

    # 잔여 빈칸 여부 확인
    def is_board_full(self):
        for row in self.board:
            for item in row :
                if item == '*':
                    return False
        return True

    # 플레이어 변경
    def next_player(self,player):
        if player == 'O':
            return 'X'
        else :
            return 'O'
        #return 'X' if player == 'O' else 'O'

    # 현재 게임판 상태 츌력
    def show_board(self):
        for row in self.board:
            for item in row:
                print(item, end='')
            print()


    # 게임 루프 시작
    def start(self):
        # 새 게임판 생성
        self.create_board()
        self.show_board()

        # 첫 플레이어 선택
        player = self.select_first_player()

        # 게임 루프 시작
        while True:
            
            # 다음 플레이어 안내
            if player =='X':
                print("컴퓨터 차례입니다.")
            else:
                print("사용자 차례입니다.")

            # 현재 게임판 상태 출력
            self.show_board()

            # 사용자 입력 대기, 컴퓨터일 경우 랜덤 위치 반환
            if player == 'X':
                while True :
                    row, col = random.randint(1,3) , random.randint(1,3)
                    if self.board[row-1][col-1] == '*':
                        break
            
                print("컴퓨터가 행" + str(row) + ", 열" + str(col) + "을/를 선택했습니다.")
                print()
            else :
                row, col = list(map(int, input("선택할 빈칸의 위치를 입력하세요:").split()))
                print("사용자가 행" + str(row) + ", 열" + str(col) + "을/를 선택했습니다.")
                print()

            # row, col 입력값이 0, 0인 경우 게임 종료
            if row == 0 and col == 0:
                break
            
            # 입력된 위치 표시
            self.mark_spot(row -1,col-1,player)
            self.show_board()

            # 현재 플레이어가 이겼는지 확인 
            if self.is_win(player) == True:
                if player =='X':
                    print("컴퓨터가 이겼습니다. 다시 도전하세요.")
                else :
                    print("사용자가 이겼습니다. 축하합니다.")
                break

            # 게임판 가득참 확인
            if self.is_board_full() == True:
                print("무승부입니다. 다시 도전하세요.")
                break

            # 플레이어 변경
            player = self.next_player(player)

        # 최종 게임판 출력
        print()
        self.show_board()


# 게임 생성
TTT= Tic_Tac_Toe()

# 게임 시작
TTT.start()
LIST