sm 기술 블로그

14. 텍스트 스타크래프트 본문

Python

14. 텍스트 스타크래프트

sm_hope 2022. 5. 8. 00:39
유닛 기본값

 

유닛 생성

class Unit:
    def __init__(self, name, hp, speed):
        
        self.name = name
        self.hp = hp
        self.speed = speed
        print("{0} 유닛이 생성되었습니다.".format(name))

    def move(self, location):
            print("{0} : {1} 방향으로 이동합니다. [속도 {2}]"\
            .format(self.name, location, self.speed))
    
    def damaged(self, damage) :
        print("{0} : {1} 데미지를 입었습니다.".format(self.name, damage))
        self.hp -= damage
        print("{0} : 현재 체력은 {1} 입니다.".format(self.name, self.hp))
        if self.hp <= 0:
            print("{0} : 파괴되었습니다.".format(self.name))

클래스를 사용한다면 반디스 def __init__ 를 통해 초기화를 해주어야 한다.

 

self.__ 를 통해서 클래스 내에 변수 저장

 

Unit 클래스에 move, damaged 메소드(함수) 생성 (첫 인수로는 반드시 self를 써주어야한다.)

 

코드가 너무 길면 역슬래시(\)를 통해 줄바꿈이 가능하다.

 

 

공격

class AttackUnit(Unit) : #상속을 받음
    def __init__(self, name, hp, speed, damage):
        Unit.__init__(self, name, hp, speed)
        self.damage = damage

    def attack(self, location):
        print("{0} : {1} 방향으로 적군을 공격 합니다. [공격력 {2}]"\
            .format(self.name, location, self.damage))
    #이름과 공격은 정의된 것을 쓰고 위치는 받은 값으로 쓴다.

Unit 클래스를 상속 받았다. Unit으로 부터 name, hp, speed를 상속 받지만 , damage는 새로 정의 한다. (오버로딩)

 

 

공중 이동

class Flyable:
    def __init__(self, flying_speed):
        self.flying_speed = flying_speed

    def fly(self, name, location):
        print("{0} : {1} 방향으로 날아갑니다. [속도 {2}]"\
            .format(name, location, self.flying_speed))

 

 

공중 공격

class FlaybleAttackUnit(AttackUnit, Flyable) : 
    #다중 상속
    def __init__(self, name, hp, damage, flying_speed):
        AttackUnit.__init__(self, name, hp, 0, damage)
        # 지상 스피드는 0이다.
        Flyable.__init__(self, flying_speed)
    #두개의 클래스를 상속받아 초기화 해줬을 뿐임.

    def move(self, location):
        self.fly(self.name, location)

공격클래스와 공중이동클래스 두 가지 클래스를 다중으로 상속을 받았다.

 


유닛 생성

마린 클래스

class Marine(AttackUnit):
    def __init__(self):
        AttackUnit.__init__(self, "마린", 40, 1, 5)
  
    # 스팀팩 : 일정 시간 동안 이동 및, 공격 속도를 증가
    def stimpack(self):
        if self.hp > 10 :
            self.hp -= 10
            print("{0} : 스팀팩을 사용합니다. (HP 10 감소)".format(self.name))
        
        else :
            print("{0} : 체력이 부족하여 스팀팩을 사용하지 않습니다.".format(self.name))​

AttackUnit을 상속 받음. 

 

스팀팩 메소드(함수) 정의.

[만약 체력이 10보다 크면 스팀팩을 사용한다 (체력은 -10 감소)]

 

 

 

탱크 클래스

class Tank(AttackUnit):
    # 시즈모드 : 탱크를 지상에 고정시켜, 더 높은 파워로 공격 가능, 이동 불가
    seize_developed = False #시즈모드 개발여부

    
    def __init__(self):
        AttackUnit.__init__(self, "탱크", 150, 1, 35)
        self.seize_mode = False

    def set_seize_mode(self):
        if Tank.seize_developed == False:
            return

        #현재 시즈모드가 아닐 때
        if self.seize_mode == False :
            print("{0} : 시즈모드로 전환합니다.".format(self.name))
            self.damage *= 2
            self.seize_mode = True

        #현재 시즈모드 일때
        else : 
            print("{0} : 시즈모드로 해제합니다.".format(self.name))
            self.damage /= 2
            self.seize_mode = False

시즈모드 메소드 정의 (단, 시즈모드 개발 True가 필요함)

 

 

 

레이스 클래스

class Wraith(FlaybleAttackUnit):
    def __init__(self):
        FlaybleAttackUnit.__init__(self, "레이스",80, 20, 5)
        self.clocked = False # 클로킹 모드(해제 상태)

    def clocking(self):
        if self.clocked == True: # 클로킹 -> 해제
            print("{0} : 클로킹 모드 해제합니다.".format(self.name))
            self.clocked = False
        
        else : # 해제 -> 클로킹
            print("{0} : 클로킹 모드 설정합니다.".format(self.name))
            self.clocked = True

