배꼽파지 않도록 잘 개발해요

방송대 파이썬 프로그래밍 기초 - 14강. 실전 프로그래밍 2 본문

방송대 컴퓨터과학과/파이썬 프로그래밍 기초

방송대 파이썬 프로그래밍 기초 - 14강. 실전 프로그래밍 2

꼽파 2023. 5. 23. 23:50


  • 1. 2차원 리스트

  • 2. 실전 프로그래밍

  • 1. 2차원 리스트

    리스트와 2차원 리스트

    리스트 2차원 리스트
    순서화된 값의 집합체를 저장할 수 있는 데이터 타입
    단일 식별자로 연속된 저장 공간 접근 수단 제공
    - 반복구조에서 많이 사용됨.
    리스트에 리스트가 내포된 즉, 리스트의 리스트
    - 값들이 서로 매칭되어 일렬로 세울 수 없는 경우
    - 2개의 차원 축이 생김.

    2차원 리스트 구조와 접근

    2차원 리스트 구조 2차원 리스트 접근
    '거리표'라고 하는 2차원 리스트는 각 주요 도시의 값들을 리스트로 갖고 있고, 이 리스트의 값들이 나머지 도착 도시와의 거리에 해당되는 값을 가지고 있음.

    ·행 인덱스(row index) : 2차원 리스트의 왼쪽에서 오른쪽으로 이동
    ·열 인덱스(column index) : 위에서 아래로 이동
    각각의 인덱스는 0부터 시작하여 2차원 리스트의 길이보다 작은 값까지 사용
    인덱스 항목은 내부 1차원 리스트를 가리키는 접근변수로 구성이 되어 있음.

    distance[0] : 0행
    distance[0][7] : 0행 7열 → 390

    두 개의 접근 연산자를 사용해 개별적인 값에 접근함. 

     

    2차원 리스트 생성

    리스트 내부에 리스트가 정의

    → 2차원 리스트 생성 시 원소가 결정된 상황


    2차원 리스트 동적 생성

    import random as rd
    
    # 행의 개수 nRows, 열의 개수 nColumns
    distance = []
    for i in range(nRows):
        row = []
        for j in range(nColumns): # append를 사용하여 추가가
            row.append(rd,randint(0, 99))
        distance.append(row)
    print(distance)

    모든 원소의 값을 알고 있다면 리스트 함수나 리스트 생성 연산자를 통해 만들 수 있음.

    동적으로 프로그램이 진행되는 상황에 맞춰서 2차원 리스트를 구성해야 하면 이런 식의 코드를 통해서 동적 생성이 가능함.


    2차원 리스트 순회

    각 차원을 순차적으로 순회하기 위한 2개의 반복구조가 중첩됨.


    2. 실전 프로그래밍

    1. 설계 관점에서 게임에 활용할 메소드 정의

    class Tic_Tac_Toe:
     
        # 게임판 생성
        def __init__(self):
    
        # 게임판 초기화
        def create_board(self):
    
        # 첫 플레이어 선택
        def select_first_player(self):
    
        # 기호 표시
        def mark_spot(self, row, col, player):
    
        # 승리 상태 확인
        def is_win(self, player):
    
        #잔여 빈칸 여부 확인
        def is_board_full(self):
    
        # 플레이어 변경
        def next_player(self, player):
    
        # 현재 게임판 상태 출력
        def show_board(self):
    
        # 게임 시작
        def start(self):
    
    
    # 게임 생성
    
    # 게임 시작

     

    2. 게임판 생성

    # 게임판 생성
    
    # board는 리스트이므로 []를 통해 생성
    # 변수처럼 작성하면 로컬변수로 착각할 수 있음
    # → Tic_Tac_Toe 클래스 전역에서 사용하려면 앞에 self.를 붙여준다
    
        def __init__(self):
            self.board = []

     

    3. 게임판 생성과 초기화

        # 게임판 초기화
        def create_board(self):
    
        # 빈칸은 *로 표시함
            for i in range(3) : # 0, 1, 2가 들어옴
                row = []       # 하나의 행 만들기
                for j in range(0, 3) : # 반복할 때마다 '*'로 채운 3개의 칸 만들기
                    row.append('*')
                self.board.append(row) # self.board판에 앞에서 만든 row를 넣음
    
    # [['*', '*', '*'],
    #  ['*', '*', '*'],
    #  ['*', '*', '*']]

    range(0, 3) 범위 : 0, 1, 2 → 3을 포함하지 않음.

    randint(0, 3) 범위 : 0, 1, 2, 3 → 3을 포함함.

     

    4. 첫 플레이어 선택

        # 첫 플레이어 선택
        # 무작위로 둘 중 하나를 선택 (ex. 0은 컴퓨터, X은 사용자)
    
        def select_first_player(self):
            if random.randint(0, 1) == 0:
                return 'X'
            else :
                return '0'
        # random 모듈을 사용했으면 코드 상단에 random 모듈을 import 해야함.

     

    5. 기호 표시

        # 기호 표시
        # 게임판 상의 행, 열 값에 Player의 말을 표시
        # []를 통해 리스트 생성
    
        def mark_spot(self, row, col, player):
            self.board[row][column] = player

     

    6. 승리 상태 확인 (행, 열, 대각선)

        # 승리 상태 확인
        # 이름이 'is'이므로 반환값이 true or false일 것으로 예상됨.
        def is_win(self, player):
            # len으로 board가 가리키는 리스트의 원소의 개수를 추출함. 
            n = len(self.board)
    
            # 행 확인
            for i in range(n) :
                win = True # 우선 승리상황이라고 가정하고, 다른 게 있는지 체크
                for j in range(n) :
                    if self.board[i][j] != player 
                    # 승리 조건 : 3칸 모두 player로 채워져야 됨.
                    # 세 칸 중 한 칸이라도 player말이 아니라는 것은 승리상황이 아님. → 반복 종료
                        win = False
                        break
                if win == True :
                    return win
    
            # 열 확인 ----> j가 고정, i만 바뀜
            for i in range(n) :
                win = True # 우선 승리상황이라고 가정하고, 다른 게 있는지 체크
                for j in range(n) :
                    if self.board[j][i] != player 
                    # 승리 조건 : 3칸 모두 player로 채워져야 됨.
                    # 세 칸 중 한 칸이라도 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
    
        # 행, 열, 대각선 확인 후에도 승리 상황이 아닌 경우에는 False를 반환     
        # return False는 win 변수의 값이 False가 되는 것을 의미함.   
            return False

     

    7. 잔여 빈칸 여부 확인

        # 잔여 빈칸 여부 확인
        # 한 칸씩 확인한 후, 빈칸을 의미하는 '*'가 있으면 False 반환
        def is_board_full(self):
            for row in self.board :
                for item in row :
                    if item == '*'
                        return False
            return True

     

    8. 플레이어 변경

        # 플레이어 변경
        # 현재 플레이어가 O이면 X를 반환, X이면 O를 반환
        def next_player(self, player): 
            if player == '0' :
                return 'X'
            else 
                return '0'
                    
        # 파이썬에서만 작성할 수 있는 코드
        # return 'X' if player == '0' else '0'

     

    9. 현재 게임판 상태 출력

        # 현재 게임판 상태 출력
        # for문을 활용해 게임판 상태를 출력 (위의 빈칸 유무 확인과 유사)
        def show_board(self):
            for row in self.board :
                for item in row :
                    print(item, end = " ") # 줄바꿈되지 않도록 함.
                print()

    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 'O'
            else:
                return 'X'
    
        def mark_spot(self, row, col, player):
            self.board[row - 1][col - 1] = 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:
                    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:
                    return win
    
            win = True
            for i in range(n):
                if self.board[i][n - i - 1] != player:
                    win = False
                    break
            if win:
                return win
    
            win = True
            for i in range(n):
                if self.board[i][i] != player:
                    win = False
                    break
            if win:
                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'
    
        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("컴퓨터 차례입니다.")
                    while True:
                        row, col = random.randint(1, 3), random.randint(1, 3)
                        if self.board[row - 1][col - 1] == '*':
                            break
    
                else:
                    print("사용자 차례입니다.")
                    while True:
                        row, col = list(map(int, input("선택할 빈칸의 위치를 입력하세요: ").split()))
                        if self.board[row - 1][col - 1] == '*':
                            break
                        else:
                            print("이미 선택된 위치입니다. 다시 선택해주세요.")
    
                if row == 0 and col == 0:
                    break
    
                self.mark_spot(row, col, player)
                self.show_board()
    
                if self.is_win(player):
                    if player == 'X':
                        print("컴퓨터가 이겼습니다. 다시 도전하세요.")
                    else:
                        print("사용자가 이겼습니다. 축하합니다.")
                    break
    
                if self.is_board_full():
                    print("무승부입니다. 다시 도전하세요.")
                    break
    
                player = self.next_player(player)
    
            print()
            self.show_board()
    
    TTT = Tic_Tac_Toe()
    TTT.start()

    728x90