Lets play some Pong! 

![pong](http://gifimage.net/wp-content/uploads/2017/08/pong-gif-3.gif)

For those who don't know what Pong is, it is a simple arcade game where two players can move their paddles to hit a ball towards the opponent's side of the screen, gaining a point for each opponent's miss. You can read more about it [here](https://en.wikipedia.org/wiki/Pong).

___

# Task:

You must finish the `Pong` class. It has a constructor which accepts the `maximum score` a player can get throughout the game, and a method called `play`. This method determines whether the current player hit the ball or not, i.e. if the paddle is at the sufficient height to hit it back. There're 4 possible outcomes: player successfully hits the ball back, player misses the ball, player misses the ball **and his opponent reaches the maximum score winning the game**, either player tries to hit a ball despite the game being over. You can see the input and output description in detail below.

### "Play" method input:

* ball position - The Y coordinate of the ball
* player position - The Y coordinate of the centre(!) of the current player's paddle

### "Play" method output:

One of the following strings:

* `"Player X has hit the ball!"` - If the ball "hits" the paddle
* `"Player X has missed the ball!"` - If the ball is above/below the paddle
* `"Player X has won the game!"` - If one of the players has reached the maximum score
* `"Game Over!"` - If the game has ended but either player still hits the ball

### Important notes:

* Players take turns hitting the ball, always starting the game with the Player 1.
* The paddles are `7` pixels in height.
* The ball is `1` pixel in height.

___

## Example

Difficulty: introductory

Starter code:

def __init__(self, max_score):
	

Solutions:
from itertools import cycle

class Pong:
    def __init__(self, max_score):
        self.max_score = max_score;
        self.scores = {1: 0, 2: 0}
        self.players = cycle((1, 2))

    def game_over(self):
        return any(score >= self.max_score for score in list(self.scores.values()))

    def play(self, ball_pos, player_pos):
        if self.game_over():
            return "Game Over!"
 
        player = next(self.players)
        if abs(ball_pos - player_pos) <= 3:
            return "Player {} has hit the ball!".format(player)
        else:
            self.scores[player] += 1
            if self.scores[player] == self.max_score:
                return "Player {} has won the game!".format(next(self.players))
            else:
                return "Player {} has missed the ball!".format(player)


class Pong:
    def __init__(self, max_score):
        self.max_score = max_score;
        self.score = [0,0]
        self.player = 0
    def play(self, ball_pos, player_pos):
        if self.max_score in self.score: return "Game Over!"
        if player_pos-3 <= ball_pos <= player_pos+3:
            self.player ^= 1
            return "Player {} has hit the ball!".format((self.player^1) +1)
        self.player ^= 1
        self.score[self.player] += 1
        if self.score[self.player] == self.max_score: return "Player {} has won the game!".format(self.player + 1)
        return "Player {} has missed the ball!".format((self.player^1) +1)

class Pong:
    def __init__(self, max_score):
        self.max_score = max_score
        self.next = 1
        self.score = {1: 0, 2: 0}

    def play(self, ball, paddle):
        if max(self.score.values()) >= self.max_score:
            return "Game Over!"
        current, self.next = self.next, 3 - self.next
        if paddle - 4 < ball < paddle + 4:
            return f"Player {current} has hit the ball!"
        else:
            self.score[current] += 1
            if self.score[current] == self.max_score:
                return f"Player {self.next} has won the game!"
            return f"Player {current} has missed the ball!"

class Pong:
    def __init__(self, win):
        self.win = win
        self.turn = -1
        self.scores = [0, 0]

    def play(self, ball, player):
        
        if max(self.scores) == self.win: return 'Game Over!'
            
        self.turn = (self.turn + 1) % 2
        
        if abs(ball - player) < 4: return 'Player ' + str(self.turn + 1) + ' has hit the ball!'

        self.scores[(self.turn + 1) % 2] += 1
            
        return 'Player ' + (str(1 if self.turn else 2) + ' has won the game!' if max(self.scores) == self.win else str(self.turn + 1) + ' has missed the ball!')

class Pong:
    def __init__(self, max_score):
        self.max_score = max_score
        self.scores = [0, 0]
        self.turn = 0

    def play(self, ball_pos, player_pos):
        try:
            if max(self.scores) == self.max_score:
                return 'Game Over!'
            if abs(ball_pos - player_pos) <= 3:
                return f'Player {self.turn + 1} has hit the ball!'
            self.scores[1 - self.turn] += 1
            if self.scores[1 - self.turn] == self.max_score:
                return f'Player {2 - self.turn} has won the game!'
            else:
                return f'Player {self.turn + 1} has missed the ball!'    
        finally:
            self.turn = (self.turn + 1) % 2

class Pong:
    def __init__(self,m):
        self.m,self.w=m,[0,0]
        self.o=self.p=0

    def play(self,b,a):
        if self.o:return "Game Over!"
        self.p+=1
        if abs(b-a)<3.5:return "Player %d has hit the ball!"%(2-self.p%2) 
        self.w[self.p%2]+=1
        if any(self.m<=x for x in self.w):self.o=1
        return "Player %d has %s!"%(2-(self.o+self.p)%2,('missed the ball','won the game')[self.o])

PADDLE_SIZE = 7

class Pong:
    def __init__(self, max_score):
        self.max_score = max_score;
        
        self.player_scores = {0: 0, 1: 0}
        
        self.current_player = 0
        self.game_state = None

    def play(self, ball_pos, player_pos):
    
        if self.game_state is not None:
            return self.game_state
    
        paddle_range = (player_pos - (PADDLE_SIZE / 2),
                        player_pos + (PADDLE_SIZE / 2))
                        
        if ball_pos > max(paddle_range) or ball_pos < min(paddle_range):
            
            self.player_scores[self.current_player ^ 1] += 1
            
            if self.player_scores[self.current_player ^ 1] >= self.max_score:
                self.game_state = "Game Over!"
                string = "Player {} has won the game!".format(self.current_player ^ 1 + 1)
            else:
                string = "Player {} has missed the ball!".format(self.current_player + 1)
        
        else:
            string = "Player {} has hit the ball!".format(self.current_player + 1)
            
        self.switch_player()
        return string
        
    def switch_player(self):
        self.current_player ^= 1
        


class Pong:
    def __init__(self, max_score):
        self.max_score = max_score;
        self.player=[0,0]
        self.index=0
        self.win=False
    def play(self, ball_pos, player_pos):
        if self.win:
            return "Game Over!"
        self.index+=1
        if abs(ball_pos-player_pos)>3:
            self.player[self.index%2]+=1
            if self.player[self.index%2]>=self.max_score:
                self.win=True
                return "Player 2 has won the game!" if self.index%2==1 else "Player 1 has won the game!"
            return "Player 1 has missed the ball!" if (self.index-1)%2==0 else "Player 2 has missed the ball!"
        return "Player 1 has hit the ball!" if (self.index-1)%2==0 else "Player 2 has hit the ball!"

class Pong:
    def __init__(self, max_score):
        self.max_score = max_score
        self.next = 1
        self.score = {1: 0, 2: 0}

    def play(self, ball, paddle):
        if max(self.score.values()) >= self.max_score:
            return "Game Over!"
        current, self.next = self.next, 3 - self.next
        if paddle - 4 < ball < paddle + 4:
            msg = f"Player {current} has hit the ball!"
        else:
            msg = f"Player {current} has missed the ball!"
            self.score[current] += 1
            if self.score[current] == self.max_score:
                msg = f"Player {self.next} has won the game!"
        return msg


class Pong:
    def __init__(self, max_score):
        self.max_score = max_score;
        self.i = -1
        self.event = "Player {} has {} the ball!"
        self.score = {1:0, 2:0}

    def play(self, ball, player):
        if self.event:
            self.i += 1
        if  not self.event: return "Game Over!"
        hit = abs(player - ball)
        if hit>3:
            winer = (1,2)[not self.i%2]
            self.score[winer]  += 1
            if self.score[winer] == self.max_score:
                self.event = None
                return f"Player {winer} has won the game!"
        return self.event.format((1,2)[self.i%2], ('hit','missed')[hit>3])