클로킹 모드 정의 (클로킹 개발은 생략함.)

 


게임시작

게임 종료 | 시작 함수 정의

def game_start():
    print("[알림] 새로운 게임을 시작합니다.")

def game_over():
    print("player : gg")
    print("[player] 님이 게임에서 퇴장하셨습니다.")

 

 

 

유닛 생성

game_start()

# 마린 3기 생성
m1 = Marine()
m2 = Marine()
m3 = Marine()

# 탱크 2기 생성
t1 = Tank()
t2 = Tank()

# 레이스 1기 생성
w1 = Wraith()

# 유닛 일괄 관리
attack_units = []
attack_units.append(m1)
attack_units.append(m2)
attack_units.append(m3)
attack_units.append(t1)
attack_units.append(t2)
attack_units.append(w1)

이미 각 유닛의 클래스 내에 초기값을 생성하여 따로 정의가 필요하지 않다.

 

모든 유닛을 일괄적으로 관리하기 위해서 리스트 사용.

 

 

 

전투

# 전군 이동
for unit in attack_units:
    unit.move("1시")

# 탱크 시즈모드 개발
Tank.seize_developed = True
print("[알림] 탱크 시즈모드 개발이 완료 되었습니다.")

# 공격 모드 준비(탱크: 시즈모드, 레이스: 클로킹, 마린: 스팀팩)
for unit in attack_units:
    if isinstance(unit, Marine): #만약 현재 유닛이 마린이라면
        unit.stimpack()
    elif isinstance(unit, Tank):
        unit.set_seize_mode()
    elif isinstance(unit, Wraith):
        unit.clocking()

# 전군 공격
for unit in attack_units:
    unit.attack("1시")

# 전군 피해
for unit in attack_units:
    unit.damaged(randint(5, 21)) # 공격은 랜덤으로 받음 5~20

#게임 종료
game_over()

isinstance(A, B) : 현재 A가 B일때 True

randint(A, B) -> A~(B-1)의 랜덤 변수를 받음. [from random import * 필요]

 

 

 


실행
# 텍스트 스타크래프트
from random import *

class Unit:
    def __init__(self, name, hp, speed):
        
        self.name = name
        self.hp = hp
        self.speed = speed
        print("{0} 유닛이 생성되었습니다.".format(name))

    def move(self, location):
            print("{0} : {1} 방향으로 이동합니다. [속도 {2}]"\
            .format(self.name, location, self.speed))
    
    def damaged(self, damage) :
        print("{0} : {1} 데미지를 입었습니다.".format(self.name, damage))
        self.hp -= damage
        print("{0} : 현재 체력은 {1} 입니다.".format(self.name, self.hp))
        if self.hp <= 0:
            print("{0} : 파괴되었습니다.".format(self.name))


class AttackUnit(Unit) : #상속을 받음
    def __init__(self, name, hp, speed, damage):
        Unit.__init__(self, name, hp, speed)
        self.damage = damage

    def attack(self, location):
        print("{0} : {1} 방향으로 적군을 공격 합니다. [공격력 {2}]"\
            .format(self.name, location, self.damage))
    #이름과 공격은 정의된 것을 쓰고 위치는 받은 값으로 쓴다.


class Flyable:
    def __init__(self, flying_speed):
        self.flying_speed = flying_speed

    def fly(self, name, location):
        print("{0} : {1} 방향으로 날아갑니다. [속도 {2}]"\
            .format(name, location, self.flying_speed))


class FlaybleAttackUnit(AttackUnit, Flyable) : 
    #다중 상속
    def __init__(self, name, hp, damage, flying_speed):
        AttackUnit.__init__(self, name, hp, 0, damage)
        # 지상 스피드는 0이다.
        Flyable.__init__(self, flying_speed)
    #두개의 클래스를 상속받아 초기화 해줬을 뿐임.

    def move(self, location):
        self.fly(self.name, location)

#---------------------------------------------------------------------------------------

# 마린 클래스
class Marine(AttackUnit):
    def __init__(self):
        AttackUnit.__init__(self, "마린", 40, 1, 5)
  
    # 스팀팩 : 일정 시간 동안 이동 및, 공격 속도를 증가
    def stimpack(self):
        if self.hp > 10 :
            self.hp -= 10
            print("{0} : 스팀팩을 사용합니다. (HP 10 감소)".format(self.name))
        
        else :
            print("{0} : 체력이 부족하여 스팀팩을 사용하지 않습니다.".format(self.name))
        
    
