Skip to content

Instantly share code, notes, and snippets.

@hjohnsen
Created March 24, 2018 19:32
Show Gist options
  • Save hjohnsen/b1ee48983f0fbeb49e71e78b32c6f7d8 to your computer and use it in GitHub Desktop.
Save hjohnsen/b1ee48983f0fbeb49e71e78b32c6f7d8 to your computer and use it in GitHub Desktop.
I had a dream about a game that was kind of like mariokart meets snake. You had to move towards the food/target while also running away from an enemy. I modified the code from https://gist.github.com/sanchitgangwar/2158089 to make this game.
# SNAKES GAME
# Use ARROW KEYS to play, SPACE BAR for pausing/resuming and Esc Key for exiting
# Adapted from https://gist.github.com/sanchitgangwar/2158089
import curses
from curses import KEY_RIGHT, KEY_LEFT, KEY_UP, KEY_DOWN
from random import randint, choice
def update_anim(snake, key, symbol):
# Calculates the new coordinates of the head of the snake.
snake.insert(0, [snake[0][0] + (key == KEY_DOWN and 1) + (key == KEY_UP and -1), snake[0][1] + (key == KEY_LEFT and -1) + (key == KEY_RIGHT and 1)])
# If snake crosses the boundaries, make it enter from the other side
if snake[0][0] == 0: snake[0][0] = 18
if snake[0][1] == 0: snake[0][1] = 58
if snake[0][0] == 19: snake[0][0] = 1
if snake[0][1] == 59: snake[0][1] = 1
# Exit if snake crosses the boundaries (Uncomment to enable)
#if snake[0][0] == 0 or snake[0][0] == 19 or snake[0][1] == 0 or snake[0][1] == 59: break
last = snake.pop()
win.addch(last[0], last[1], ' ')
win.addch(snake[0][0], snake[0][1], symbol)
def get_dir(first, second, dir):
""" dir should be "towards" if second should move towards first
or "away" if second should move away from first
if first is to the NW of second, xdif and ydif are neg."""
x_dif = first[1]-second[1]
y_dif = first[0]-second[0]
if abs(x_dif) >= abs(y_dif):
if dir == "towards":
if x_dif<0:
return KEY_LEFT
else:
return KEY_RIGHT
else:
if x_dif<0:
return KEY_RIGHT
else:
return KEY_LEFT
else:
if dir == "towards":
if y_dif<0:
return KEY_UP
else:
return KEY_DOWN
else:
if x_dif<0:
return KEY_DOWN
else:
return KEY_UP
def get_next_move(you, enemy, food):
if randint(0,3)==0: # move randomly 1/4 of the time
return(choice(key_choices), choice(key_choices))
else: # move in the best direction
return(get_dir(you, enemy, "towards"), get_dir(you, food, "away"))
curses.initscr()
win = curses.newwin(20, 60, 0, 0)
win.keypad(1)
curses.noecho()
curses.curs_set(0)
win.border(0)
win.nodelay(1)
key = KEY_RIGHT # Initializing values
score = 0
endgame = False
key_choices = [KEY_LEFT, KEY_RIGHT, KEY_UP, KEY_DOWN]
you = [[4,10]] # Initial snake co-ordinates
enemy = [[15,30]]
food = [[11,20]] # First food co-ordinates
win.addch(you[0][0], you[0][1], 'o')
win.addch(food[0][0], food[0][1], '*') # Prints the food
win.addch(enemy[0][0], enemy[0][1], 'X')
try:
while key != 27 and endgame == False: # While Esc key is not pressed
win.border(0)
win.addstr(0, 2, 'Score : ' + str(score) + ' ') # Printing 'Score' and
win.addstr(0, 27, " Holly's Game ")
win.timeout(520) # Increases the speed of Snake as its length increases
prevKey = key # Previous key pressed
event = win.getch()
key = key if event == -1 else event
if key == ord(' '): # If SPACE BAR is pressed, wait for another
key = -1 # one (Pause/Resume)
while key != ord(' '):
key = win.getch()
key = prevKey
continue
if key not in [KEY_LEFT, KEY_RIGHT, KEY_UP, KEY_DOWN, 27]: # If an invalid key is pressed
key = prevKey
update_anim(you, key, 'o')
if you[0] == enemy[0]:
endgame = True
if you[0] == food[0]: # When snake eats the food
food = []
score += 1
while food == []:
food = [[randint(1, 18), randint(1, 58)]] # Calculating next food's coordinates
if food in you: food = []
win.addch(food[0][0], food[0][1], '*')
enemy_move, food_move = get_next_move(you[0], enemy[0], food[0])
update_anim(enemy, enemy_move, 'X')
if you[0] == enemy[0]:
endgame = True
update_anim(food, food_move, '*') #choice(key_choices)
if you[0] == food[0]: # When snake eats the food
food = []
score += 1
while food == []:
food = [[randint(1, 18), randint(1, 58)]] # Calculating next food's coordinates
if food in you: food = []
win.addch(food[0][0], food[0][1], '*')
finally:
curses.endwin()
print("\nScore - " + str(score))
# SNAKES GAME
# Use ARROW KEYS to play, SPACE BAR for pausing/resuming and Esc Key for exiting
# Adapted from https://gist.github.com/sanchitgangwar/2158089
import curses
from curses import KEY_RIGHT, KEY_LEFT, KEY_UP, KEY_DOWN
from random import randint, choice
def update_anim(snake, key, symbol):
# Calculates the new coordinates of the head of the snake.
snake.insert(0, [snake[0][0] + (key == KEY_DOWN and 1) + (key == KEY_UP and -1), snake[0][1] + (key == KEY_LEFT and -1) + (key == KEY_RIGHT and 1)])
# If snake crosses the boundaries, make it enter from the other side
if snake[0][0] == 0: snake[0][0] = 18
if snake[0][1] == 0: snake[0][1] = 58
if snake[0][0] == 19: snake[0][0] = 1
if snake[0][1] == 59: snake[0][1] = 1
# Exit if snake crosses the boundaries (Uncomment to enable)
#if snake[0][0] == 0 or snake[0][0] == 19 or snake[0][1] == 0 or snake[0][1] == 59: break
last = snake.pop()
win.addch(last[0], last[1], ' ')
win.addch(snake[0][0], snake[0][1], symbol)
def get_dir(first, second, dir):
""" dir should be "towards" if second should move towards first
or "away" if second should move away from first
if first is to the NW of second, xdif and ydif are neg."""
x_dif = first[1]-second[1]
y_dif = first[0]-second[0]
if abs(x_dif) >= abs(y_dif):
if dir == "towards":
if x_dif<0:
return KEY_LEFT
else:
return KEY_RIGHT
else:
if x_dif<0:
return KEY_RIGHT
else:
return KEY_LEFT
else:
if dir == "towards":
if y_dif<0:
return KEY_UP
else:
return KEY_DOWN
else:
if x_dif<0:
return KEY_DOWN
else:
return KEY_UP
def get_next_move(you, enemy, food):
if randint(0,3)==0: # move randomly 1/4 of the time
return(choice(key_choices), choice(key_choices))
else: # move in the best direction
return(get_dir(you, enemy, "towards"), get_dir(you, food, "away"))
curses.initscr()
win = curses.newwin(20, 60, 0, 0)
win.keypad(1)
curses.noecho()
curses.curs_set(0)
win.border(0)
win.nodelay(1)
key = KEY_RIGHT # Initializing values
score = 0
endgame = False
key_choices = [KEY_LEFT, KEY_RIGHT, KEY_UP, KEY_DOWN]
you = [[4,10]] # Initial snake co-ordinates
enemy = [[15,30]]
food = [[11,20]] # First food co-ordinates
win.addch(you[0][0], you[0][1], 'o')
win.addch(food[0][0], food[0][1], '*') # Prints the food
win.addch(enemy[0][0], enemy[0][1], 'X')
try:
while key != 27 and endgame == False: # While Esc key is not pressed
win.border(0)
win.addstr(0, 2, 'Score : ' + str(score) + ' ') # Printing 'Score' and
win.addstr(0, 27, " Holly's Game ")
win.timeout(520) # Increases the speed of Snake as its length increases
prevKey = key # Previous key pressed
event = win.getch()
key = key if event == -1 else event
if key == ord(' '): # If SPACE BAR is pressed, wait for another
key = -1 # one (Pause/Resume)
while key != ord(' '):
key = win.getch()
key = prevKey
continue
if key not in [KEY_LEFT, KEY_RIGHT, KEY_UP, KEY_DOWN, 27]: # If an invalid key is pressed
key = prevKey
update_anim(you, key, 'o')
if you[0] == enemy[0]:
endgame = True
if you[0] == food[0]: # When snake eats the food
food = []
score += 1
while food == []:
food = [[randint(1, 18), randint(1, 58)]] # Calculating next food's coordinates
if food in you: food = []
win.addch(food[0][0], food[0][1], '*')
enemy_move, food_move = get_next_move(you[0], enemy[0], food[0])
update_anim(enemy, enemy_move, 'X')
if you[0] == enemy[0]:
endgame = True
update_anim(food, food_move, '*') #choice(key_choices)
if you[0] == food[0]: # When snake eats the food
food = []
score += 1
while food == []:
food = [[randint(1, 18), randint(1, 58)]] # Calculating next food's coordinates
if food in you: food = []
win.addch(food[0][0], food[0][1], '*')
finally:
curses.endwin()
print("\nScore - " + str(score))
@versionctrl
Copy link

