파이썬 (3) Thread를 이용한 경마게임

Thread를 이용하여 경마게임을 만들었다.

프로그램 시작 시 사용자는 말의 마리수를 입력하고, 마리수만큼의 말이 경마를 시작한다. 경마의 진행상황은 1초마다 갱신되어 도착선에 먼저 도착한 경마의 순위를 출력한다.

사용자의 경마는 1번마이며 스페이스바를 누를 시 부스터를 사용할 수 있게 하였다. 또한 경마시간은 실시간으로 출력되게 하였다.

이번 프로그램은 Thread를 공부하는 것이기 때문에 각각의 말을 Thread처리하여 독립적으로 진행되게 하였다.

 

 

다음은 말의 이동과 위치를 변경하는 클래스이다

 

Horse.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import threading
import random
import time
 
 
class Horse(threading.Thread):
    
    def __init__(self):
        threading.Thread.__init__(self)
        self.location = 0
        
    def run(self):
        while True:
            self.location += random.randint(1,3)
            if self.location > 30:
                self.location = 31
                break
            time.sleep(1)
            
 
cs

말의 이동은 랜덤이므로 random모듈을 사용하여 1~3칸의 이동을 랜덤으로 이동하게 하였다. 이동된 위치는 location변수에 저장하고 location변수가 30을 초과할 경우 31칸으로 고정하여 실행을 종료하게 하였다.

Time.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import threading
import time
 
 
class Time(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
        self.endTime = 0
        self.resultTime = 0
        self.checkEnd = 0
        self.startTime = None
 
    def run(self):
        self.startTime = time.time() #시작된 시간 체크
        while True:
            self.endTime = time.time() #현재 측정된 시간 체크
            self.resultTime = self.endTime - self.startTime #현재시간 - 시작시간 = 경과된 시간
            if self.checkEnd == 1#모든말이 들어오면 종료
                break
            time.sleep(0.1
 
    def printTime(self):
        print("현재 경과된 시간은 " + str(round(self.resultTime,2)) + "초 입니다."
cs

경마진행시간또한 실시간으로 출력되어야 하므로 Thread를 사용하였다. time모듈을 사용하여 시작시간을 체크한 후 0.1초마다 현재시간을 체크하여 둘의 차로 경과된 시간을 간단하게 계산하였다.

Boost.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import threading
import keyboard
import time
 
class Boost(threading.Thread):
 
    def __init__(self,horse):
        threading.Thread.__init__(self)
        self.horse = horse
        self.checkEnd = 0
   
    def run(self):
        while True:
            if keyboard.is_pressed('space'):
                if self.horse.location < 30:
                    print("1번마 부스터!")
                    self.horse.location += 3
                    time.sleep(0.5)
 
            if self.checkEnd == 1:
                break
        
cs

부스트를 사용하는 Boost.py를 만들었다. 부스트는 키보드의 스페이스바를 인식하여 스페이스바가 눌리면 부스터가 사용되도록 하였다. 

 

Racing.py

 

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
import time
from Boost import Boost
from Horse import Horse
from Time import Time
 
class Racing:
    def __init__(self):
        self.horseNumber = None 
        self.horseList = []  #tmp로 객체로 만들어서 넣어주어야함 tmp로 만들때마다 주소값이 새로 지정되기 때문에 값이 공유되지않음
        self.nowTime = Time()
        self.finish = 0
        self.boost = None
        self.ranking = []
 
 
    def starting(self): #경마시작
        print("경마장에 오신 것을 환영합니다.")
        self.horseNumber = int(input("출전시키실 말의 수를 입력해주세요 : "))
        for index in range(self.horseNumber): #입력한 숫자만큼 말 생성
            tmpHorse = Horse() # !!!! 주소값 다름1!
            self.horseList.append(tmpHorse)
 
 
        for index2 in range(len(self.horseList)): #등록된 말 모두 위치변경 시작
            self.horseList[index2].start()
        
        self.boost = Boost(self.horseList[0]) 
        self.boost.start() #부스터기능 시작
        self.nowTime.start() #시간측정시작
        while True:
            for i in range(7):
                print()
            self.nowTime.printTime() #경과된 시간 출력
            for index2 in range(len(self.horseList)): #인터페이스 출력
                print(str(index2+1+"번마" + " " * self.horseList[index2].location + "🦓")
                if self.horseList[index2].location == 31#먼저들어온 말 랭킹리스트에 추가
                    self.ranking.append(str(index2+1+ "번마")
 
            for index3 in range(len(self.horseList)): #경마 종료판정
                    if self.horseList[index3].location == 31
                        self.finish = 1
                    else# 마지막말이 들어오지못하면 finish는 0으로 바뀜
                        self.finish = 0
                        break
 
            if self.finish == 1
                self.nowTime.checkEnd = 1
                self.boost.checkEnd = 1
                print("경기끝")
                self.ranking = list(dict.fromkeys(self.ranking)) #중복제거
                for rank in range(len(self.horseList)):
                    print(str(rank+1)+"위 : " + str(self.ranking[rank]) )
                break
            time.sleep(1)
 
    
class Main:
    if __name__ == "__main__" :
        racing = Racing()
        racing.starting()
cs

게임의 전체적인 실행을 하는 클래스이다.

숫자를 입력받아 입력받은 숫자만큼 horse의 객체를 생성한다. 생성한 객체는 배열에 저장하여 놓는다. 그 후 배열의 크기만큼 Thread의 start를 사용하여 Thread를 시작한다. Thread를 시작한 시점에서 말들의 location은 변하고 있으므로 각각의 말의 location을 불러와 print문으로 출력한다. 이 후 말이 30칸이상 이동하였으면 finish변수를 1번 그렇지않으면 0의 값을 넣어준다. 또한 rank변수에 결승선을 통과한 말을 추가시킨다.

모든말이 결승선을 통과하면 Thread를 정지하고 랭킹을 출력시킨다.

'Python' 카테고리의 다른 글

파이썬 (2) 완성된 스도쿠판 자동생성기  (0) 2022.05.13
파이썬 (1) 기본적인 문법  (0) 2022.05.09