# 탱크 클래스
class Tank(AttackUnit):
    # 시즈모드 : 탱크를 지상에 고정시켜, 더 높은 파워로 공격 가능, 이동 불가
    seize_developed = False #시즈모드 개발여부

    
    def __init__(self):
        AttackUnit.__init__(self, "탱크", 150, 1, 35)
        self.seize_mode = False

    def set_seize_mode(self):
        if Tank.seize_developed == False:
            return

        #현재 시즈모드가 아닐 때
        if self.seize_mode == False :
            print("{0} : 시즈모드로 전환합니다.".format(self.name))
            self.damage *= 2
            self.seize_mode = True

        #현재 시즈모드 일때
        else : 
            print("{0} : 시즈모드로 해제합니다.".format(self.name))
            self.damage /= 2
            self.seize_mode = False

class Wraith(FlaybleAttackUnit):
    def __init__(self):
        FlaybleAttackUnit.__init__(self, "레이스",80, 20, 5)
        self.clocked = False # 클로킹 모드(해제 상태)

    def clocking(self):
        if self.clocked == True: # 클로킹 -> 해제
            print("{0} : 클로킹 모드 해제합니다.".format(self.name))
            self.clocked = False
        
        else : # 해제 -> 클로킹
            print("{0} : 클로킹 모드 설정합니다.".format(self.name))
            self.clocked = True

def game_start():
    print("[알림] 새로운 게임을 시작합니다.")

def game_over():
    print("player : gg")
    print("[player] 님이 게임에서 퇴장하셨습니다.")

#-----------------------------------------------------------------------------------------------

#게임 시작
game_start()

# 마린 3기 생성
m1 = Marine()
m2 = Marine()
m3 = Marine()

# 탱크 2기 생성
t1 = Tank()
t2 = Tank()

# 레이스 1기 생성
w1 = Wraith()

# 유닛 일괄 관리
attack_units = []
attack_units.append(m1)
attack_units.append(m2)
attack_units.append(m3)
attack_units.append(t1)
attack_units.append(t2)
attack_units.append(w1)

# 전군 이동
for unit in attack_units:
    unit.move("1시")

# 탱크 시즈모드 개발
Tank.seize_developed = True
print("[알림] 탱크 시즈모드 개발이 완료 되었습니다.")

# 공격 모드 준비(탱크: 시즈모드, 레이스: 클로킹, 마린: 스팀팩)
for unit in attack_units:
    if isinstance(unit, Marine): #만약 현재 유닛이 마린이라면
        unit.stimpack()
    elif isinstance(unit, Tank):
        unit.set_seize_mode()
    elif isinstance(unit, Wraith):
        unit.clocking()

# 전군 공격
for unit in attack_units:
    unit.attack("1시")

# 전군 피해
for unit in attack_units:
    unit.damaged(randint(5, 21)) # 공격은 랜덤으로 받음 5~20

#게임 종료
game_over()

 

 

출력결과

[알림] 새로운 게임을 시작합니다.
마린 유닛이 생성되었습니다.
마린 유닛이 생성되었습니다.
마린 유닛이 생성되었습니다.
탱크 유닛이 생성되었습니다.
탱크 유닛이 생성되었습니다.
레이스 유닛이 생성되었습니다.
마린 : 1시 방향으로 이동합니다. [속도 1]
마린 : 1시 방향으로 이동합니다. [속도 1]
마린 : 1시 방향으로 이동합니다. [속도 1]
탱크 : 1시 방향으로 이동합니다. [속도 1]
탱크 : 1시 방향으로 이동합니다. [속도 1]
레이스 : 1시 방향으로 날아갑니다. [속도 5]
[알림] 탱크 시즈모드 개발이 완료 되었습니다.
마린 : 스팀팩을 사용합니다. (HP 10 감소)
마린 : 스팀팩을 사용합니다. (HP 10 감소)
마린 : 스팀팩을 사용합니다. (HP 10 감소)
탱크 : 시즈모드로 전환합니다.
탱크 : 시즈모드로 전환합니다.
레이스 : 클로킹 모드 설정합니다.
마린 : 1시 방향으로 적군을 공격 합니다. [공격력 5]
마린 : 1시 방향으로 적군을 공격 합니다. [공격력 5]
마린 : 1시 방향으로 적군을 공격 합니다. [공격력 5]
탱크 : 1시 방향으로 적군을 공격 합니다. [공격력 70]
탱크 : 1시 방향으로 적군을 공격 합니다. [공격력 70]
레이스 : 1시 방향으로 적군을 공격 합니다. [공격력 20]
마린 : 18 데미지를 입었습니다.
마린 : 현재 체력은 12 입니다.
마린 : 10 데미지를 입었습니다.
마린 : 현재 체력은 20 입니다.
마린 : 10 데미지를 입었습니다.
마린 : 현재 체력은 20 입니다.
탱크 : 10 데미지를 입었습니다.
탱크 : 현재 체력은 140 입니다.
탱크 : 14 데미지를 입었습니다.
탱크 : 현재 체력은 136 입니다.
레이스 : 8 데미지를 입었습니다.
레이스 : 현재 체력은 72 입니다.
player : gg
[player] 님이 게임에서 퇴장하셨습니다.
Comments