Wow! Nice game. Enjoyed both playing and going through the code.

@airusbell
Copy link

Traceback (most recent call last):
File "C:/Users/User/Desktop/my work/python test/lol.py", line 1, in
import curses
File "C:\Users\User\AppData\Local\Programs\Python\Python37-32\lib\curses_init_.py", line 13, in
from _curses import *
ModuleNotFoundError: No module named '_curses'
pls help

@sanjiv070
Copy link

Traceback (most recent call last):
File "C:/Users/sanji/.PyCharmCE2018.2/config/scratches/scratch_3.py", line 6, in
from curses import KEY_RIGHT, KEY_LEFT, KEY_UP, KEY_DOWN
ImportError: cannot import name 'KEY_RIGHT' from 'curses' (C:\Users\sanji.PyCharmCE2018.2\config\scratches\curses_init_.py)
plese help me to fix this error

@deepeshkataria3092
Copy link

Can u provide the curses module that you are using ......
As this error is happening with me
Traceback (most recent call last):
File "C:\Users\workstation228\AppData\Local\Programs\Python\Python37-32\lib_curses_init_.py", line 53, in
has_key
NameError: name 'has_key' is not defined

@xtealer
Copy link

xtealer commented Jul 11, 2019

Wow you blew my mind, never tought of it!!! :0

Copy link

ghost commented Sep 17, 2019

The curses and ncurses (new curses) libraries go back to 1980's and 90's and provide an API to create textual user interfaces (TUI). If you write a command-line application, you should consider using curses to implement functionality you could not otherwise do with standard console output. The text editor nano is a good example of a ncurses application. We will look at how to use this library in Python.

Read more about curses programming from one of the ncurses authors, Thomas E. Dickey, who also worked on xterm and lynx among other things. https://invisible-island.net/. Another author of ncurses was Eric S. Raymond, who has a bunch of awesome writings at http://www.catb.org/~esr/.

The official Python curses tutorial is really good, make sure to check it out as well at https://docs.python.org/3/howto/curses.html. The full API documentation is also available at https://docs.python.org/3/library/curses.html. There are lots of useful functions in the full API that are not covered here. I strongly encourage you to browse the full documentation. This tutorial will serve as an introduction to common tasks.

If you want to check out a simple finished project that uses Python curses, check out the issh DevDungeon project which creates a menu for choosing SSH connections.
Installation

The curses package comes with the Python standard library. In Linux and Mac, the curses dependencies should already be installed so there is no extra steps needed. On Windows, you need to install one special Python package, windows-curses available on PyPI to add support.

Needed in Windows only

python -m pip install windows-curses

You can verify everything works by running a Python interpreter and attempting to import curses. If you do not get any errors, you are in good shape.

import curses

@MRPERFECT69
Copy link

Can someone tell me where to learn Python from? Like how do I learn all these classes and what numbers, inputs, etc to use. Advises will be appreciated. Thank you.

Copy link

ghost commented Jan 29, 2020 via email

@zeusfaraji
Copy link

thanks for sharing this
i have this problem :
line 65, in
win = curses.newwin(20, 60, 0, 0)
_curses.error: curses function returned NULL

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment